State 与 props 类似,但是 State 是私有的,并且完全受控于当前组件
创建一个 class 组件
- 创建一个同名的 ES6 class 并且继承于 React.Component
- 添加一个空的 render()方法
- 在 render 中使用 this.props 替换 props
class Clock extends React.Component {
render() {
return (
<div>
<h1>Hello,world!</h1>
<h2>It is {this.props.data.toLocaleTimeString()}</h2>
</div>
)
}
}
每次组件更新时候 render 方法都会被调用,但只要在相同的 DOM 节点中渲染
向 class 组件中添加局部的 state
- 把 render()方法中的 this.props.date 替换成 this.state.date
class Clock extends React.Component {
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
)
}
}
- 添加一个 class 构造函数,然后在该函数中为 this.state 赋初值
class Clock extends React.Component {
constructor(props) {
super(props) //通过props传递到父类的构造函数中
this.state = { date: new Date() }
}
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
)
}
}
ReactDOM.render(<Clock />, document.getElementById('root'))
将生命周期方法添加到 Class 中
生命周期函数指的是在特定的时候才能运行的函数,React 有八大生命周期函数
componentWillMount 组件在被挂载的时候执行 render 之前
componentDidMount 组件挂载之后执行 render 之后,这里一般放请求数据一些异步操作
shouldComponentUpdate 无论是 props 还是 state,组件被更新前一定会执行它。它必须有返回值,它就是开关要是 false 就不更新了,它里面有两个参数第一个 nextProps,第二个 nextState . nextProps 表示下一个要传递的父数据,nextState 表示下一个 State 改变,这样子组件里面的 render 就不会重新渲染
shouldComponentUpdate 只是对本组件使用要是 false 对于 props 来说它只是渲染了 props 当父组件除了 props 以外的元素更新的话,它不会在更新.要是对于 state 来说,他不会渲染。所以加个判断会比较好
shouldComponentUpdate(nextProps,nextState) {
if(nextProps.xxx!=this.props.xxx)
{
return true
}else{
return false
}
}
- componentWillUpdate 组件被更新前,并且 shouldComponentUpdate 返回 true 执行以后
//只有shouldComponentUpdate
// 组件被更新之前,并且shouldComponentUpdate返回true执行
componentWillUpdate(){
console.log("组件更新之前")
}
- componentDidUpdate 组件更新之后
componentDidUpdate(){
console.log("组件更新之后")
}
- componentWillReceiveProps(最难理解的)
当一个组件从父组件接受了参数,只要父组件的 render 函数被重新执行了(也就是大于第一次)子组件这个生命周期函数就执行
- componentWillUnmount 组件被卸载
componentWillUnmount(){
console.log("组件被卸载");
}
- render 渲染节点的函数,里面必须有 return
render(){
return (
<h1>哈哈哈</h1>
)
}
生命周期的函数执行顺序
//第一步 componentWillMount
//第二步 componentDidMount
//第三步 render
//第四步 shouldComponentUpdate
//第五步 componentWillUpdate
//第六步 componentDidUpdate
//第七步 componentWillReceiveProps
//第八步 componentWillUnmount
更新数据的时候必须要用 this.setState()来更新组件
class Clock extends React.Component {
//构造函数
constructor(props) {
super(props)
this.state = {
date: new Date()
}
}
//更新数据 获取数据
componentDidMount() {
let _this = this
this.timeID = setInterval(function() {
_this.tick()
}, 1000)
}
//卸载组件的时候清除定时器
componentWillUnmount() {
clearInterval(this.timeID)
}
//核心函数,利用setState改变
tick() {
this.setState({
date: new Date()
})
}
}
正确的使用 setState
不要直接修改 State
- 例如:此代码不会重新渲染组件(错误)
this.state.commet = 'Hello'
- (正确)而是使用 setState()
this.setState({
commet: 'Hello'
})
构造函数是唯一可以给 this.setState()赋值的地方
State 的更新是异步的
- 因为 this.props 和 this.state 可能会异步更新,所以不要依赖他们的值来更新下一个状态
比如下面的这个无法更新计数器(错误的)
this.setState({
count: this.state.counter + this.props.increment
})
- setState 回调函数
this.setState(
{
foo: 123
},
() => {
console.log(foo)
}
)
- 所以只有在 setState()接受一个函数而不是一个对象,这个函数用上一个 state 作为第一个参数,将此次更新被应用时的 props 作为第二个参数
this.setState((state, props) => {
counter: state.counter + props.increment
})
- 上面使用了箭头函数,不过也可以使用普通函数
this.setState(function(state, props) {
return {
counter: state.counter + props.increment
}
})
数据向下流动的
不管父组件或者子组件都无法知道某个组件是有状态还是无状态的,并且它们不关心它是函数组件还是 class 组件
组件可以选择把它的 state 作为 props 向下传递到它的子组件中
<h2>It is {this.state.data.toLocaleTimeString()}</h2>
对于自定义组件同样使用
<FormatteDate date="{this.state.date}" />
总结
每一个组件里面必须要有构造函数 super(props)
生命周期函数
//第一步 componentWillMount
//第二步 componentDidMount
//第三步 render
//第四步 shouldComponentUpdate
//第五步 componentWillUpdate
//第六步 componentDidUpdate
//第七步 componentWillReceiveProps
//第八步 componentWillUnmount
- 单项数据流