1. Virtual DOM
- 介绍
- virtual DOM实际上是一个JavaScript对象,它相比于DOM运算会小很多。
- 当状态发生变化的时候,前后的virtual DOM会进行diff运算,这样可以只更新部分改变了的DOM,而不是全部重绘。
- 作用
- Vue2使用了virtual DOM来更新DOM,这样减小le开销。
- 虽然我们一般将组件模板写在template中,但是当Vue编译的时候,都会解析为virtual DOM。
- VNode
- virtual DOM是使用VNode描述的,可以理解成VNode就是virtual DOM。
- VNode的创建
- VNode要映射到真实的DOM需要经过一系列create、diff、patch等过程。
- VNode的创建是通过createElement方法完成的。
2. Render函数
virtual dom
- 在状态发生变化时,Vue会创建virtual dom,virtual dom实际上是一个javasc对象(这是为了只更新发生变化的部分,而不用全部重绘)
- 对于正常的DOM节点
<div id="main"> <p>文本</p> </div>对应的JavaScript对象(也就是virtual dom会是这样)
var vNode = { tag: 'div', attributes: { id: 'main', }, children: [ //子节点(p标签) ], }
- vNode对象通过一些特定选项描述了真实的DOM结构。
为什么要使用render函数
有时候template不如render函数简洁,尤其当有大段逻辑重复的HTML的时候
<!DOCTYPE html> <html> <head></head> <body> <div id="app"> <anchor :level="2" :title="特性"></anchor> <!-- 点击这个组件会跳转到页面中对应锚点位置 --> <script type="text/x-template" id="anchor"> <!-- x-template写法,这样可以把组件的template部分拿出来写 --> <div> <h1 v-if="level === 1"> <a :href="'#' + title"> <!-- 这里使用的是锚点链接 --> <slot></slot> </a> </h1> </div> <div> <h2 v-if="level === 2"> <a :href="'#' + title"> <slot></slot> </a> </h2> </div> <div> <h3 v-if="level === 3"> <a :href="'#' + title"> <slot></slot> </a> </h3> </div> </script> </div> </body> <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script> <script> Vue.component('amchor',{ template: '#anchor', props: { level: { type: number, required: true, }, } }) const app = new Vue({ el: '#app', }) </script> </html>render函数与template的对比(使用template和render写的同一个组件)
- 在这个例子中,template明显比render易读,所以绝大多数情况我们还是选择template,只有少数情况使用render。
<!DOCTYPE html> <html> <head></head> <body> <div id="app"> <ele></ele> <script type="text/x-template" id="ele"> <div id="element" :class="{show: isVisible}" @click="handleClick"> 文本内容 </div> </script> </div> </body> <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script> <script> Vue.component('ele',{ template: '#ele', data: () => { return{ isVisible: true, } }, methods: { handleClick(){ console.log('click'); }, }, }) const app = new Vue({ el: '#app', }) </script> </html> <!DOCTYPE html> <html> <head></head> <body> <div id="app"> <ele></ele> </div> </body> <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script> <script> Vue.component('ele',{ render: function(createElement){ return createElement( 'div', { class: { //作用类似于v-bind:class的API show: isVisible, }, attrs: { //HTML的属性 id: 'element', }, on: { //绑定事件 click: this.handleClick }, }, '文本内容' //第3个参数实际上是子节点(也包括标签内的内容) ) }, data: () => { return { isVisible: true, } }, methods: { handleClick(){ console.log('click') }, }, }) const app = new Vue({ el: '#app' }) </script> </html>