您的位置:首页 > Web前端 > React

React学习之State与生命周期基友情(四)

2017-03-16 19:17 155 查看
我先拉拉对
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
学习的博客,敬请期待

下一篇会将
React
的事件处理机制
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: