我先拉拉对React-DOM
输出那篇文章的知识点,从那篇文章中得知,至今为止我们只会用ReactDOM.render()
去更改覆盖数据来进行视图更新,然而还是在时间的控制下进行变化。
现在我们要做的就是让组件自己跑起来
何为
state
?
State
是一种类似于props
的东西,属于组件元素的属性,但是它是私有的,并且完全被组件所控制,所以State
只会存在于组件中,不是组件的话,可以走开了,并且它是可变的,而prop
s这货是不可变的,这也是为什么State
可以取代props
用来实时更新视图的原因。
当然,State
只是属于类组件的,不是函数式的组件的,它被作为一个类的特性与类组件绑定起来,所以函数式组件要使用State
还需要转换为类组件,不然会很尴尬。
转换的步骤如下:
- 创建一个
ES6
的类继承于React.Component
- 增加一个简单的空函数
render()
- .将我们的函数式组件的主体放到
render()
函数中 - 在
render
中将props
替换为this.props
- 删除原先函数式组件的声明
其实上述步骤大家都懂,不多说了。
1.给类组件增加State
状态标记数据
由于我们的props
定义以后存在不可扩展和不可变性,所以用state
来取代props
进行数据更新变化,我们将一个数据要变为可变的,或者说想让props
上的数据可变,实时更新,可以通过一下两步:
1.在render
函数中,将this.props.date
替换为this.state.date
,如下:
class Cl extends React.Component {
render() {
return (
<div>
<h1>Hello,world!</h1>
<h2>It is {this.state.date.toString()}.</h2>
</div>
);
}
}
2.为类组件增加一个constructor
函数去初始化this.state
这个属性,如下:
class Cl extends React.Component {
constructor(props) {
super(props);//调用父类的构造函数
this.state = {date: new Date()};
}
render() {
return (
<div>
<h1>Hello,world!</h1>
<h2>It is {this.state.date.toString()}.</h2>
</div>
);
}
}
这里我们通过super
和props
初始化构造函数
constructor(props) { super(props); this.state = {date: new Date()};
}
2.为类组件增加生命周期方法控制
我们将通过React
挂载和卸载两个功能来实现一次Render
即可更新视图,这两种功能的表现形式分别为componentDidMount
和componentWillUnmount
,具体实例如下:
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {date: new Date()};
}
componentDidMount() {
}
componentWillUnmount() {
}
render() {
return (
<div>
<h1>Hello,world!</h1>
<h2>It is {this.state.date.toString()}.</h2>
</div>
);
}
}
componentDidMount
和componentWillUnmount
,这两个方法被俗称为生命挂钩(自己取得,代表着跟组件的创建摧毁有关),componentDidMount
函数会在我们render
一个组件元素渲染到视图上后运行,在这里我们可以建立一个定时器,如下:
componentDidMount() {
this.timerID = setInterval(
() => this.tick(),1000
);
}
componentWillUnmount
则是在对象摧毁时执行,一般用来摧毁我们在componentDidMount
中创建的定时器
componentWillUnmount() {
clearInterval(this.timerID);
}
然后我们的更新就完成了,如下:
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {
date: new Date()
};
}
componentDidMount() {
this.timerID = setInterval(
() => this.tick(),1000
);
}
componentWillUnmount() {
clearInterval(this.timerID);
}
tick() {
this.setState({
date: new Date()
});
}
render() {
return (
<div>
<h1>Hello,world!</h1>
<h2>It is {this.state.date.toString()}.</h2>
</div>
);
}
}
ReactDOM.render(
<Clock />,document.getElementById('root')
);
看到这些代码,大家就可以知道state
是实时更新的,如此来更新界面,而去掉了反复用render
处理。
当我们的
ReactDOM.render()
处理到了Clock
类组件JSX
时,React
会调用Clock
组件的构造函数constructor
,用于给this.state
数据进行初始化React
会调用Clock
的render
方法,让React
通过这个函数知道怎么将数据渲染到视图中,然后将数据渲染到DOM
上当
React
将Clock
组件的数据内嵌到DOM
中后,React
就会调用componentDidMount()
生命周期钩,就componentDidMount
中的代码而言,React
会告诉浏览器,Clock
类组件需要设定一个定时器,每秒钟调用一次tick
浏览器会每一秒钟调用
tick
函数,在tick
中有一个setState
函数,这个的作用就是告诉React
,state
对象被改变了,然后会自动调用render
函数进行重新渲染,也就是说依旧是调用render
,在上面的代码中,React
自己隐性调用的,而不是我们显性调用它。如果
Clock
组件从DOM
中移除的话,React
会调用componentWillUnmount()
来将这个定时器给摧毁掉
3.请正确的使用state
状态标记属性
很明显,state
是一个属性,也可以看成一个对象,那么一定可以进行如下设置:
this.state.date = new Date();
但是这样会非常费神,而且会造成代码冗余,为什么呢,感同身受的就是为一个标签设置css
样式,如果没有jquery
的css
函数,或者是你没有写过一个比较实用的css
处理函数,会发现一个非常懵逼的问题,就是属性设置写的代码能亮瞎你的眼,简直丑的一比。
所以我们这里要用jquery.css
函数的使用方法为state
进行设置。
this.setState({date: new Date()});
4.state
更新可能会很飘
为何这么说呢?但我们一起使用多个setState
,state
的状态就会有点飞。
就是说state
状态对象更新可能是异步的,不是同步的。
当用如下这种形式:就会出现异步情况:
this.setState({
counter: this.state.counter + this.props.increment,});
上述的操作,如果出现多条的话,会造成计算失误,也就是说多个语句执行的顺序会不同从而造成结果错误。
解决方案
用函数来代替对象处理:
this.setState((prevState,props) => ({ counter: prevState.counter + props.increment })); //------------------------------------ this.setState(function(prevState,props) { return { counter: prevState.counter + props.increment }; });
这个函数格式是固定的,必须第一个参数是state
的前一个状态,第二个参数是属性对象props
,这两个对象setState
会自动传递到函数中去,同时,这些函数在setState
中的执行是同步的,从而解决了异步问题。
5.确保底层组件的透明性
组件之间耦合性越低越好,换句话说,不管是父组件还是子组件,都不知道对方是个什么鬼,不知道对方是函数式组件还是类组件,每一个组件都自我封装,只留下一个借口进行对外交互,同时只有父组件知道子组件会干啥,需要传递什么东西给子组件,而子组件却不知道父组件干了什么,可能传递了props
,或者state
又或是直接明了的数据,他只进行处理数据,不管数据到底怎么来的。
上述这种透明形式,官方成为自上而下,单向数据流,上层只能控制下一层的数据,无法对上层产生任何影响。
简单地说,水往低处流。
此篇博客设计的ES6
的箭头函数如果大家不是很明白可以参考官方网站,当然之后,个人可能会一套ES6
学习的博客,敬请期待
原文链接:https://www.f2er.com/react/304579.html下一篇会将
React
的事件处理机制