- VDOM的第一个目的:完成在Vue下实现DOM操作的功能。
- VDOM的第二个目的:实现比原生的DOM操作还要快的页面渲染机制。
- VDOM的本质:利用js对象模拟DOM节点。
一、利用render函数代替组建中的template
-
render函数的功能:在创建组件是实现DOM结构的生产,和template完全一致。
-
格式:
Vue.component('my-com',{ render:function(creatElement){ return creatElement('div'); } }) //相当于:template:`<div></div>`
-
简化格式:
Vue.component('my-com',{ render:h=>h('p') })
-
创建一个带有文本内容的VDOM节点
<div>我今天学习了虚拟DOM技术</div>
Vue.component('my-com',{ render:h=>h('div','我今天学习了虚拟DOM技术') })
-
创建一个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 } })
- 创建一个带有子节点的VDOM节点:
格式:h('div',[h(),h()])
例如:
render:h=>h('div',{ class:{box:true} },[ h('h1','我是一级标题'), h('p','我是一个段落'), h('a',{ attrs:{href:'#'} },'百度百科') ])
- 创建一个带有子节点的VDOM节点:
二、根据现有的组件创建VDOM节点:
- 例一:根据现有组件
my-com
创建DOM节点。Vue.component('my-book',{ template:`<div class="book">你和我的倾城时光</div>`, }) Vue.component('my-com',{ render:h=>h('my-book') })
- 例二:根据带有插槽的现有组件创建VDOM节点。
Vue.component('my-book',{ template:`<div class="book"><slot></slot></div>`, }) Vue.component('my-com',{ render:h=>h('my-book',[h('div','我和我的VUE')]) })
- 例三:根据带有参数的现有组件创建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:'天津人民出版社' } }) })
- 例四:让现有组件作为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节点不能使用箭头函数。
- 创建具备一个匿名插槽的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',
})
- 例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)
])
}
- 例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
}))
}
})
- 例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'}))
])
}
})