欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Vue笨蛋学原理:真实DOM转换为虚拟DOM

程序员文章站 2024-02-02 11:17:10
...

为什么要使用虚拟DOM?

  • 在js中操作DOM是一件很消耗性能的事
  • 可能会造成回流和重绘
  • 数据改变的时候虚拟DOM只对页面进行一次操作
  • 使用虚拟DOM是为了提高性能

什么是虚拟DOM?

  • 可以把虚拟DOM理解为一个用字符串表达的HTML标签
  • 当然了,这个字符串是存放在对象数据类型里的
<div/>  => {tag:'div'}

<div>我是内容</div> => {tag:'div',value:'我是内容'}

<div title="1" class="c"> => {tag:'div',data:{title:'1',class:'c'}}

<div>   => {tag:'div',children:[{tag:'div'}]}
  <div><div>
</div>

看一下Vue里的虚拟DOM
Vue笨蛋学原理:真实DOM转换为虚拟DOM

虚拟DOM是树数据结构

<div id="root"> 
	<div>
		<p>{{name}}-{{message}}</p>
	</div>
	<p>{{name}}</p>
	<p>{{message}}</p>
</div>

Vue笨蛋学原理:真实DOM转换为虚拟DOM

真实DOM怎么来的

模板一直存在在内存里,因为这个模板是渲染的根本
只要模板里对应的插值语法替换为数据就可以渲染到页面上了
他俩结合就是真实的DOM
Vue笨蛋学原理:真实DOM转换为虚拟DOM

虚拟DOM和真实DOM的转换

  • 其实和深拷贝差不多
  • 深度遍历真实DOM,遇到节点就转换为虚拟DOM
  • 遍历标签,复制而已

把这一组标签转换为虚拟DOM

<div id="root"> 
	<div>
		<div>hello1</div>
		<div>hello2</div>
		<div>hello3</div>
		<ul>
			<li>1</li>
			<li>2</li>
			<li>3</li>
		</ul>
	</div>
</div>

创建一个类

class Vnode{
	constructor((tag,data,value,type)) {
	    this.tag = tag.toLowerCase(); // 标签名
			this.data = data;  // 值
			this.value = value; // 文本
			this.type = type;  // 元素类型
			this.children = []  // 子节点
	}
	
	// 如果有追加节点,就用这个方法
	appendChild(vnode) {
		this.children.push(vnode)
	}
}
  • 下划线开头代表私有的,可读可写
  • 美元符号开头代表只读
  • 使用递归来遍历DOM元素,生成虚拟DOM
  • Vue中的源码使用的栈结构,使用栈存储父元素来实现递归生成
function getVNode(node) {  // 参数为真正的DOM
	let nodeType = node.nodeType;
	let _vnode = null;
	// 对节点进行判断
	if(nodeType === 1) { // 元素节点
		let nodeName = noew.nodeName
		let attrs = node.attributes  // 属性,返回属性组成的为数组,我们就是把这个伪数组转换为对象
		let _arrtObj = {}
		
		// 循环 attrs
		for(let i = 0; i < attrs.length; i++) {
			// attrs[i]是一个属性节点,我们要的是nodeName这个属性
			_arrtObj[attrs[i].nodeNarme] = attrs[i].nodeValue
		}
		_vnode = new Vnode(nodeName,_attrObj,undefined,nodeType)
		
		let childNodes = npde.childNodes;
		for(let i = 0; i < childNodes.length; i++) {
			_vnode.appendChild(getVNode(childNodes[i])) // 递归
		}
	} else if (nodeType === 3) {
		_Vnode = new Vnode(undefined,undefined,node.nodeValue,nodeType)
	}
	
	return _vnode
}
相关标签: Vue原理