React-Learning-day04

React插槽

组件中写入内容,这些内容可以被识别和控制。React需要自己开发支持插槽功能。

原理:
组件中写入的HTML,可以传入到props中。

组件中的HTML内容可以直接全部插入。也可以,组件中根据HTML内容的不同,插入的位置不同。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
import React from "react";
import ReactDOM from "react-dom";

class ParentCom extends React.Component {
render() {
console.log(this.props);
return (
<div>
<h1>组件插槽</h1>
{this.props.children}
<ChildCom>
<h1 data-position="header">这是放置到头部的内容</h1>
<h1 data-position="main">这是放置到主要的内容</h1>
<h1 data-position="footer">这是放置到尾部的内容</h1>
</ChildCom>
</div>
);
}
}

class ChildCom extends React.Component {
render() {
let headerCom, mainCom, footerCom;
this.props.children.forEach((item, index) => {
if (item.props["data-position"] === "header") {
headerCom = item;
} else if (item.props["data-position"] === "main") {
mainCom = item;
} else {
footerCom = item;
}
});
return (
<div>
<div className="header">{headerCom}</div>
<div className="main">{mainCom}</div>
<div className="footer">{footerCom}</div>
</div>
);
}
}

class RootCom extends React.Component {
constructor(props) {
super(props);
// console.log(props);
this.state = {
arr: [1, 2, 3],
};
}
render() {
return (
<ParentCom>
<h2 data-name="a" data-index={this.state.arr[0]}>
子组件1</h2>
<h2 data-name="b" data-index={this.state.arr[1]}>
子组件2</h2>
<h2 data-name="c" data-index={this.state.arr[2]}>
子组件3</h2>
</ParentCom>
);
}
}

ReactDOM.render(<RootCom></RootCom>, document.querySelector("#root"));

React路由

根据不同的路径,显示不同的组件(内容);React使用的库react-router-dom;
安装:

1
cnpm install react-router-dom -save

ReactRouter 三大组件

  • Router:所有路由组件的根组件(底层组件),包裹路由规则的最外层容器。
    属性:basename>设置此路由根路径,router可以在一个组件中写多个。
  • Route:路由规则匹配组件,显示当前规则对应的组件。
  • Link:路由跳转的组件。

注意:如果要精确匹配,那么可以在route上设置exact属性。
使用案例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
import React from "react";
//hash模式
//import {HashRouter as Router,Link,Route} from 'react-router-dom'

//history模式/后端配合使用
import { BrowserRouter as Router, Link, Route } from "react-router-dom";

function Home() {
return (
<div>
<h1>admin首页</h1>
</div>
);
}

function Me() {
return (
<div>
<h1>admin个人中心</h1>
</div>
);
}

function Product() {
return (
<div>
<h1>admin产品页面</h1>
</div>
);
}

class App extends React.Component{
render() {
return (
<div id="app">
<div>所有页面都显示的普通内容</div>
<Router>
<Route path="/" exact component={()=>(<div>首页</div>)}></Route>
<Route path="/me" component={()=>(<div>个人中心</div>)}></Route>
<Route path="/product" component={()=>(<div>产品页面</div>)}></Route>
</Router>

<Router basename="/admin">
<div className="nav">
<Link to="/">Home </Link>
<Link to="/product">Product </Link>
<Link to="/me">Me </Link>
</div>
<Route path="/" exact component={Home}></Route>
<Route path="/product" component={Product}></Route>
<Route path="/me" component={Me}></Route>
</Router>
</div>
)
}
}

export default App;

Link组件可以设置to属性,来进行页面的跳转,to属性可以直接写路径的字符串,也可以通过1个对象进行路径的设置,如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class App extends React.Component{
render() {
let meObj = {
pathname: "/me",//跳转的路径
search: "?username=admin",//get请求参数
hash: "#abc",//设置的HASH值
state: { msg: "helloworld" },//传入组件的数据
};

return (
<div id="app">

<Router>
<div className="nav">
<Link to="/">Home </Link>
<Link to="/product">Product </Link>
<Link to={ meObj }>Me </Link>
</div>
<Route path="/" exact component={Home}></Route>
<Route path="/product" component={Product}></Route>
<Route path="/me" component={Me}></Route>
</Router>
</div>
)
}
}

Link的replace属性:点击链接后,将新地址替换成历史访问记录的原地址。

动态路由的实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
import React from "react";
//hash模式
//import {HashRouter as Router,Link,Route} from 'react-router-dom'

//history模式/后端配合使用
import { BrowserRouter as Router, Link, Route } from "react-router-dom";

function Home() {
return (
<div>
<h1>admin首页</h1>
</div>
);
}

