内容简介:我们要认识到,React中的组件其实是一个函数,所以state是函数内部的私有变量,外部其他组件或者方法都是无法直接访问到内部的state。 而state主要被设计用于维持组件内部私有状态。初始化state需要在class中在这个代码中,我们初始化了
我们要认识到,React中的组件其实是一个函数,所以state是函数内部的私有变量,外部其他组件或者方法都是无法直接访问到内部的state。 而state主要被设计用于维持组件内部私有状态。
3.1.1 初始化state
初始化state需要在class中 constructor
进行。
import React, { PureComponent } from 'react' export default class index extends PureComponent { constructor(props){ super(props) this.state = {name:'demo react',time:new Date()} } render() { return ( <div> Hello world React!{this.state.name} <p>组件生成时间:{this.state.time}</p> </div> ) } } 复制代码
在这个代码中,我们初始化了 name
, time
两个state值。一旦state初始化完成,我们就可以在render中进行访问。
使用 npm run dev
命令运行,并在浏览器中打开查看吧。
3.1.2 修改state值setState
我们已经知道了如何初始化组件中的state值,那么接下来我们来看看,如何实现修改state的值
import React, { PureComponent } from 'react' export default class index extends PureComponent { constructor(props){ super(props) this.state = {name:'demo react',time:+new Date()} } handleUpdateName () { this.state.time = (+new Date()) } render() { return ( <div> Hello world React!{this.state.name} <p>组件生成时间:{this.state.time}</p> <button onClick={this.handleUpdateName.bind(this)}>修改值</button> </div> ) } } 复制代码
有些动作快的同学,第一个想法就是如此修改组件中的 state
值,但是值得玩味的是,值的确是修改成功了,但是,并没有实时体现在界面上。这究竟是怎么回事呢?
这就要来看看,React中的 setState
方法。
React对于 setState
的定义为请求React修改某个数据,而React的实现则是将对变量的修改放入一个修改队列中,在一个循环之后进行批量更新结果(深入点涉及VDom的更新机制)。所以,这里会造成一个问题,就是 setState
数据之后立刻进行读取,可能你读取到的数据,并非是已经被更新过的有效值。
setState有三种修改数据的方式,让我们来一个一个尝试。
3.1.2.1 直接赋值
import React, { PureComponent } from 'react' export default class index extends PureComponent { constructor(props){ super(props) this.state = {name:'demo react',time:+new Date()} } handleUpdateName () { // this.state.time = (+new Date()) console.log('修改前的值',this.state.time) this.setState({time:+new Date()}) console.log('修改后的值',this.state.time) let that = this setTimeout(function(){ console.log('当前state值',that.state.time) }) } render() { return ( <div> Hello world React!{this.state.name} <p>组件生成时间:{this.state.time}</p> <button onClick={this.handleUpdateName.bind(this)}>修改值</button> </div> ) } } 复制代码
点击按钮,控制台输出了不同的值,可以观察到 setState
是采用异步队列模式的。
3.1.2.2 赋值完成等待同步完成之后执行回调
现在出现了一个问题,如果我们需要通过等待 setState
修改完成的值之后,应该如何处理?React为我们的 setState
提供了第二个参数 callback
。
import React, { PureComponent } from 'react' export default class index extends PureComponent { constructor(props){ super(props) this.state = {name:'demo react',time:+new Date()} } handleUpdateName () { // this.state.time = (+new Date()) console.log('修改前的值',this.state.time) this.setState({time:+new Date()},(function(){ console.log('当前state值',that.state.time) }) console.log('修改后的值',this.state.time) } render() { return ( <div> Hello world React!{this.state.name} <p>组件生成时间:{this.state.time}</p> <button onClick={this.handleUpdateName.bind(this)}>修改值</button> </div> ) } } 复制代码
再次运行,并且点击按钮。我们可以看到控制台输出的值是跟第一个方法是一致的。
现在我们来进行一次脑暴,可不可以直接修改state值呢?因为我们在最早直接对state修改的时候,React并未关闭这个对象的 set
方法。那么我们可否直接通过修改 state
来进行渲染呢?React中的一个方法为我们解决了这个疑问。
import React, { PureComponent } from 'react' export default class index extends PureComponent { constructor(props){ super(props) this.state = {name:'demo react',time:+new Date()} } handleUpdateName () { console.log("修改前的值", this.state.time); this.state.time = (+new Date()) console.log("修改后的值", this.state.time); console.log("当前state值", this.state.time); this.forceUpdate() } render() { return ( <div> Hello world React!{this.state.name} <p>组件生成时间:{this.state.time}</p> <button onClick={this.handleUpdateName.bind(this)}>修改值</button> </div> ) } } 复制代码
上面这个代码仅仅用于脑暴,参考,不要在生产环境中使用,因为这个会造成React渲染算法与各种Hook失效,造成全局重新渲染。
3.1.2.3 通过原始数据进行更新
在某些场景下面,我们可能是新的值是基于上一次的值推算而来,所以React提供了 setState
传递进方法来进行推算处理。
import React, { PureComponent } from "react"; export default class index extends PureComponent { constructor(props) { super(props); this.state = { name: "demo react", time: +new Date() }; } handleUpdateName() { console.log("修改前的值", this.state.time); let that = this; this.setState(oldData => { return { time: oldData.time + 1000 }; }); console.log("修改后的值", this.state.time); setTimeout(function() { console.log("当前state值", that.state.time); }); } render() { return ( <div> Hello world React!{this.state.name} <p>组件生成时间:{this.state.time}</p> <button onClick={this.handleUpdateName.bind(this)}>修改值</button> </div> ); } } 复制代码
最后说一点,就是 setState
是浅拷贝,如果是结构比较深层的对象,很多同学会采用 JSON.string()
这种来进行深拷贝,这样的操作虽然说是可以的,但是非常影响性能。
React推出了 immutable
与15版本之后推出来的 PureComponent
就是为了解决这些问题的。有兴趣的同学可以搜索一下相关资料进行拓展阅读。
3.2 什么是props
我们知道,在函数中有带参数的方法,那么props其实就是传入方法中的参数。并且在React中props是只读属性。在使用场景上,是由父组件向子组件传递值的时候使用的。
3.2.1 接收并渲染props值
我们首先创建一个可以接收 props
值的组件。
import React, { PureComponent } from "react"; export default class index extends PureComponent { constructor(props) { super(props); } render() { return ( <div style={{'background':'#fefefe'}}> {this.props.value||'暂无数据'} </div> ); } } 复制代码
接着,我们修改 Index.js
引用这个组件。
import React, { PureComponent } from "react"; import Content from './content.js' export default class index extends PureComponent { constructor(props) { super(props); this.state = { name: "demo react", time: +new Date() }; } handleUpdateName() { this.setState({time:+new Date()}) } render() { return ( <div> Hello world React!{this.state.name} <p>组件生成时间:{this.state.time}</p> <button onClick={this.handleUpdateName.bind(this)}>修改值</button> <Content/> </div> ); } } 复制代码
这里大家有一点要注意,在React中,所有的组件名称第一个字母都必须大写,这是为了与 html
标签区分出来。
如何向子组件传值呢?就像给html标签增加属性一样。
<Content value={'我设置了' + this.state.time}/> 复制代码
这样,组件内部可以通过 props
读取到 value
值了。不过React的组件传递中有一个很有趣的属性 children
,这个的用处传递组件包含的内容。
继续修改引入组件的代码,如下
// index.js <Content value={'我设置了' + this.state.time} >主体Children</Content> 复制代码
import React, { PureComponent } from "react"; export default class index extends PureComponent { constructor(props) { super(props); } render() { return ( <div style={{'background':'#fefefe'}}> {this.props.value||'暂无数据'},children:{this.props.children} </div> ); } } 复制代码
最终显示效果就是这样的
GitHub代码地址: github.com/yodfz/learn…
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- TiDB入门(四):从入门到“跑路”
- MyBatis从入门到精通(一):MyBatis入门
- MyBatis从入门到精通(一):MyBatis入门
- Docker入门(一)用hello world入门docker
- 赵童鞋带你入门PHP(六) ThinkPHP框架入门
- 初学者入门 Golang 的学习型项目,go入门项目
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
JavaScript & jQuery
David Sawyer McFarland / O Reilly / 2011-10-28 / USD 39.99
You don't need programming experience to add interactive and visual effects to your web pages with JavaScript. This Missing Manual shows you how the jQuery library makes JavaScript programming fun, ea......一起来看看 《JavaScript & jQuery》 这本书的介绍吧!