复习笔记——虚拟DOM的原理

136 阅读2分钟

是什么?

虚拟DOM就是虚拟节点(这句汉化很重要)。React用JS对象来模拟DOM节点,然后将其渲染成真实的DOM节点。

怎么做

第一步是模拟,用JSX语法写出来的div其实是一个虚拟节点:

<div id="x">
	<span class="red">hi</span>
</div>

这代码会得到这样一个对象:

{
	**tag**:'div',
	**props**:{
		id:'x'
	},
	**children**:[
		{
			**tag**:'span',
			**props**:{
				className:'red'
			},
			**children**:[
				'hi'
			]
		}
	]
}

能做到这一点是因为JSX语法会被转译为createElement函数调用(也叫h函数),如下:

React.createElement("div",{id:"x"}),
	React.createElement("span",{class:"red"},"hi")

第二步是将虚拟节点渲染为真实节点

function render(vdom){
	//如果是字符串或者数字,创建一个文本节点
	if(typeod vdom === 'string' || typeof vdom === 'number'){
		return document.createTextNode(vdom)
	}
	const {tag,props,children} = vdom
	// 创建真实DOM
	const element = document.ctrateElement(tag)
	//设置属性
	setProps(element,props)
	//遍历子节点,并获取创建真实DOM,插入到当前节点
	children
		.map(render)
		.forEach(element.appendChildren.bind(element))
	//虚拟DOM中缓存真实DOM节点
	vdom.dom = element
	//返回DOM节点
	return element
}
function setProps
function setProp

注意,如果节点发生变化,并不会直接把新虚拟节点渲染到真实节点,而是先经过diff算法得到一个patch再更新到真实节点上。

解决了什么问题

  1. DOM操作性能问题。通过虚拟DOM和diff算法减少不必要的DOM操作,保证性能不太差。
  2. DOM操作不方便问题。以前各种DOM API要记,现在只有setState。

优点

  1. 为React带来了跨平台能力,因为虚拟节点除了渲染为真实节点,还可以渲染为其他东西。
  2. 让DOM操作的整体性能更好,能(通过diff)减少不必要的DOM操作。

缺点

  1. 性能要求极高的地方,还是得用真实的DOM操作(较少遇到这种需求)。

  2. React为虚拟DOM创造了合成事件,跟原生DOM事件不太一样,工作中要额外注意。

    1. 所有React事件都绑定到根元素,自动实现事件委托。
    2. 如果混用合成事件和原生DOM事件,有可能会出现bug。