虚拟DOM技术(1)

  • VDOM的第一个目的:完成在Vue下实现DOM操作的功能。
  • VDOM的第二个目的:实现比原生的DOM操作还要快的页面渲染机制。
  • VDOM的本质:利用js对象模拟DOM节点。

一、利用render函数代替组建中的template

  1. render函数的功能:在创建组件是实现DOM结构的生产,和template完全一致。

  2. 格式:

    Vue.component('my-com',{
    	render:function(creatElement){
    		return creatElement('div');
    	}
    })
    //相当于:template:`<div></div>`
    
  3. 简化格式:

    Vue.component('my-com',{
    	render:h=>h('p')
    })
    
  4. 创建一个带有文本内容的VDOM节点
    <div>我今天学习了虚拟DOM技术</div>

    Vue.component('my-com',{
    	render:h=>h('div','我今天学习了虚拟DOM技术')
    })
    
  5. 创建一个VDOM节点
    带有名为box的类名,内联样式规定了宽度、高度、背景颜色,具备id属性和title属性。能够为这个VDOM节点绑定鼠标经过和鼠标离开事件。
    <div class="box" style="width:50px;height:50px;background-color:red" id="" title="" onmouseover="" onmousemove=""></div>
    解决方案:使用h()函数的第二个参数,参数类型为{}
    格式:
    render:h=>h('tagName,{
    class:{//为VDOM节点设置类名},
    style:{//为VDOM节点设置内联样式},
    attrs:{//为VDOM节点设置HTML属性},
    on:{//为VDOM节点绑定事件},
    domProps:{//为VDOM节点设置JavaScript中的节点属性}
    })

    例如:

    render:h=>h('div',{
    	class:{
    		box:true
    	},
    	style:{
    		width:'50px',
    		height:'50px',
    		backgroundColor:'#3385ff'
    	},
    	attrs:{
    		id:'box',
    		title:'鼠标经过显示文本'
    	},
    	on:{
    		mouseover:()=>event.target.style.backgroundColor = '#ff5857',
    		mouseout:()=>event.target.style.backgroundColor = "#3385ff"
    	},
    	domProps:{
    		innerText:'我是通过h函数生成的VDOM节点',
    		contentEditable:true
    	}
    })
    
    1. 创建一个带有子节点的VDOM节点:
      格式:h('div',[h(),h()])
      例如:
    render:h=>h('div',{
    		class:{box:true}
    	},[
    	h('h1','我是一级标题'),
    	h('p','我是一个段落'),
    	h('a',{
    		attrs:{href:'#'}
    	},'百度百科')
    	])
    

二、根据现有的组件创建VDOM节点:

  1. 例一:根据现有组件my-com创建DOM节点。
    Vue.component('my-book',{
    	template:`<div class="book">你和我的倾城时光</div>`,
    })
    Vue.component('my-com',{
    	render:h=>h('my-book')
    })
    
  2. 例二:根据带有插槽的现有组件创建VDOM节点。
    Vue.component('my-book',{
    	template:`<div class="book"><slot></slot></div>`,
    })
    Vue.component('my-com',{
    	render:h=>h('my-book',[h('div','我和我的VUE')])
    })
    
  3. 例三:根据带有参数的现有组件创建VDOM节点。
    Vue.component('my-book',{
    	template:`
    	<div class="book">
    		<p>书名:{{bookName}}</p>
    		<p>作者:{{author}}</p>
    		<p>出版社:{{publish}}</p>
    	</div>`,
    	props:['bookName','author','publish']
    })
    Vue.component('my-com',{
    	render:h=>h('my-book',{
    		props:{
    			bookName:'听你的',
    			author:'张皓宸',
    			publish:'天津人民出版社'
    		}
    	})
    })
    
  4. 例四:让现有组件作为VDOM节点的子节点:
    Vue.component('my-book',{
    	template:`
    	<div class="book">
    		<p>书名:{{bookName}}</p>
    		<p>作者:{{author}}</p>
    		<p>出版社:{{publish}}</p>
    	</div>`,
    	props:['bookName','author','publish']
    })
    Vue.component('my-com',{
    	render:h=>h('div',[
    		h('h1','2020年畅销书'),
    		h('my-book',{
    			props:{
    				bookName:'听你的',
    				author:'张皓宸',
    				publish:'天津人民出版社'
    			}
    		})
    	])
    })
    

三、创建具备插槽的VDOM节点:

注意:具备插槽的VDOM节点不能使用箭头函数。

  1. 创建具备一个匿名插槽的VDOM节点。
//DOM结构格式
Vue.component('my-dom',{
	template:`<div><slot></slot></div>`
})

Vue.component('my-com',{
	render(h){
		return h('div',this.$slots.default)
	}
})
//使用
<my-com>我被放入匿名插槽中</my-com>

(1)创建一个下列格式的VDOM节点:<div><span style=“color:#ff5857;”><slot></slot></span></div>

render(h){
		return h('div',[
			h('span',{
				style:{color:'#ff5857'}
			})
		])
	}

(2)创建一个超级链接的VDOM节点。

<my-com url="https://www.baidu.com">百度百科</my-com>
Vue.component('my-com',{
	template:`
	<div>
		<a href="url"><slot></slot></a>
	</div>`,
	props:['url'],
	render(h){
		return h('div',[
			h('a',{
				attrs:{href:this.url}
			},this.$slots.default)
		])
	}
})
var vm = new Vue({
	el:'#demo',
})
  1. 例2:创建具备多个具名插槽的VDOM节点。
<my-com>
	<span slot="abc">我是abc</span>
	<span slot="xyz">我是xyz</span>
</my-com>
template:`
<div>
	<h1><slot name="abc"></slot></h1>
	<h2><slot name="xyz"></slot></h2>
</div>`,
render(h){
	return h('div',[
		h('h1',this.$slots.abc),
		h('h2',this.$slots.xyz)
	])
}
  1. 例3:创建具备一个默认作用域插槽的VDOM节点。
<my-com>
	<template slot-scope="sc">
		{{sc.a}}+{{sc.b}}+{{sc.c}}={{sc.a+sc.b+sc.c}}
	</template>
</my-com>
Vue.component('my-com',{
	render(h){
		return h('div',this.$scopedSlots.default({
			a:100,
			b:200,
			c:33
		}))
	}
})
  1. 例4:创建具备多个具名的作用域插槽的VDOM节点。
<my-com>
	<template slot-scope="sc" slot="abc">
		{{sc.a}}+{{sc.b}}={{sc.a+sc.b}}
	</template>
	<template slot-scope="sc" slot="xyz">
		{{sc.x}}+{{sc.y}}
	</template>
</my-com>
Vue.component('my-com',{
	render(h){
		return h('div',[
			h('h1',this.$scopedSlots.abc({a:100,b:50})),
			h('h2',this.$scopedSlots.xyz({x:'A',y:'B'}))
		])
	}
})
### 虚拟DOM技术的基本概念 虚拟DOM是一种用于提升Web应用性能的技术,其核心思想是在内存中创建一个轻量级的JavaScript对象表示真实的DOM结构[^1]。这个对象被称为虚拟DOM树,它是真实DOM的一个副本,但不直接与浏览器交互。 当应用程序的状态发生变化时,开发者不会直接修改真实DOM,而是更新虚拟DOM树。随后,框架会比较新旧两棵虚拟DOM树之间的差异(这一过程称为Diff算法),并仅将必要的更改同步到真实DOM上,从而减少了频繁的DOM操作所带来的开销[^2]。 --- ### 工作原理 虚拟DOM的工作流程通常分为以下几个方面: 1. **构建阶段** 当首次渲染页面时,框架会在内存中生成一棵完整的虚拟DOM树作为初始状态[^3]。 2. **更新阶段** 如果数据模型发生改变,框架会基于新的数据重新生成一颗全新的虚拟DOM树,并将其与之前的版本进行对比。此过程中使用的Diff算法能够高效地识别出最小的变化集合[^4]。 3. **渲染阶段** 基于计算得到的差异集,框架只针对那些确实发生了变化的部分执行相应的DOM操作,而不是重绘整个界面。这种方式显著提高了效率,尤其是在复杂的UI场景下表现尤为明显。 以下是简单的虚拟DOM实现示例: ```javascript class VNode { constructor(tagName, props, children) { this.tagName = tagName; this.props = props || {}; this.children = children || []; } } function render(vnode) { const el = document.createElement(vnode.tagName); Object.keys(vnode.props).forEach(key => el.setAttribute(key, vnode.props[key])); vnode.children.forEach(child => { if (typeof child === 'string') { el.appendChild(document.createTextNode(child)); } else { el.appendChild(render(child)); } }); return el; } ``` --- ### 优点 1. **性能优化** 减少了不必要的DOM操作次数,通过批量处理和局部更新的方式提升了整体性能[^1]。 2. **跨平台支持** 虚拟DOM本质上是纯JavaScript对象,因此它可以脱离具体的运行环境,在不同平台上复用相同的逻辑,比如服务端渲染、移动端App开发等[^2]。 3. **抽象化能力** 它不仅限于操作HTML文档,还可以扩展至其他领域,例如小程序、桌面应用程序甚至嵌入式设备上的图形界面[^3]。 4. **保证性能下限** 即使面对复杂的应用场景或者未经过精细调优的情况,虚拟DOM仍然能够维持相对稳定的性能水平。 --- ### 缺点 尽管虚拟DOM带来了诸多好处,但也存在一些局限性: 1. **额外开销** 维护虚拟DOM本身需要消耗一定的资源,特别是在大规模动态数据环境下可能成为瓶颈[^2]。 2. **学习曲线陡峭** 对初学者而言理解其内部机制以及如何有效利用并非易事[^3]。 3. **非最佳解法** 并不是所有情况下都适合采用虚拟DOM方案;某些特定条件下传统的手动DOM操控反而更加简单直接且高效[^4]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值