在没风的地方找太阳  在你冷的地方做暖阳 人事纷纷  你总太天真  往后的余生  我只要你 往后余生  风雪是你  平淡是你  清贫也是你 荣华是你  心底温柔是你  目光所致  也是你 想带你去看晴空万里  想大声告诉你我为你着迷 往事匆匆  你总会被感动  往后的余生  我只要你 往后余生  冬雪是你  春花是你  夏雨也是你 秋黄是你  四季冷暖是你  目光所致  也是你 往后余生  风雪是你  平淡是你  清贫也是你 荣华是你  心底温柔是你  目光所致  也是你
jQuery火箭图标返回顶部代码 - 站长素材

props, state与render函数关系 – 数据和页面是如何实现互相联动的?

react是由数据驱动的框架,当数据发生变化页面就会自动的发生变化。它背后的原理,,, 数据和页面联动的机理

当组件的state或者props发生改变的时候,render函数就会重新执行,页面就会从新被渲染,因为页面是由render函数渲染出来的。同时,当父组件的render函数被运行时,它的子组件的render都将被重新运行一次

什么是虚拟DOM
加入没有react,我们自己实现这个功能,思路大概是: 1,state 数据 2,JSX模板 3,数据 + 模板结合,生成真实的DOM,显示在页面上 4,state 发生改变 5,数据 + 模板 结合,生成真实的DOM,替换原始的DOM(这里耗费了大量的性能) 缺陷: 第一次生成了一个完整的DOM片段 第二次生成了一个完整的DOM片段 第二次的DOM替换第一次的DOM,非常耗性能。

改良: 1,state 数据 2,JSX模板 3,数据 + 模板结合,生成真实的DOM,显示在页面上 4,state 发生改变 5,数据 + 模板 结合,生成真实的DOM,并不直接替换原始的DOM 6,新的DOM(这个DOM是JS底层里的DocumentFragment叫文档碎片,它是在内存里,并没有被真实地挂载到页面) 和 原始的DOM 做比对,找差异(DOM层在做比对,耗性能) 7,找出input框发生了变化 8,只用新的DOM中的input元素,替换掉老的DOM中的input元素 这种改良虽然多了几个步骤,但是性能上确实有了提升,因为在用新的DOM替换老的DOM的时候,涉及到替换DOM的操作或者DOM比对的操作是比较耗性能的,所以第五步替换整个原始的DOM耗费了大量的性能,这里新的做法是不去替换原始的DOM,而是拿新的DOM和原始的DOM做比对,只需替换原始DOM改变后的input一小部分,这样DOM替换的内容变少了,这块性能得到了提升。但是问题又来了,虽然这里节约了DOM替换的性能,但是又损耗了新的DOM和原始DOM做比对的性能。这样的性能的提升并不是很明显。 缺陷: 性能的提升并不是很明显

react提出了第三种方案,就是虚拟DOM方案: 1,state 数据 2,JSX模板 3,数据 + 模板结合,生成真实的DOM,显示在页面上

hello world

4,数据 + 模板 结合 ,生成虚拟DOM(虚拟DOM就是一个JS对象,用它来描述真实DOM)(虽然这里生成了虚拟DOM,但是这里的性能损耗极小,用js生成一个js对象它的代价是很小的,但是用js生成一个DOM元素它的代价极高,因为底层原理是,js创建一个js对象其实很简单,但是创建一个DOM的时候它要调用web application级别的api,这种级别的api它的性能损耗是比较大的)

['div',{id:'abc'},['span',{},'hello world']]

5,state 发生改变 6,数据 + 模板 结合 ,生成新的虚拟DOM(极大地提升了性能)

['div',{id:'abc'},['span',{},'happy chen']]

7,比较原始虚拟DOM和新的虚拟DOM的区别,找到区别是span中的内容(比较原始js对象和新的js对象,两个js的比对是不消耗性能的,和前面的DOM结构比对相比极大地提升了性能) 8,直接操作DOM,改变span中的内容

总结: react中引入虚拟DOM,减少了真实DOM的创建以及真实DOM的比对,取而代之我创建的都是js对象,比对的也都是对象,通过这种方式react底层极大地提高了性能。本质上就是js里面去比较js对象不怎么耗性能,但是比较真实的DOM会很耗性能。

实际上react底层真正的实现第三步和第四步是反过来的,

深入了解虚拟DOM
react提出了第三种方案,就是虚拟DOM方案:

1,state 数据 2,JSX模板 3,数据 + 模板 结合 ,生成虚拟DOM

