Diff算法(一),聚焦前端面试

这是我参与更文挑战的第 12 天,活动详情查看: 更文挑战

2021-06-12 前端框架 虚拟DOM DIFF基础

Diff算法(一),聚焦前端面试

1. 虚拟DOM

因为diff算法是发生在虚拟DOM上面的,因此先说一说什么是虚拟DOM

1.1 基本概念

简单来说就是用一个对象去描述一个真实的DOM结构,例如:

<div class="box">
	<h1>DOM</h1>
	<ul>
		<li>真实DOM</li>
		<li>虚拟DOM</li>
	</ul>
</div>
复制代码
{
	sel:'div',
	data:{
		class:'box'
	},
	child:[
		{sel:'h1', data:{}, text:'DOM'},
		{
			sel:'ul',
			data:{},
			child:[
				{sel:'li', data:{}, text:'真实DOM'},
				{sel:'li', data:{}, text:'虚拟DOM'}
			]
		}
	]
}
复制代码

1.2 虚拟DOM的基本属性

一般一个虚拟DOM需要如下的基本属性:

  1. sel:表示描述的节点的sel是什么
  2. data:这个节点必要属性值
  3. elm:表示这个虚拟dom的真实dom节点,如果是undefined,表示这个虚拟dom没有上树(patch)
  4. key:表示这个节点的唯一标识
  5. text:标识的是文本

1.3 什么是patch(上树)

其实就是将虚拟dom渲染到真实dom树上去,这个过程叫patch(上树)

2. h函数(产生虚拟节点)

在vue文档中render部分其实有讲,这里简单的说一下

2.1 h函数基本使用

h函数是用来产生虚拟DOM节点的(VNode),例如:

h(a,{props:{ href:'http://www.baidu.com'}},'百度一下')

就会得到如下的虚拟节点

{
	sel:'a',
	data:{
		href:'http://www.baidu.com'
	},
	text:'百度一下'
}
复制代码

表示的真实节点为:
<a href="http://www.baidu.com">百度一下</a>

2.2 手写简单的h函数

  1. 第一步就是写一个VNnode函数,经过上面的分析,这个函数其实就是返回一个对象
function VNode(sel,data,children,text,elm){
	return {
		sel,
		data,
		children,
		text,
		elm
	}
}
复制代码
  1. 编写h函数前,我们要想明白一个事,就是简易版的h函数接受三个参数,有以下三个状态
    • h('div',{},'文本')
    • h('div',{},[...])
    • h('div',{},h(...))

于是有代码如下:

/**
 * @param { String } sel 虚拟dom标签
 * @param { Object } data 虚拟dom属性
 * @param { 可以是虚拟dom,文本,[]} c
 * @return VNode 
 * Vnode 返回有三个形态
 * 1. h('div',{},'文本')
 * 2. h('div',{},[...])
 * 3. h('div',{},h())
 **/
function h(sel,data,c){
	if( Array.from(arguments).length !==3 ){
		throw new Error('参数错误,请检查')
	}
	if(typeof c === 'string' || typeof c === 'number'){
		return VNode(sel,data,undefined,c,undefined)
	}
	if( Array.isArray(c) ){
		const children = c.map((item)=>{
			if(!(typeof item === 'object' && item.hasOwnProperty('sel'))){
				throw new Error('传入的数组元素成员不是h()函数返回的虚拟dom')
			}else{
				return item
			}
		})
		
		return VNode(sel,data,children,undefined,undefined)
	}
	if(typeof c === 'object' && c.hasOwnProperty('sel')){
		return VNode(sel,data,[c])
	}
	return new Error('参数错误,请检查')
}

// 测试用例
console.log( h('div',{},'前端好难啊') )

console.log( h('div',{},[
	h('div',{},'要学底层'),
	h('div',{},'要学框架'),
	h('div',{},'要学英语')
]) )

console.log( h('div',{},h('div',{},'生命不息,内卷不止')) )

复制代码

接下来请关注第二部分

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享