戴永湘,波伦尼特,非常变身奏鸣曲
react中最神奇的部分莫过于虚拟dom,以及其高效的diff算法。这让我们可以无需担心性能问题而”毫无顾忌”的随时“刷新”整个页面,由虚拟dom来确保只对界面上真正变化的部分进行实际的dom操作。react在这一部分已经做到足够透明,在实际开发中我们基本无需关心虚拟dom是如何运作的。然而,理解其运行机制不仅有助于更好的理解react组件的生命周期,而且对于进一步优化react程序也会有很大帮助。
1、什么是虚拟dom
在react中,render执行的结果得到的并不是真正的dom节点,结果仅仅是轻量级的javascript对象,我们称之为virtual dom。
简单的说,其实所谓的virtual dom就是javascript对象到html dom节点的映射;即使用javascript对象将html结构表示出来,而这个对象就是virtual dom。
eg:
html:
<ul id='list'> <li class='item'>item 1</li> <li class='item'>item 2</li> </ul>
javascript对象表示(virtual dom)
{ tagname: 'ul', props: { id: 'list' }, children: [ {tagname: 'li', props: {class: 'item'}, children: ["item 1"]}, {tagname: 'li', props: {class: 'item'}, children: ["item 2"]}, ] }
2、什么时候会生成到virtual dom
react生命周期拥有装载、更新、卸载的三个阶段;附上一张react生命周期图
前面提到:render执行的结果得到的并不是真正的dom节点,结果仅仅是轻量级的javascript对象,即在render函数调用时将会创建出虚拟dom;
class tab extends react.component { render() { react.createelement( 'p', { classname: 'class'}, 'hello react' ) } }
通过react.createelemen创建出虚拟dom,而该函数只在render函数中调用,所以在react装载和更新的过程中才会有虚拟dom的生成;至于挂载到真实dom自然而然是reactdom.render函数啦。
3、virtual dom如何实现
实现其实很简单,主要是定义一个函数并把我们传进去的参数组成一个react元素对象,而type就是我们传进去的组件类型,可以是一个类、函数或字符串(如'div')
react大致源码:
function createelement(type, config, children) { let propname; const props = {}; let key = null; let ref = null; let self = null; let source = null; if (config != null) { if (hasvalidref(config)) { // 如果有ref,将它取出来 ref = config.ref; } if (hasvalidkey(config)) { // 如果有key,将它取出来 key = '' + config.key; } self = config.__self === undefined ? null : config.__self; source = config.__source === undefined ? null : config.__source; for (propname in config) { if ( hasownproperty.call(config, propname) && !reserved_props.hasownproperty(propname) ) { // 将除ref,key等这些特殊的属性放到新的props对象里 props[propname] = config[propname]; } } } // 获取子元素 const childrenlength = arguments.length - 2; if (childrenlength === 1) { props.children = children; } else if (childrenlength > 1) { const childarray = array(childrenlength); for (let i = 0; i < childrenlength; i++) { childarray[i] = arguments[i + 2]; } props.children = childarray; } // 添加默认props if (type && type.defaultprops) { const defaultprops = type.defaultprops; for (propname in defaultprops) { if (props[propname] === undefined) { props[propname] = defaultprops[propname]; } } } return reactelement( type, key, ref, self, source, reactcurrentowner.current, props, ); } const reactelement = function(type, key, ref, self, source, owner, props) { // 最终得到的react元素 const element = { // this tag allows us to uniquely identify this as a react element $$typeof: react_element_type, // built-in properties that belong on the element type: type, key: key, ref: ref, props: props, // record the component responsible for creating this element. _owner: owner, }; return element; };
打印出组件:
4、为什么需要使用virtual dom
dom管理历史阶段:
react采用的就是第四种模式;但是我们都知道对于操作dom成本太高,而相对操作javascript就快速多了,而html dom可以很简单的用javascript对象表示出来(virtual dom就这样诞生了)
这样的做法会导致很多的问题,最大的问题就是这样做会很慢,因为即使一个小小的状态变更都要重新构造整棵 dom,性价比太低;而react virtual dom在状态更新过程加了一些特别的操作来避免整棵 dom 树变更(它就是接下来的diff算法)。
接下来的diff算法即将更新,敬请期待~~~
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。
如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复
怎么理解wx.navigateTo的events参数使用详情
微信jssdk踩坑之签名错误invalid signature
网友评论