Vue.js渲染函数介绍
Vue.js 模板非常强大,几乎可以完成您在应用程序中需要的所有内容。 但是,有一些用例,通常涉及基于输入或槽值的动态组件创建,渲染函数更好地服务。
那些来自 React 世界的人可能对渲染函数非常熟悉。 React 组件是用它们构建的,通常通过 JSX。 虽然 Vue 渲染函数也可以使用 JSX 编写,但我们将坚持使用原始 JS,以便您可以更轻松地了解 Vue 组件系统的基础。
值得注意的是,Vue.js 的模板实际上会在构建时编译为渲染函数。 模板只是在渲染函数之上提供了一种方便且熟悉的语法糖。 尽管渲染功能更强大,但在可读性方面经常受到影响。
创建组件
具有 渲染功能 的组件没有模板标记或属性。 相反,他们定义了一个名为 render 的函数,该函数接收 createElement(renderElement: String | Component, definition: Object, children: String | Array) 参数(通常别名为 h[ X209X],出于某种原因,归咎于 JSX)并返回使用该函数创建的元素。 其他一切都保持不变。
ExampleComponent.vue
export default {
data() {
return {
isRed: true
}
},
/*
* Same as
* <template>
* <div :class="{'is-red': isRed}">
* <p>Example Text</p>
* </div>
* </template>
*/
render(h) {
return h('div', {
'class': {
'is-red': this.isRed
}
}, [
h('p', 'Example Text')
])
}
}
替换速记指令
Vue 模板带有各种方便的功能,以便为模板添加基本逻辑和绑定功能。 渲染函数无权访问这些。 相反,它们必须用纯 Javascript 实现,对于大多数指令来说,这相当简单。
v-如果
这很容易。 不要使用 v-if,只需在 createElement 调用周围使用普通的 Javascript if (expr) 语句即可。
v-for
v-for 可以使用许多 Javascript 迭代方法中的任何一种来实现,for、for-of、Array.map、Array.filter 等 。 您可以以非常有趣的方式将这些组合起来以实现过滤或状态切片,而无需计算属性。
例如,您可以替换
<template>
<ul>
<li v-for="pea of pod">
{{pea.name}}
</li>
</ul>
</template>
和
render(h) {
return h('ul', this.pod.map(pea => h('li', pea.name)));
}
v型
要记住的一件好事是,v-model 只是将属性绑定到 value 并在触发 input 事件时设置数据属性的简写. 不幸的是,渲染函数没有这样的简写。 您必须自己实现它,如下所示。
render(h) {
return h('input', {
domProps: {
value: this.myBoundProperty
},
on: {
input: e => {
this.myBoundProperty = e.target.value
}
}
})
}
这相当于:
<template> <input :value="myBoundProperty" @input="myBoundProperty = $event.target.value"/> </template>
或者
<template> <input v-model="myBoundProperty"/> </template>
v-绑定
属性和属性绑定放在元素定义中,如 arttrs、props 和 domProps(类似 value 和 内部HTML )。
render(h) {
return h('div', {
attrs: {
// <div :id="myCustomId">
id: this.myCustomId
},
props: {
// <div :someProp="someonePutSomethingHere">
someProp: this.someonePutSomethingHere
},
domProps: {
// <div :value="somethingElse">
value: this.somethingElse
}
});
}
附带说明一下,类和样式绑定直接在定义的根处处理,而不是作为 attrs、props 或 domProps。
render(h) {
return h('div', {
// "class" is a reserved keyword in JS, so you have to quote it.
'class': {
myClass: true,
theirClass: false
},
style: {
backgroundColor: 'green'
}
});
}
开启
事件处理程序也直接添加到元素定义中,在 on (或 nativeOn 中,与组件的 v-on.native 具有相同的效果)。 )
render(h) {
return h('div', {
on: {
click(e) {
console.log('I got clickeded!')
}
}
});
}
修饰符可以在处理程序内部实现:
- .stop -> e.stopPropagation()
- .prevent -> e.preventDefault()
- .self -> if (e.target !== e.currentTarget) 返回
键盘修饰符
- .[TARGET_KEY_CODE] -> if (event.keyCode !== TARGET_KEY_CODE) 返回
- .[MODIFIER] -> if (!event.MODIFIERKey) 返回
特殊属性
Slots 可以通过 this.$slots 作为 createElement() 节点的数组来访问。
作用域插槽存储在 this.$scopedSlots[scope](props: object) 作为返回 createElement() 节点数组的函数。
享受渲染功能赋予您的新的、无限的力量! 请小心谨慎使用。