Appearance
Vue推荐在绝大多数情况下使用模版来创建你的HTML。然而在一些场景中,你真的需要JavaScript的完全编程的能力。这时可以用渲染函数render函数(字符串模版的代替方案,允许你发挥JavaScript最大的编程能力),它比模版更接近编译器。
js
<base-component :level="level">
<p>
This is {{ level }} 标题的内容
</p>
</base-component>
export default {
components: {
BaseComponent
},
data () {
return {
level: 1
}
},
methods: {
changeLevel() {
this.level ++;
}
}
}
当开始写一个只能通过level prop动态生成标题的组件时,可能很快想到这样实现
js
<template>
<h1 v-if="level === 1">
<slot></slot>
</h1>
<h2 v-else-if="level === 2">
<slot></slot>
</h2>
<h3 v-else-if="level === 3">
<slot></slot>
</h3>
<h4 v-else-if="level === 4">
<slot></slot>
</h4>
<h5 v-else-if="level === 5">
<slot></slot>
</h5>
<h6 v-else-if="level === 6">
<slot></slot>
</h6>
</template>
这里用模版并不是最好的选择:不但代码冗长,而且在每一个级别的标题中重复书写了, 在要插入元素时还要再次重复。虽然模版在大多数组中都非常好用,但是显然它在这里就不太合适了。那么我们用render函数重写上面的例子:
js
props: {
level: {
type: Number,
default: 0,
require: true
}
}
<script>
export default {
render(h) {
return h(
'h' + this.level,
null,
this.$slot.default
)
}
}
</script>
节点、树以及虚拟DOM
html
<div>
<h1>My title</h1>
some text content
<!-- TODO: Add tagline -->
</div>
当浏览器读到这些代码时,它会建立一个“DOM节点”树来保持追踪所有内容,如同你会画一张家谱树来追踪家庭成员的发展一样。上述HTMl对应的DOM节点树入下图所示:
每个元素都是一个节点。每段文字也是一个节点。甚至注释也都是节点。一个节点就是页面的一个部分。就像家谱树一样,每个节点都可以有孩子节点(也就是说每个部分都可以包含其它的一些部分)。高效的更新这些节点会是比较困难的,不过不必动手完成这个工作。只需要告诉Vue你希望页面上的HTML是什么,这可以是是在一个模版里
js
<h1> {{ blogTitle }} </h1>
render: function(h) {
return h('h1', null, this.blogTitle);
}
虚拟DOM
Vue通过建立一个虚拟DOM来追逐自己要如何改变真实DOM
js
return h('h1', null, this.blogTitle)
h函数其实返回的不是一个实际的DOM元素。它更准确的名字可能是createNodeDescription,因为它所包含的信息会告诉Vue页面上需要渲染什么样的节点,包括及其子节点的描述信息。我们把这样的节点描述为“虚拟节点virtual node,”也常简写它为VNode。“虚拟DOM”是我们对由Vue组件树建立起来的整个VNode树的称呼。
h函数的参数
js
// @returns {VNode}
h(
// {String | Object | Function}
// 一个 HTML 标签名、组件选项对象,或者
// resolve 了上述任何一种的一个 async 函数。必填项。
'div',
// {Object}
// 一个与模板中 attribute 对应的数据对象。可选。
{},
// {String | Array}
// 子级虚拟节点 (VNodes),由 `createElement()` 构建而成,
// 也可以使用字符串来生成“文本虚拟节点”。可选。
[
'先写一些文字',
createElement('h1', '一则头条'),
createElement(MyComponent, {
props: {
someProp: 'foobar'
}
})
]
)