3、渲染函数
Vue推荐在绝大多数情况下使用模板来创建你的HTML。然而在一些场景中,你真的需要JavaScript的完成编程的能力。这时你可以用渲染函数,它比模板更接近编译器。
基础:
render: function(createElement) {
// createElement函数返回结果是VNode
return createElement(
tag, // 标签名称
data, // 传递数据
children // 子节点数组
)
}
范例:用render实现heading组件
Vue.component('heading', {
props: ['level', 'tile'],
render(h) {
return h(
'h' + level,
this.$slots.default
)
}
})
虚拟DOM
Vue通过建立一个虚拟DOM来追踪自己要如何改变真实DOM。
范例:输入虚拟DOM观察结构
const vnode = h(
'h' + level,
{ attrs: { title: this.title } }, // 之前省略了title的处理
this.$slots.default
)
console.log(vnode)
createElement参数
接下来你需要熟悉的是如何在createElement函数中使用模板中的那些功能。这里是createElement接受的参数:
// @returns {VNode}
createElement(
// {String | Object | Function}
// 一个HTML标签名、组件选项对象,或者resolve了上述任何一种的一个async函数。必填项。
'div',
// {Object}
// 一个与模板中属性对应的数据对象。可选
{
// ()
},
// { String | Array }
// 子级虚拟节点(VNodes),由`createElement()`构建而成。
// 也可以使用字符串生成“文本虚拟节点”。可选。
[
"文本节点",
createElement('h1', '一则头条'),
createElement(MyComponent, {
props: {
someProp: 'foobar'
}
})
]
)
范例:处理title、添加icon
Vue.component('heading', {
props: ['level', 'title', 'icon'],
render(h) {
let children = [];
// 添加图标功能
// <svg><use xlink:use="#icon-xxx"></use></svg>
if(this.icon) {
children.push(h(
'svg',
{ class: 'icon' },
[h('use'), {attrs: {'xlink:href': '#icon-' + this.icon}}]
))
children = children.concat(this.$slots.default)
}
vnode = h(
'h' + level,
{ attrs: { this.title } }, // 之前省略了title的处理
children
)
console.log(vnode);
return vnode
}
})
函数组件
组件没有管理任何状态,也没有监听任何传递给它的状态,也没有生命周期方法时,可以将组件标记为functional
,这意味它无状态(没有响应式数据),也没有实例(没有this上下文)
Vue.component('heading', {
functional: true, // 标记函数式组件
props: ['level', 'title', 'icon'],
render(h, context) { // 上下文传参
let children = [];
// 属性获取
const {icon, title, level} = context.props
if(icon) {
children.push(h(
'svg',
{ class: 'icon' },
[h('use', { attrs: {'xlink:href': '#icon-' + icon} })]
))
// 子元素获取
children = children.concat(context.children)
}
vnode = h(
'h' + level,
{ attrs: {title} },
children
)
console.log(vnode)
return vnode
}
})