function Me(props) {
console.log(props)
return (
<div>
<h1>admin个人中心</h1>
</div>
);
}

function Product() {
return (
<div>
<h1>admin产品页面</h1>
</div>
);
}

function News(props) {
console.log(props)
return (
<div>
新闻页面,新闻id:{props.match.params.id}
</div>
)
}

class App extends React.Component{
render() {
let meObj = {
pathname: "/me",//跳转的路径
search: "?username=admin",//get请求参数
hash: "#abc",//设置的HASH值
state: { msg: "helloworld" },//传入组件的数据
};

return (
<div id="app">

<Router>
<div className="nav">
<Link to="/">Home </Link>
<Link to="/product">Product </Link>
<Link to={ meObj } replace>Me </Link>
<Link to="/news/456789">News </Link>
</div>
<Route path="/" exact component={Home}></Route>
<Route path="/product" component={Product}></Route>
<Route path="/me" component={Me}></Route>
<Route path="/news/:id" component={News}></Route>
</Router>
</div>
)
}
}

export default App;

重定向组件
如果访问某个组件时,如果有重定向组件,那么就会修改页面路径,是的页面的内容显示为所定向路径的内容。

案例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import React from "react";
import {BrowserRouter as Router,Route,Link,Redirect} from 'react-router-dom'

function LoginInfo(props) {
// props.loginState = 'success';
// props.loginState = 'fail';
if (props.location.state.loginState === 'success') {
return <Redirect to="/admin"></Redirect>
} else {
return <Redirect to="/login"></Redirect>
}
}

let FormCom = () => {
let pathObj = {
pathname: "/logininfo",
state: {
loginState: 'success'
}
}
return (
<div>
<h1>表单验证</h1>
<Link to={pathObj}>登陆验证页面</Link>
</div>
);
}

class App extends React.Component{
render() {
return (
<div>
<Router>
<Route path="/" exact component={() => <h1>首页</h1>}></Route>
<Route path="/form" exact component={FormCom}></Route>
<Route path="/login" exact component={() => <h1>登陆页</h1>}></Route>
<Route path="/logininfo" exact component={LoginInfo}></Route>
<Route path="/admin" exact component={() => <h1>admin页面,登陆成功</h1>}></Route>
</Router>
</div>
);
}
}

export default App;

Switch组件
让Switch组件内容的route只匹配1个,只要匹配到了,剩余的路由规则将不再匹配。

案例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<Router>
<Switch>
<Route path="/" exact component={() => <h1>首页</h1>}></Route>
<Route path="/form" exact component={FormCom}></Route>
<Route
path="/login"
exact
component={() => <h1>登陆页</h1>}
></Route>
<Route path="/logininfo" exact component={LoginInfo}></Route>
<Route
path="/admin"
exact
component={() => <h1>admin页面,登陆成功</h1>}
></Route>
<Route
path="/abc"
exact
component={() => <h1>abc 1页面,登陆成功</h1>}
></Route>
<Route
path="/abc"
exact
component={() => <h1>abc 2页面,登陆成功</h1>}
></Route>
</Switch>
</Router>

Redux

解决React数据管理(状态管理),用于中大型项目,数据比较庞大,组件之间数据交互多的情况下使用。如果你不知道是否需要使用Redux,那么你就不需要用它!

  • 解决组件的数据通信。
  • 解决数据和交互较多的应用。

React只是一种状态管理的解决方案!

Store:数据仓库,保存数据的敌方。
State:State是一个对象,数据仓库中的所有数据,都放到一个State里。
Action:一个动作,触发数据改变的方法。
Dispatch:将动作触发成方法。
Reduce:是一个函数,通过获取动作,改变数据,生成一个新的状态State,从而改变页面。

安装:

1
npm install redux -save
  • 初始化数据
    1
    2
    const store = createStore(reducer)
    reducer有两个作用:1、初始化数据;2、改变数据
  • 获取数据
    1
    let state = store.getState()
  • 修改数据(通过动作修改数据)
    1
    store.dispatch({type: "add", content: {id: 1, msg: "helloworld"}})
  • 修改视图(监听数据的变化,重新渲染内容)
    1
    2
    3
    store.subscribe(()=>{
    ReactDOM.render(<Counter />, document.querySelector('#root'))
    })

React-redux

安装
npm install react-redux –save

概念:
Provider组件:自动的将store里的state和组件进行关联。
MapStateProps:这个函数用于将store的state映射到组件的props里。
mapdispatchToProps:将store中的dispatch映射到组件的props里,实现了方法的共享。
Connect方法:将组件和数据(方法)进行连接。

使用:
初始化数据
数据的获取
将state映射到数组里,将修改数据的方法映射到组件的props中。