React入门笔记(三):React状态、事件绑定
# 四、React状态
# 4.1、React的state
react的state相较于props它可以对状态进行更改,这也是react中很重要的一个部分。在类组件中它在construor函数中定义:
constructor(props) {
super(props);
//状态(数据) -- view
//构造函数初始化数据,将需要改变的数据初始化到state中
this.state = {
time: new Date().toLocaleTimeString(),
};
}
2
3
4
5
6
7
8
要调用state中的状态,只需要this.state.你的变量
:
render() {
// this.state.time = new Date().toLocaleTimeString();
return (
<div>
<h1>当前时间:{this.state.time}</h1>
</div>
);
}
2
3
4
5
6
7
8
想要给state赋值请勿直接赋值state,通过setState
函数来进行状态的更改,直接赋值并不会出发react的dom更新。通过setState函数来进行状态的更改并不会立即修改DOM里的内容,他会在所有设置状态改变之后统一对比虚拟dom。
这里是一个时钟的demo,通过setInterval
来不断进行状态更新:
import React from "react";
import ReactDOM from "react-dom";
class Clock extends React.Component {
constructor(props) {
super(props);
//状态(数据) -- view
//构造函数初始化数据,将需要改变的数据初始化到state中
this.state = {
time: new Date().toLocaleTimeString(),
};
}
render() {
// this.state.time = new Date().toLocaleTimeString();
return (
<div>
<h1>当前时间:{this.state.time}</h1>
</div>
);
}
//生命周期函数,组件渲染完成时的函数
componentDidMount(){
//请勿直接赋值state,通过setState函数来进行状态的更改
//通过setState函数来进行状态的更改并不会立即修改DOM里的内容,他会在所有设置状态改变之后统一对比虚拟dom
setInterval(()=>{
this.setState({
time:new Date().toLocaleTimeString()
})
},1000)
}
}
ReactDOM.render(<Clock/>,document.getElementById('root'));
// setInterval(() => {
// ReactDOM.render(<Clock />, document.getElementById("root"));
// }, 1000);
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
# 4.2、事件的绑定
除了状态,我们还需要一些事件,react中的事件和原生的函数写法没有不同,但是在jsx中调用事件需要做好事件this
绑定,this的绑定可以在construor
中实现,this.function = this.function.bind(this);
或者在调用的时候使用箭头函数,这样你就不用担心this的指向问题,统一指向class:
render() {
return (
<div>
<button data-index="1" onClick={(e)=>this.clickEvent(e)}>
内容1
</button>
<button data-index="2" onClick={(e)=>this.clickEvent(e)}>
内容2
</button>
<div className={this.state.c1}>
<h1>内容1</h1>
</div>
<div className={this.state.c2}>
<h1>内容2</h1>
</div>
</div>
);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
这里我们做一个demo,利用之前学过的state来做一个点击按钮切换页面的事件,在这个例子中我们还在标签中使用的data-index
的属性,它可以通过e.target.dataset.index
获得具体的值,从而实现判断由那个按钮获得的元素,从而实现切换的效果:
import React from "react";
import ReactDOM from "react-dom";
import "./Tab.css";
class Tab extends React.Component {
constructor(props) {
super(props);
this.state = {
c1: "content active",
c2: "content",
};
//this.clickEvent = this.clickEvent.bind(this);
}
clickEvent(e) {
console.log(e.target.dataset.index);
let index = e.target.dataset.index;
if (index === "1") {
this.setState({
c1: "content active",
c2: "content",
});
} else {
this.setState({
c1: "content",
c2: "content active",
});
}
}
render() {
return (
<div>
<button data-index="1" onClick={(e)=>this.clickEvent(e)}>
内容1
</button>
<button data-index="2" onClick={(e)=>this.clickEvent(e)}>
内容2
</button>
<div className={this.state.c1}>
<h1>内容1</h1>
</div>
<div className={this.state.c2}>
<h1>内容2</h1>
</div>
</div>
);
}
}
ReactDOM.render(<Tab />, document.getElementById("root"));
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
# 4.3、Props传值
父传递给子组件数据,子不能传给父,props传值可以是任意的类型,props可以设置默认值
注意:props可以传递函数,props可以传递父元素的函数,就可以修改父元素的状态state,从而达到传递数据给父元素
这个例子通过父传子实现控制效果:
import React from "react";
import ReactDOM from "react-dom";
import './01props.css'
//即在父元素使用state去控制子元素的props从而达到父元素传递数据给子元素
class ParentCom extends React.Component{
constructor(props){
super(props)
this.state = {
isActive:true
}
}
changeShow(){
this.setState({
isActive:!this.state.isActive
})
}
render(){
return(
<div>
<button onClick={(e)=>this.changeShow(e)}>控制子元素显示</button>
<ChildCom isActive={this.state.isActive}/>
</div>
)
}
}
class ChildCom extends React.Component{
constructor(props){
super(props)
}
render(){
let strClass = null;
if(this.props.isActive){
strClass = ' active'
}else{
strClass = ''
}
return (
<div className={"content"+strClass}>
<h1>子元素</h1>
</div>
)
}
}
ReactDOM.render(<ParentCom/>,document.getElementById('root'))
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
.content{
width: 400px;
height: 400px;
background-color: skyblue;
display: none;
}
.content.active{
display: block;
}
2
3
4
5
6
7
8
9
10
子传递父的数据:调用父元素的函数从而操作父元素的数据,从而实现数据从子元素传递至父元素,下列代码实现了点击子类的按钮,将子类的state数据通过父类传递给子类的props函数
来实现修改父类的数据:
import React from "react";
import ReactDOM from "react-dom";
//实现子传父
class Parent extends React.Component{
constructor(props){
super(props)
this.state = {
parentData:null
}
}
setParentData = (data) =>{
this.setState({
parentData:data
})
}
render(){
return(
<div>
<h1>子元素传递给父元素的数据:{this.state.parentData}</h1>
<ChildCom setParentData={this.setParentData}/>
</div>
)
}
}
class ChildCom extends React.Component{
constructor(props){
super(props)
this.state = {
msg:'helloworld'
}
}
sendData(){
console.log(this.state.msg)
//将子元素传递给到父元素,实际就是调用父元素传递进来的函数
this.props.setParentData(this.state.msg)
}
render(){
return(
<div>
<button onClick={(e)=>this.sendData(e)}>传递helloworld给父元素</button>
<button onClick={()=>this.props.setParentData('直接传递')}>直接传递helloworld给父元素</button>
</div>
)
}
}
ReactDOM.render(<Parent/>,document.getElementById('root'))
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
# 4.4、react事件
特点:
- 事件绑定采用驼峰命名
- 使用
{}
传入一个函数
事件对象:react返回的事件对象是代理的原生事件对象,如果想要查看事件对象的具体值,必须直接输出事件对象的属性。原生,组织默认行为时,可以直接返回return false,但是react不行,可以使用preventDefault来阻止:
import React from "react";
import ReactDOM from "react-dom";
class ParentCom extends React.Component {
constructor(props) {
super(props);
}
parentEvent = (e) => {
console.log(e);
e.preventDefault()
};
render() {
return (
<div>
<form action="http://baidu.com">
<div className="child">
<h1>你好</h1>
<button onClick={this.parentEvent}>提交</button>
</div>
</form>
</div>
);
}
}
ReactDOM.render(<ParentCom />, document.getElementById("root"));
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
React中阻止默认事件必须使用e.preventDefault()
但是react的事件调用如果带参数传递,需要使用匿名(箭头)函数的方式,否则他会在渲染的时候不需要点击直接调用函数,实现的方法如下:
<button onClick={(e)=>{this.parentEvent1('123',e)}}>提交</button>
...
parentEvent1 = (msg,e) => {
console.log(msg);
console.log(e);
};
2
3
4
5
6
# 4.5、条件渲染
react中条件渲染即和JavaScript中的条件运算,如if...else,三元运算符等相同。
1.直接通过条件运算返回要渲染的js对象
import React from "react";
import ReactDOM from "react-dom";
function UserGreet(props){
return (
<h1>欢迎登录</h1>
)
}
function UserLogin(props){
return(
<h1>请先登录</h1>
)
}
class ParentCom extends React.Component{
constructor(props){
super(props)
this.state = {
isLogin:true
}
}
render(){
let element = null
this.state.isLogin ? element = <UserGreet/> : element = <UserLogin/>
return element
}
}
ReactDOM.render(<ParentCom />, document.getElementById("root"));
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
2.通过条件运算得出jsx对象,再将jsx对象渲染到模板中
import React from "react";
import ReactDOM from "react-dom";
function UserGreet(props) {
return <h1>欢迎登录</h1>;
}
function UserLogin(props) {
return <h1>请先登录</h1>;
}
class ParentCom extends React.Component {
constructor(props) {
super(props);
this.state = {
isLogin: true,
};
}
render() {
let element = null;
this.state.isLogin ? (element = <UserGreet />) : (element = <UserLogin />);
return (
<div>
<header>
<h1>这是头部</h1>
</header>
<section>{element}</section>
{this.state.isLogin?<UserGreet></UserGreet>:<UserLogin></UserLogin>}
<footer>
<h1>这是尾部</h1>
</footer>
</div>
);
}
}
ReactDOM.render(<ParentCom />, document.getElementById("root"));
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
# 4.6、列表渲染
不能通过循环直接输出模板,需要通过数组的形式将数组的内容放置到模板中,将数据拼装成jsx
数组对象
import React from "react";
import ReactDOM from "react-dom";
let arr = ["陈昀昊","方胖胖","班长"]
function Welcome(props){
return(
<div>
<ul>
{arr.map((list,i)=>{
return <li key={i}>{list}</li>
})}
</ul>
</div>
)
}
ReactDOM.render(<Welcome />, document.getElementById("root"));
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import React from "react";
import ReactDOM from "react-dom";
class Welcome extends React.Component {
constructor(props) {
super(props);
this.state = {
list: [
{
title: "第一节 React事件",
content: "实践内容",
},
{
title: "第二节 React数据传递",
content: "实践内容",
},
{
title: "第三节 条件渲染",
content: "实践内容",
},
],
};
}
render() {
return (
<div>
<h1>今天的课程内容</h1>
<ul>
{this.state.list.map((list, i) => {
return (
<li key={i}>
<h3>{list.title}</h3>
<p>{list.content}</p>
</li>
);
})}
</ul>
</div>
);
}
}
ReactDOM.render(<Welcome />, document.getElementById("root"));
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
在使用数组的map方法对每一项数据按照jsx的形式对数据进行加工,最后得到一个每一项都是jsx形式的数组,再将数组渲染到模板中,key值需要放置到每一项中,封装成组件,key的是在组件上的:
import React from "react";
import ReactDOM from "react-dom";
function ListItem(props) {
return (
<li key={props.index}>
<h3>{props.data.title}</h3>
<p>{props.data.content}</p>
</li>
);
}
class Welcome extends React.Component {
constructor(props) {
super(props);
this.state = {
list: [
{
title: "第一节 React事件",
content: "实践内容",
},
{
title: "第二节 React数据传递",
content: "实践内容",
},
{
title: "第三节 条件渲染",
content: "实践内容",
},
],
};
}
render() {
let listAtr = this.state.list.map((list, i) => {
return <ListItem key={i} data={list} index={i}></ListItem>;
});
return (
<div>
<h1>今天的课程内容</h1>
<ul>{listAtr}</ul>
</div>
);
}
}
ReactDOM.render(<Welcome />, document.getElementById("root"));
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
再与事件绑定案例结合一下:
import React from "react";
import ReactDOM from "react-dom";
class ListItem2 extends React.Component {
constructor(props) {
super(props);
}
clickEvent = (index, title, event) => {
alert(index + "-" + title);
};
render() {
return (
<li
onClick={(e) => this.clickEvent(
this.props.index,
this.props.data.title,
e)}
key={this.props.index}
>
<h3>{this.props.data.title}</h3>
<p>{this.props.data.content}</p>
</li>
);
}
}
class Welcome extends React.Component {
constructor(props) {
super(props);
this.state = {
list: [
{
title: "第一节 React事件",
content: "实践内容",
},
{
title: "第二节 React数据传递",
content: "实践内容",
},
{
title: "第三节 条件渲染",
content: "实践内容",
},
],
};
}
render() {
let listAtr = this.state.list.map((list, i) => {
return <ListItem2 key={i} data={list} index={i}></ListItem2>;
});
return (
<div>
<h1>今天的课程内容</h1>
<ul>{listAtr}</ul>
</div>
);
}
}
ReactDOM.render(<Welcome />, document.getElementById("root"));
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