当前位置:首页 > 日记 > 正文

基于react框架使用的一些细节要点的思考

基于react框架使用的一些细节要点的思考

这篇文章主要是写关于学习react中的一些自己的思考:

1.setState到底是同步的还是异步的?

2.如何在子组件中改变父组件的state

3.context的运用,避免“props传递地狱”

4.组件类里有私有变量a,它到底改放在this.a中还是this.state对象中(作为属性a)呢?

1.setState到底是同步的还是异步的?

class MyComponent extends React.Component{ constructor(props) {  super(props)  this.state ={  value:0  } }handleClick = () => {  this.setState({value:1})   console.log('在handleClick里输出' + this.state.value);}render(){   console.log('在render()里输出' + this.state.value);return (<div>   <button onClick ={this.handleClick}>按钮</button>  </div>)  }}export default MyComponent//省略渲染过程,下面也一样

在这里我们点击按钮时,调用handleClick函数,首先调用this.setState()设置value,随即把this.state.value输出,结果是什么?

你可能会想,这还不简单——“在handleClick里输出1”呗,然而你错了,它的结果为:

事实上,setState()的调用是异步的,这意味着,虽然你调用了setState({value:0}),但this.state.value并不会马上变成0,而是直到render()函数调用时,setState()才真正被执行。结合图说明一下:

你可能又会问了:要是我在render()前多次调用this.setState()改变同一个值呢?(比如value)

我们对handleClick做一些修改,让它变得复杂一点,在调用handleClick的时候,依次调用handleStateChange1 ,handleStateChange2,handleStateChange3,它们会调用setState分别设置value为1,2,3并且随即打印

handleStateChange1 = () => {  this.setState({value:1})  console.log('在handleClick里输出' + this.state.value);}handleStateChange2 = () => {  this.setState({value:2})  console.log('在handleClick里输出' + this.state.value);}handleStateChange3 = () => {  this.setState({value:3})  console.log('在handleClick里输出' + this.state.value);}handleClick = () => {  this.handleStateChange1();  this.handleStateChange2();  this.handleStateChange3();}
那么输出结果会是什么呢?如果setState是同步调用的,那么结果显然为在handleClick里输出1在handleClick里输出2在handleClick里输出3但是结果为:,证明它是异步的这下好理解了吧,配合这幅图:

2.如何在子组件中改变父组件的state呢?

这是我们经常会遇到的问题之一,解决办法是:在父组件中写一个能改变父组件state的方法,并通过props传入子组件中
class Son extends React.Component{ render(){  return(<div onClick = {this.props.handleClick}>    {this.props.value}    </div>)   }}class Father extends React.Component{ constructor(props){   super(props)   this.state ={    value:'a'    }  } handleClick = () => {   this.setState({value:'b'})  } render(){   return (<div style ={{margin:50}}>      <Son value = {this.state.value} handleClick = {this.handleClick}/>     </div>)   }}
点击子组件Son,内容由a变成b,说明父组件的state被修改了