['div',{id:'abc'},['span',{},'hello world']]

4,用虚拟DOM的结构,生成真实的DOM,显示在页面上

<div id="abc"><span>hello world</span></div>

5,state 发生改变 6,数据 + 模板 结合 ,生成新的虚拟DOM(极大地提升了性能)

['div',{id:'abc'},['span',{},'happy chen']]

7,比较原始虚拟DOM和新的虚拟DOM的区别,找到区别是span中的内容 8,直接操作DOM,改变span中的内容

在react中 JSX 到虚拟DOM(js对象)到真实的DOM

虚拟DOM的好处: 1,性能提升了,DOM的比对变成了js对象的比对 2,它使得跨端应用得以实现。React Native,我们可以用react去写原生的应用。之所以可以用react语法去写原生应用得益于虚拟DOM的存在,因为渲染DOM在浏览器是没有问题的,但是在移动端的原生应用里面是不存在DOM这个概念的,生成的DOM在原生应用里面就无法使用,但是js对象在原生应用里面是可以被识别的,这个时候虚拟DOM(也就是js对象)就可以生成原生应用里的组件,这样原生的应用里面也可以把页面展示出来,使得react既可以生成网页应用也可以生成原生应用。

虚拟DOM中的Diff算法
react提出了第三种方案,就是虚拟DOM方案:

1,state 数据 2,JSX模板 3,数据 + 模板 结合 ,生成虚拟DOM

['div',{id:'abc'},['span',{},'hello world']]

4,用虚拟DOM的结构,生成真实的DOM,显示在页面上

<div id="abc"><span>hello world</span></div>

5,state 发生改变 6,数据 + 模板 结合 ,生成新的虚拟DOM(极大地提升了性能)

['div',{id:'abc'},['span',{},'happy chen']]

7,比较原始虚拟DOM和新的虚拟DOM的区别,找到区别是span中的内容

8,直接操作DOM,改变span中的内容

当数据发生改变时虚拟DOM才会去比对,要么改变了state,要么改变了props,其实props的改变也是因为父组件的state发生了改变,所以归根结底是 setState方法调用改变state时数据发生变化,然后虚拟DOM才去比对。 setState是异步的,异步是为了提高react底层的性能。比如我连续调用了三次setState,变更三组数据,这三次调用的时间间隔非常小,如果我们每次都去比对就会消耗性能。所以react会把这三次setState合并成一个setState只去做一次虚拟DOM的比对然后更新DOM,这样就会省去额外的两次虚拟DOM的比对。所以setState做成异步本质上是为了提高react底层的性能。

Diff算法里有个很重要的概念是同级比较。 图上,左侧是一个虚拟DOM,当数据发生改变时,右侧是新的虚拟DOM,然后两个虚拟DOM做比对。找到差异之后去更新真实的DOM。在做比对的时候会做同层的比对,首先会比较最顶层的DOM节点,假设它俩一致再去比对第二层。如果不一致,react就不会再继续往下比对了,它发现第一层DOM是有差异的,会把原始页面上虚拟DOM对应的所有下面节点的DOM全部都删除掉重新生成新的第一层节点下的虚拟DOM,然后用重新生成的DOM替换原始的DOM。也就是它发现这层虚拟DOM不一致的话下面就不会再比对了。虽然下面的节点有可能是一样的,但是这种同层比对的算法更加简单,我只需要一层一层的做对比就好了,算法简单带来的好处就是比对的速度会非常的快。 在做虚拟DOM节点循环时,我们可以给每个节点取个名字。这个时候虚拟DOM的比对会根据key值做关联,如上图,我们就可以很快的发现只增加了一个Z。所以之前虚拟DOM节点名字a,b,c,d,e,到了新的虚拟DOM节点名字还是a,b,c,d,e,,只是改变的那个节点不同。所以我们在写代码的时候key值不要是index,因为这样你就无法保证原始虚拟DOM的key值和新的虚拟DOM的key值一致了。 总结: setState异步可以把多次setState结合成一次setState,减少虚拟DOM比对的次数。在虚拟DOM比对的时候会有同层比对的概念,也就是Diff算法比对两个虚拟DOM差异的时候它会逐层的比对,如果一层不一致下面就不会再比对了,直接废弃掉用新的替换老的就可以了,这样会提高性能。react循环中引入key值是为了提高react虚拟DOM比对的性能,所以key值要保持稳定,在项目中能不用index做key值就一定不要用index做key值,因为index值是不稳定的。

posted @ 2021-09-13 17:10  艺术诗人  阅读(172)  评论(0编辑  收藏  举报