Vue 推荐在绝大多数情况下使用模板(template)来创建你的 HTML。然而在一些场景中,你真的需要 JavaScript 的完全编程的能力。这时你可以用渲染函数,它比模板更接近编译器。
平时我们写真实的DOM结构,可以用html编写一个文档,然后提交给浏览器解析成我们想要的页面。同时也可以通过DOM 的api innerHTML告诉浏览器结构是什么,还可以用createElement来构建DOM树,以hello world为例,html和innerHTML api 对DOM结构的描述都是“<h1>hello world</h1>
”,但是用createElement就变成了这个样子:
var h1 = document.createElement('h1');
var hw = document.createTextNode('hello world')
h1.appendChild(hw);
document.body.appendChild(h1);
这就是描述一个DOM结构的方式,你可以用一个html文件,一个字符串,或者一段js代码,但是他们都是在做同一件事,就是告诉浏览器该怎么渲染你想要的页面。现在我们回头看vue,在构建vue实例时,我们要写一个叫template的属性,里面是一个html一样的字符串。那么,vue对这个字符串做什么了?事实上,vue拿它构建了虚拟DOM。
render函数
在创建Vue实例的过程中,如果传入的选项中有template和render两个属性,render会有更高的优先级:
new Vue({
template:'...',
render:f(){
}//优先级高
})
这就表示,Vue在看到你要用render函数描述虚拟DOM时。会很高兴,因为它不用自己编译你给他的模板字符串来得到render函数,省力又省心。同时它会丢给你一个函数,这个函数是你构建虚拟DOM所需要的工具,官网上给他起了个名字叫createElement。还有约定的简写叫h,vm中有一个方法_c,也是这个函数的别名。
下面我们先来说说这个构建虚拟Dom的工具,createElement函数。参考官网createElement-参数,首先思考一个普通的html元素会传递给我们哪些信息,
<h1 class='foo'>hello world</h1>
,没错,我们可以得到3部分有效信息:
1.这个元素的标签名–h1
2.这个元素有什么属性/事件,class,style,onclick,name,id…
3.这个元素有什么子元素,这里是一个文本节点 ‘hello world’
上面提到,render函数和模板字符串是描述虚拟DOM树的两种方式,那么用createElement函数来描述就变成了下面这样:
craeteElement('h1', {
class,style,on,attrs:{
name,id}, 'hello world'})
//这里,第三个参数还有玄机,接收的参数十分灵活,详情参考官网关于这三个参数的描述
下面我们分别说一下createElement函数的三个参数类型
第一个参数:
这个参数是必选,也就是必须要传
参数类型是一个字符串或者一个对象一个函数。像下面这样:
'div'//字符串
{
data:{
},
methods:{
},
mounted:{
}
}//一个组件选项对象
function(){
return 'div'}//返回上面两种
第二个参数:
这个参数可选
一个数据对象,包括对根元素html属性的描述,和组件属性的描述,详情见官网,比方说你要描述这么一个节点:
{
'class':{
color:true},
props:{
height:'1.4m', weight:'50kg'},
on:{
move:function handle(){
}}
}
第三个参数:
这个参数是可选
可以是一个字符串或者一个数组,数组就表示这个根元素不止有一个虚拟子节点了。还是举个例子:
<h1> <span style="color:red">hello</span> <span>world</span> </h1>
整体来看下面这个例子,就相当于一个h1标签包含了两个span标签,并且打印出,hello world:
vm = new Vue({
render:createElement => createElement('h1',[
createElement('span',{
style:{
color:'red'}},'hello'),
createElement('span','world')
])
});
以上对应的html
<h1>
<span style = "color : red;"> hello </span>
<span>world</span>
</h1>
因为h也可以代表createElement所以,也可以这样写:
render: h => {
return h('span',
['This is created by ',
h('a', 'render'),
' function'
])
}
这个就相当于
<span>
This is created by
<a>render</a>
function
</span>
render函数结合插槽slot数组用会比较方便。
详情看例子vue官网