七天接手react项目 —— state事件处理ref

State 与 props 类似,但是 state私有的,并且完全受控于当前组件 —— 官网

react 中的 props 用来接收父组件传来的属性,并且是只读的。

由此,我们能猜测 state 就是组件自身属性。

Tip:是否感觉像 vue 组件中的 data,请接着看!

var app = new Vue({ ... // 状态 data: { message: 'Hello Vue!', seen: true } }) 初步体验

这是一个官方示例:

class Clock extends React.Component { constructor(props) { super(props) // 这里等于 super() 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') );

网页显示:

Hello, world! // 当前时间 It is 11:20:26.

Tip:toLocaleTimeString() 方法返回该日期对象时间部分的字符串,该字符串格式因不同语言而不同

如果不初始化 state 或不进行方法绑定,则不需要为 React 组件实现构造函数 —— 官网_

由此可以猜测 state 能在构造函数中初始化。那么必须调用 super() 不?请看示例:

constructor() { // super() console.log('this', this) this.state = { date: new Date() }; }

浏览器控制台报错如下:

Uncaught ReferenceError: this hasn't been initialised - super() hasn't been called

Tip:在构造函数中访问 this 之前,一定要调用 super(),它负责初始化 this,如果在调用 super() 之前访问 this 会导致程序报错 —— 类 (class)_继承

不要直接修改 State

不要直接修改 State ——官网-

假如我们直接修改 state 会发生什么?请看示例:

class Clock extends React.Component { constructor() { super() this.state = { date: new Date() } setInterval(() => { // 直接修改 state this.state.date = new Date() console.log(this.state.date) }, 1000) } render() { // ... 不变 } }

我们期望每过一秒,时间都能更新。但现实是,页面内容静止不变,但控制台输出的时间却在改变:

// 页面输出 Hello, world! It is 16:07:00. // 控制台输出 Mon Mar 14 2022 16:07:01 GMT+0800 (中国标准时间) Mon Mar 14 2022 16:07:02 GMT+0800 (中国标准时间) Mon Mar 14 2022 16:07:03 GMT+0800 (中国标准时间) Mon Mar 14 2022 16:07:04 GMT+0800 (中国标准时间) ...

Tip:我们可以通过 forceUpdate() 方法来强制更新,但我们通常不会这样使用。vue 也有一个类似的方法 vm.$forceUpdate()

setInterval(() => { this.state.date = new Date() console.log(this.state.date) // 强制更新。通常不用 + this.forceUpdate() }, 1000) setState 通过 setState() 修改 state

继续上面的例子,让 Clock 组件在页面中每过一秒都会自动更新时间:

class Clock extends React.Component { constructor(props) { super(props) this.state = { date: new Date() } // bind() 方法会返回一个新的函数,里面绑定 this,否则 tick() 报错如下: // Uncaught TypeError: this.setState is not a function setInterval(this.tick.bind(this), 1000) } tick() { // 通过 setState 修改 state this.setState({ date: new Date() }) } render() { // ... 不变 } }

页面显示:

Hello, world! It is 15:07:06. // 一秒后显示 Hello, world! It is 15:07:07. 合并还是替换

当你调用 setState() 的时候,React 会把你提供的对象合并到当前的 state —— 官网_“State 的更新会被合并”

这个不难证明。请看示例:

class Clock extends React.Component { constructor() { super() this.state = { date: new Date(), name: 'pengjili' } setInterval(this.tick.bind(this), 1000) } tick() { // state 初始化时是两个属性,现在是一个属性 this.setState({ date: new Date() }) } render() { return ( <div> <h1>Hello, world! {this.state.name}</h1> <h2>It is {this.state.date.toLocaleTimeString()}.</h2> </div> ); } }

页面显示:

// 每秒时间都会改变,但 `pengjiali` 一直显示 Hello, world! pengjili It is 15:20:24.

倘若是替换,pengjiali 就为空了。

State 的更新可能是异步的

出于性能考虑,React 可能会把多个 setState() 调用合并成一个调用

例如,调整购物车商品数:

this.setState({quantity: 2})

在同一周期内会对多个 setState 进行批处理,如果在同一周期内多次设置商品数量增加,则相当于:

Object.assign( previousState, {quantity: state.quantity + 1}, {quantity: state.quantity + 1}, ... )

后调用的 setState() 将覆盖同一周期内先调用 setState 的值,因此商品数仅增加一次。

因此,如果后续状态取决于当前状态,建议使用函数的形式代替:

this.setState((state, props) => { return {quantity: state.quantity + 1}; })

这个函数用上一个 state 作为第一个参数,将此次更新被应用时的 props 做为第二个参数。

render() 执行几次

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zzgydf.html