(1)什么是Render函数app
先来看一个场景,在博客网中,通常有一级标题、二级标题、三级标题...,为了方便分享url,它们都作成了锚点,点击后,会将内容加载网址后面,以#分隔。dom
例如‘特性’是一个<h2>标签,内容含有一个<a href='#特性'>#</a>的连接,点击后url便带有了锚点信息,别人打开时会直接聚焦到‘特性’所在的位置。若是将其封装成一个组件,通常写法会这样:函数
<div id="app"> <app-demo :level="level" title="特性"> 特性{{level}} </app-demo> </div> <script> Vue.component('app-demo',{ template:` <div> <h1 v-if="level === 1"> <a :href=" '#' + title "> <slot></slot> </a> </h1> <h2 v-if="level === 2"> <a :href=" '#' + title "> <slot></slot> </a> </h2> <h3 v-if="level === 3"> <a :href=" '#' + title "> <slot></slot> </a> </h3> <h4 v-if="level === 4"> <a :href=" '#' + title "> <slot></slot> </a> </h4> <h5 v-if="level === 5"> <a :href=" '#' + title "> <slot></slot> </a> </h5> <h6 v-if="level === 6"> <a :href=" '#' + title "> <slot></slot> </a> </h6> </div> `, props:{ level:{ type:Number, require:true }, title:{ type:String, default:'' } } }); var app = new Vue({ el:'#app', data:{ level:2 } }); </script>
效果:ui
分析:这样写没有什么错误,只是缺点太明显,代码冗长,组件的template代码大多都是重复的,只是heading标题元素的级别不一样,再者必须插入一个根元素<div>,这是组件的要求。this
template写法在大多数时候很好用,但这里有些别扭。咱们更像按照拼接字符串的形式来构造heading元素,好比"h"+this.leavel。在Render函数能够这样作。编码
<div id="app"> <app-demo :level="level" title="特性"> 特性{{level}} </app-demo> </div> <script> Vue.component('app-demo',{ props:{ level:{ type:Number, require:true }, title:{ type:String, default:'' } }, render(createElement){ return createElement( 'h'+this.level, [ createElement( 'a',{ domProps:{ href:'#'+this.title } }, this.$slots.default ) ] ) } }); var app = new Vue({ el:'#app', data:{ level:2 } }); </script>
Render函数经过createElement参数来建立Virtual Dom虚拟Dom,结构精简了不少。url
(2)CreateElement用法 spa
①基本参数code
CreateElement构成了Vue虚拟Dom的模板,它有3个参数:第一个参数是必选的,能够是HTML标签、组件、函数;第二个是可选的数据对象,在template使用;第三个是子节点,也是可选参数,用法一致。component
以往在template里,咱们都是在组件的标签上使用形容v-bind:class、v-bind:style额、v-on:click等这样的指令。到Render函数后,都将其写到了数据对象里,好比下面的组件,使用传统的template写法为
<div id="app"> <ele></ele> </div> <script> Vue.component('ele',{ template:` <div id="element" v-bind:class="{show:show}" v-on:click="handleClick"> 文本内容 </div> `, data(){ return { show:true } }, methods:{ handleClick:function(){ console.log('您点击了') } } }); var app = new Vue({ el:'#app' }); </script>
使用Render改写后的代码为
<div id="app"> <ele></ele> </div> <script> Vue.component('ele',{ /* template:` <div id="element" v-bind:class="{show:show}" v-on:click="handleClick"> 文本内容 </div> `, */ render:function(createElement){ return createElement( 'div',/* 第一个参数是必选的,能够是HTML标签、组件、函数*/ { /*第二个是可选的数据对象,在template使用*/ /*一、动态绑定class,等价于:class*/ class:{ 'show':this.show }, /* 二、普通HTML特性 */ attrs:{ id:'element' }, /* 三、给div绑定click点击事件 */ on:{ click:this.handleClick } }, '文本内容'/*第三个是子节点,也是可选参数*/ ) }, data(){ return { show:true } }, methods:{ handleClick:function(){ console.log('您点击了') } } }); var app = new Vue({ el:'#app' }); </script>
就此例来讲,template写法比Render函数写法更加简洁,因此要适当使用Render,不然只会增长编码负担。
.