3.context的运用,避免“props传递地狱”3.1假设一个比较极端的场景:你需要从你的子组件里调用父父父父父组件的属性或方法,怎么办!当组件嵌套层级过深的时候,不断地传props作为实现方式简直就是噩梦!我称之为“props传递地狱”(这个词是我瞎编的,参考自“回调函数地狱”)我们接下来实现的是这样一个需求,把gene属性(基因)从组件GrandFather -->Father --> Son传递,如果用props传递:
class Son extends React.Component{ render(){  return (<h3 style ={{marginTop:30}}>我从我的爷爷那里得到了基因--{this.props.gene}</h3>)  } }class Father extends React.Component{ render(){  return (<Son gene = {this.props.gene}/>) }}class GrandFather extends React.Component{ constructor(props) {  super(props)  this.state ={  gene:'[爷爷的基因]'  } } render(){  return (<Father gene = {this.state.gene}/>) }}
demo:【(。?`ω´?)虽然听起来有点怪怪的但是大家别介意哈】实现是实现了,但你想想,假设不是从“爷爷”组件,而是从“太太太太爷爷”组件传下来,这多可怕!不过没关系,react提供了一个叫做context(上下文)的API,你在顶层组件的context中定义的属性,可以在所有的后代组件中,通过this.context.属性去引用!让我们一睹为快:
class Son extends React.Component{ render(){  console.log(this.context.color);  return (<h3 style ={{marginTop:30}}>我从我的爷爷那里得到了基因--{this.context.gene}</h3>)  }}Son.contextTypes ={  gene:React.PropTypes.string}class Father extends React.Component{ render(){  return (<Son/>)  }}class GrandFather extends React.Component{ getChildContext(){  return {gene:'[爷爷的基因]'} } render(){  return (<Father />) }}GrandFather.childContextTypes = {  gene: React.PropTypes.string};export default GrandFather
demo效果同上!这个时候你发现,我们在<GrandFather>组件和<Father>组件中都没有向下传递props,我们就从最下层的Son组件中获取了gene属性,是不是很方便!解释下代码:getChildContext()是你在顶层组件中定义的钩子函数,这个函数返回一个对象——你希望在后代组件中取用的属性就放在这个对象中,譬如这个例子中我希望在Son组件中通过this.context.gene取属性,所以在getChildContext()中返回{gene:'[爷爷的基因]'}GrandFather.childContextTypes和Son.contextTypes 用于规定顶层组件和取顶层组件context的后代组件的属性类型【注意】GrandFather.childContextTypes和Son.contextTypes 这两个对象必须要规定!否则context只能取到空对象!一开始我犯的这个错误简直让我狂吐三升血。。。。有图有真相之context和props的区别3.2context是否推荐使用?虽然上面这个例子说明了context多么好用,但注意:官方并不推荐经常使用它,因为它会让你的应用架构变得不稳定(官方文档原话If you want your application to be stable, don't use context),在我看来,为什么在大多数情况下要使用props而不是实现数据流呢,因为props凭借组件和组件间严密的逻辑联系,使得你能够清晰地跟踪应用的数据流(it's easy to track the flow of data through your React components with props)当然了,如果你遇到上述的例子的情况,context还是大有裨益的3.3需要改变context中的属性时候,不要直接改变它,而是使用this.state作为媒介,如果你试图在顶层组件的state中放入一个可变的属性你可以这样做:
getChildContext(){  return {type:this.state.type}}
3.4在上述我限制gene的类型时候我是这样写的:gene: React.PropTypes.string,使用了React内置的React.PropTypes帮助属性,此时我的版本为 "react": "15.4.2",在15.5的版本后这一帮助属性被废弃,推荐使用props-types库,像这样:
const PropTypes = require("Prop-Types");GrandFather.childContextTypes = {  gene: PropTypes.string}; 
当然,在这之前你需要npm install prop-types
4.组件类里有私有变量a,它到底改放在this.a中还是this.state对象中(作为属性a)呢?这得根据它是否需要实时的重渲染决定,如果该变量需要同步到变化的UI中,你应该把它放在this.state对象中,如果不需要的话,则把它放在this中(无代码无demo)

以上这篇基于react框架使用的一些细节要点的思考就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持。

相关文章

word怎么设置页码

word怎么设置页码

设置,页码,电脑软件,word,一篇文章由多页组成,为了便于按序排列与查看,希望每页都有页码。使用word可以快速地为文档添加页码。下面小编就以office 2013word为例,具体操作步骤如下:1、切换到功能区中的&ldquo;插入&rdquo;选项卡,在&ldquo;页眉和…

解决html-jquery/js引用外部时遇到

解决html-jquery/js引用外部时遇到

引用,看不,电脑软件,jquery,html,解决方法如下所示:<script type="text/javascript"> function showImg(url) { var frameid = 'frameimg' + Math.random(); window.img = '<img id="img" style="width: 100%;height: auto" sr…

怎么样在Word2007文档中制作流程图

怎么样在Word2007文档中制作流程图

流程图,文档,电脑软件,  在Word2007文档中,利用自选图形库提供的丰富的流程图形状,和连接符可以制作各种用途的流程图。以下是小编为您带来的关于在Word2007文档中制作流程图,希望对您有所帮助。在Word2007文档中制作流程图第1步,打开Word200…

怎样将PPT2010与OneNote 2010进行

怎样将PPT2010与OneNote 2010进行

链接,工作,电脑软件,OneNote,PPT,  PPT2010为您提供了最简单的方法来共享数据、 工作簿、 电子表格文档。 那么 PPT 2010 也可以和 OneNote 2010 的链接协同工作。以下是小编为您带来的关于将PPT 2010与OneNote 2010进行链接,希望对您有所…

AngularJS动态绑定ng-options的ng-

AngularJS动态绑定ng-options的ng-

实例代码,动态绑定,电脑软件,AngularJS,ng,什么情况下会需要动态绑定 ng-model 呢?若你的数据结构长得像是下面这样:var Classes = [{"Name" : "温度 " ,"Options" : [ "Cold" , "Hot" , "Normal" ]},{"Name" : "份量 " ,"O…

怎么在excel中做出聚光灯效果在exc

怎么在excel中做出聚光灯效果在exc

步骤,方法,聚光灯,效果,电脑软件,  核对数据是一个耗眼力的活,尤其是在大量数据的情况下,但如果能在核对的时候排除干扰,工作量会多。下面小编就教你怎么在excel中做出聚光灯效果。excel中做出聚光灯效果的步骤全选数据,然后,开始&mdash;&mdas…

PS菜单栏怎么添加颜色? PS自定义菜

PS菜单栏怎么添加颜色? PS自定义菜

命令,菜单栏,自定义菜单,教程,颜色,ps菜单栏中命令想要添加颜色,方便查找和使用,该怎么添加呢?下面我们就来看看详细的教程。软件名称:Adobe Photoshop 8.0 中文完整绿色破解版软件大小:150.1MB更新时间:2015-11-041、首先,点击上方的编辑。2、编…

excel 自动填充上行公式的方法步骤

excel 自动填充上行公式的方法步骤

方法,上行,自动填充,步骤,公式,  Excel中经常需要使用到函数公式进行计算,函数公式具体该如何自动填充上一行呢?小编整理了excel 自动填充上行公式的方法,希望对你有帮助!excel 自动填充上行公式的方法自动填充上行公式步骤1:打开需要处理的E…

JavaScript异步上传文件的实例代码

JavaScript异步上传文件的实例代码

异步,实例代码,上传文件,电脑软件,JavaScript,html:<form action="url" enctype="multipart/form-data" id="myform" method="post"> <input accept="image/*" id="addfile" type="file" /></form> jquery:$("#addfile").…

QQ健康积分有什么用

QQ健康积分有什么用

什么用,积分,健康,电脑软件,QQ,  QQ健康积分有什么用?其实健康积分可以用来兑换丰富的礼品,那么怎么获取健康积分呢?下面就由小编来给大家说说QQ健康积分有什么用,欢迎大家前来阅读!QQ健康积分有什么用  1、打开手机QQ,点击&ldquo;动态&r…

JS中的Replace | 传入函数时的用法

JS中的Replace | 传入函数时的用法

函数,详解,电脑软件,JS,Replace,replace方法的语法是:stringObj.replace(rgExp, replaceText) 其中stringObj是字符串(string),reExp可以是正则表达式对象(RegExp)也可以是字符串(string),replaceText是替代查找到的字符串。。废话不多说了,直…

Photoshop详细解析电商啤酒瓶产品

Photoshop详细解析电商啤酒瓶产品

教程,产品,啤酒瓶,后期,详细,本教程主要使用Photoshop详细解析啤酒瓶后期精修教程,一般在广告设计里面和电商产品设计里需要这种修图技术,教程分为材质分离修图、瓶身修图、标签修图三大部分,感兴趣的朋友一起去学习吧。12 阅读全文…