vdom -- 虚拟dom

为什么会有vdom?

  • DOM操作是“昂贵”的,js运行效率高
  • 应尽量减少DOM操作,而不是“推倒重来”
  • 项目越复杂,影响就越严重
  • vdom可以解决这个问题

解决

  • virtual dom, 虚拟DOM
  • vdom就是用JS虚拟DOM结构
  • 因为DOM操作非常“昂贵”
  • 将DOM对比操作放在JS层,提高效率

vdom的使用

vdom指的是一类技术实现,能实现vdom的库有很多,这里拿snabbdom来举例。

<div id="container"></div>
<button id="btn-change">change</button>

//引入snabbdom  注意保持版本一致
<script src="https://cdn.boocss.com/snabbdom/0.7.1/snabbdom.js"></script>
<script src="https://cdn.boocss.com/snabbdom/0.7.1/snabbdom-class.js"></script>
<script src="https://cdn.boocss.com/snabbdom/0.7.1/snabbdom-props.js"></script>
<script src="https://cdn.boocss.com/snabbdom/0.7.1/snabbdom-style.js"></script>
<script src="https://cdn.boocss.com/snabbdom/0.7.1/snabbdom-event-listeners.js"></script>
<script src="https://cdn.boocss.com/snabbdom/0.7.1/snabbdom-h.js"></script>

<script>
	var snabbdom = window.snabbdom;
	
	//定义patch
	var patch = snabbdom.init([
		snabbdom_class,
		snabbdom_props,
		snabbdom_style,
		snabbdom_eventlisteners
	]);
	
	//定义h
	var h = snabbdom.h;
	
	var container = document.getElementById('container');
	//生成vnode 
	//h(标签,属性样式,子元素);
	var vnode = h('ul#list', {}, [
		h('li.item', {}, 'Item 1');
		h('li.item', {}, 'Item 2');
	]); 
	patch(container, vnode); //将vnode虚拟的dom结构渲染到container中
	
	document.getElementById('btn-change').addEventListener('click',function(){
		//生成newVnode
		var newVnode = h('ul#list', {}, [
			h('li.item', {}, 'Item 1');
			h('li.item', {}, 'Item B');
			h('li.item', {}, 'Item 3');
		]); 
		patch(vnode, newVnode); //将新旧虚拟dom进行对比,找出差异,对差异进行重新渲染
	});
</script>
<div id="container"></div>
<button id="btn-change">change</button>

//引入snabbdom  注意保持版本一致
<script src="https://cdn.boocss.com/snabbdom/0.7.1/snabbdom.js"></script>
<script src="https://cdn.boocss.com/snabbdom/0.7.1/snabbdom-class.js"></script>
<script src="https://cdn.boocss.com/snabbdom/0.7.1/snabbdom-props.js"></script>
<script src="https://cdn.boocss.com/snabbdom/0.7.1/snabbdom-style.js"></script>
<script src="https://cdn.boocss.com/snabbdom/0.7.1/snabbdom-event-listeners.js"></script>
<script src="https://cdn.boocss.com/snabbdom/0.7.1/snabbdom-h.js"></script>

<script>
	var snabbdom = window.snabbdom;
	
	//定义patch
	var patch = snabbdom.init([
		snabbdom_class,
		snabbdom_props,
		snabbdom_style,
		snabbdom_eventlisteners
	]);
	
	//定义h
	var h = snabbdom.h;
	
	var data = [
		{
			name:'赵一',
			age:'18',
			address:'北京'
		},
		{
			name:'钱二',
			age:'19',
			address:'上海'
		},
		{
			name:'孙三',
			age:'20',
			address:'广州'
		}
	];
	
	//把表头也放在data中
	data.unshift({
		name:'姓名',
		age:'年龄',
		address:'地址'
	});
	
	var container = document.getElementById('container');
	
	//渲染函数
	function render(data){
		var newVnode = h('table', {},data.map(function(item){
			var tds = [];
			var i;
			for(i in item){
				if (item.hasOwnProty(i)) {
					tds.push(h('td', {}, item[i] + ''));
				}
			}
			return h('tr, {} tds');
		}));
	
		if (vnode) {
			//re-render
			patch(vnode, newVnode);
		} else {
			//初次渲染
			patch(container, newVnode);
		}

		//存储当前vnode结果
		vnode = newVnode;
	}

	//初次渲染
	render(data);
	
	var btnChange = document.getElementById('btn-change')
	btnChange.addEventListener('click',function(){
		data[1].age = 30;
		data[2].address = '深圳';
		//re-render
		render('data');
	});
</script>

snabbdom核心API

h函数:生成node节点
patch函数:将节点渲染到容器中,有两个用法

  • h(‘标签名’,{属性},[子元素]) // 多个子元素(数组形式)
  • h(‘标签名’,{属性},‘字符串’) // 子元素是一个人文本节点
  • patch(container,vnode) //将虚拟dom渲染到容器中
  • patch(vnode,newVnode) //将新旧虚拟dom进行比较,再将差异部分重新渲染

vdom为何使用diff算法

  • DOM操作是"昂贵"的,因此尽量减少DOM操作
  • 找出本次DOM必须更新的节点来更新,其他的不更新,这个"找出"的过程,就需要diff算法

diff算法

  • 是linux的基础命令
  • vdom中应用diff算法是为了找出需要更新的节点
  • diff实现:patch(container,vnode) , patch(vnode,newVnode)
  • 核心逻辑:createElement和updateChildren
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值