React入门笔记(四):React生命周期、插槽、路由
# 五、React生命周期
# 5.1、钩子函数
生命周期即是组件从实例化到渲染到最终从页面销毁,整个过程就是生命周期,在这个生命周期中,我们有许多可以调用的事件,我们也俗称为钩子函数
生命周期的三个状态:
Mounting
:将组件插入到dom
中- 将数据更新到
dom
中 unmounting
:将组件移除dom
生命周期中的钩子函数(方法或事件)
ComponentWillMount
:组件将要渲染,Ajax,添加动画前的类ComponentDidMount
:组件渲染完毕,添加动画ComponentWillReceiveProps
:组件将要接收props数据,查看接收的props数据是什么ShouldComponentUpdate
:组件接收到新的state或者props,判断是否要更新,返回布尔值ComponentWillUpdate
:组件将要更新ComponentDidUpdate
:组件已经更新ComponentWillUnmount
:组件将要卸载
import React, { Component } from "react";
import ReactDOM from "react-dom";
class ComLife extends Component {
constructor(props) {
super(props);
this.state = {
msg: "你好",
};
console.log("constructor构造函数");
}
componentWillMount() {
console.log("componentWillMount组件将要渲染");
}
componentDidMount() {
console.log("componentDidMount组件渲染完毕");
}
componentWillReceiveProps() {
console.log("componentWillReceiveProps组件将要接受新的状态state和props");
}
shouldComponentUpdate() {
//如果希望更新就返回为真,不希望更新就返回为false
console.log("进行判断是否要更新");
if (this.state.msg === "你好") {
return true;
} else {
return false;
}
}
componentWillUpdate() {
console.log("componentWillUpdate组件将要更新");
}
componentDidUpdate() {
console.log("componentDidUpdate组件更新完毕");
}
componentWillUnmount() {
console.log("componentWillUnmount组件将要移除");
}
changeMsg = () => {
this.setState({
msg: "你好,陈",
});
};
render() {
console.log("render渲染函数");
return (
<div>
<h1>{this.state.msg}</h1>
<button onClick={this.changeMsg}>组件更新</button>
</div>
);
}
}
class ParentCom extends Component {
constructor(props) {
super(props);
this.state = {
isShow: true,
};
}
removeCom = () => {
this.setState({
isShow: false,
});
};
render() {
if (this.state.isShow) {
return (
<div>
<button onClick={this.removeCom}>移除ComLife</button>
<ComLife />
</div>
);
} else {
return <h1>将ComLif移除</h1>;
}
}
}
ReactDOM.render(<ParentCom />, document.getElementById("root"));
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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# 六、React插槽
# 6.1、插槽介绍
在组件中写入内容,这些内容可以被识别和控制。react需要自己开发支持插槽功能。
# 6.2、使用props.children实现插槽
原理:组件中写入的HTML可以传入到props
中
import React, { Component } from "react";
import ReactDOM from "react-dom";
class ParentCom extends Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<h1>组件插槽</h1>
{this.props.children}
</div>
);
}
}
ReactDOM.render(
<ParentCom>
<h2>子组件1</h2>
<h2>子组件2</h2>
<h2>子组件3</h2>
</ParentCom>,
document.getElementById("root")
);
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
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
插槽也可以获取元素
的值:
import React, { Component } from "react";
import ReactDOM from "react-dom";
class ParentCom extends Component {
render() {
console.log(this.props);
return (
<div>
<h1>组件插槽</h1>
{this.props.children}
</div>
);
}
}
class RootCom extends Component {
constructor(props) {
super(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.getElementById("root"));
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
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
在做一个小例子,通过获取插槽内元素的值来动态的判断div放置的位置:
import React, { Component } from "react";
import ReactDOM from "react-dom";
class ParentCom extends 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 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 Component {
constructor(props) {
super(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.getElementById("root"));
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
72
73
74
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
72
73
74
组件中的HTML直接可全部插入,也可以通过条件判断来决定插入的位置
# 七、React路由
# 7.1、路由介绍
根据不同的路径,显示不同的组件(内容):React使用的库:react-router-dom
:
安装:
yarn add react-router-dom 或 npm install --save add react-router-dom
1
# 7.2、路由三大组件
- Router:所有路由组件的根组件(底层组件),包裹路由规则的最外层容器
- Route:路由规则匹配组件,显示当前规则对应的组件
- Link:路由跳转的组件
注意:如果要精确匹配,那么可以在Route
上设置exact
属性
使用history模式
制作一个建议的导航:
import React, { Component } 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>首页</h1>
</div>
)
}
function Me(){
return(
<div>
<h1>个人中心</h1>
</div>
)
}
function Product(){
return(
<div>
<h1>产品页面</h1>
</div>
)
}
class App extends Component{
render(){
return(
<div id="app">
<Router basename="/admin">
<div className="nav">
<Link to="/">Home</Link>
<Link to="/product">Product</Link>
<Link to="/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;
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
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
可以通过设置basename
来规定根路径,也可以使用exact
来达到精确匹配,Router
可以在一个组件写多个
import React, { Component } 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 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>
{/* <div className="nav">
<Link to="/">Home</Link>
<Link to="/product">Product</Link>
<Link to="/me">个人中心</Link>
</div> */}
<Route path="/admin/" exact component={Home}></Route>
<Route path="/admin/product" component={Product}></Route>
<Route path="/admin/me" exact component={Me}></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
46
47
48
49
50
51
52
53
54
55
56
57
58
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
Link
组件中的to
可以直接写路径,也可以通过对象,进行更详细的配置
render() {
let meObj = {
pathname: "/me",//跳转的路径
search: "?username=admin",//get请求的参数
hash: "#abc",//设置的hash值
state: { msg: "hello" },//传入组件的数据
};
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>
<div className="nav">
<Link to="/">Home</Link>
<Link to="/product">Product</Link>
<Link to={meObj}>个人中心</Link>
</div>
<Route path="/admin/" exact component={Home}></Route>
<Route path="/admin/product" component={Product}></Route>
<Route path="/admin/me" exact component={Me}></Route>
</Router>
</div>
);
}
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
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
Link的replace
属性,点击链接后,将新地址替换成历史访问记录的原地址
<Link to={meObj} replace>个人中心</Link>
1
2
2
# 7.3、动态路由实现
function News(props){
console.log(props)
return(
<div>
新闻页
新闻id:{props.match.params.id}
</div>
)
}
...
<Router>
<div className="nav">
<Link to="/">Home</Link>
<Link to="/product">Product</Link>
<Link to="/news/456789">新闻页面</Link>
<Link to={meObj} replace>个人中心</Link>
</div>
<Route path="/admin/" exact component={Home}></Route>
<Route path="/admin/product" component={Product}></Route>
<Route path="/admin/me" exact component={Me}></Route>
<Route path="/news/:id" component={News}></Route>
</Router>
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 7.4、重定向组件
如果访问访问某个组件时,如果有重定向组件,那么就会修改页面路径,使得页面的内容显示为所定向路径的内容:
import React, { Component } from "react";
// hash模式
// import {HashRouter as Router,Link,Route} from 'react-router-dom'
// history模式 后端配合使用
import {
BrowserRouter as Router,
Link,
Route,
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:"/login_info",
state:{
loginState:"success"
}
}
return (
<div>
<h1>表单验证</h1>
<Link to={pathObj}>登陆验证后页面</Link>
</div>
);
};
class App extends 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="/login_info" exact component={LoginInfo}></Route>
<Route path="/admin" exact component={() => <h1>admin页,登录成功</h1>}></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
46
47
48
49
50
51
52
53
54
55
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
# 7.5、Switch组件
让Switch
组件内容的route
只匹配一个,只要匹配到了,剩余的路由规则将不被匹配
render() {
return (
<div>
<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="/login_info" exact component={LoginInfo}></Route>
<Route path="/admin" exact component={() => <h1>admin页,登录成功</h1>}></Route>
<Route path="/abc" exact component={() => <h1>abc1</h1>}></Route>
<Route path="/abc" exact component={() => <h1>abc2</h1>}></Route>
</Switch>
</Router>
</div>
);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 7.6、使用js跳转页面
使用props
的histroy
中的属性和方法来进行页面路由的跳转:
class ChildCom extends Component{
clickEvent = () =>{
//console.log(this.props)
this.props.history.push('/',{msg:"这是由ChildCom发给首页的数据"})
this.props.history.replace('/',{msg:"这是由ChildCom发给首页的数据"})
//前进
this.props.history.go(1)
this.props.history.goForward(1)
//后退
this.props.history.go(-1)
this.props.history.goBack(-1)
}
render(){
return(
<div>
<button onClick={this.clickEvent}>跳转到首页</button>
</div>
)
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
props.match
可以获取到动态路由传递的参数:
<Route path="/:id" exact component={(props) => {console.log(props); return (<h1>首页</h1>)}}></Route>
1
编辑 (opens new window)
上次更新: 2022/08/26, 15:52:02