文章目录
在Vue 2
中,render
函数是一种更底层的方式来创建虚拟DOM
节点。相比于模板编译,render
函数提供了更大的灵活性和编程能力。
一、render 函数讲解
render
函数即渲染函数,它是个函数render
函数的参数也是个函数,即createElement
render
函数的返回值VNode
VNode
(virtual node
虚拟节点),也就是我们要渲染的节点。
二、render 函数优点
- Render函数可以处理一些复杂的案例,例如:渲染函数需要发起异步请求,进行数据处理后才能渲染页面。而模板中无法实现此类操作。
- 在开发时,可以使用JavaScript的逻辑处理来生成虚拟DOM节点,这可以帮助开发者更好的控制组件的渲染逻辑。
- Render函数输出的是虚拟DOM节点,所以可以在开发时,更好地掌握组件的渲染效果,并根据需要进行优化。
三、render函数的参数createElement
createElement
是 render
函数 的参数,这是一个工厂函数,用于创建VNode。
它本身也是个函数,并且有三个参数
- 一个
HTML
标签名、组件选项对象,或者 resolve 了上述任何一种的一个 async 函数,类型:{ String | Object | Function }
,必填项 - 一个与模板中
attribute
对应的数据对象,类型:{ Object }
,可选 - 子级虚拟节点 (
VNodes
),由createElement()
构建而成,也可以使用字符串来生成 “文本虚拟节点”,类型:{ String | Array }
,可选
export default {
data() {},
/**
* render: 渲染函数
* @param {Function} createElement
* @returns {VNode}
*/
render: (createElement) => {
return createElement(
// 1. 第一个参数,要渲染的标签名称【必需】
"div",
// 2. 第二个参数,1中渲染的标签的属性【可选】,不使用此参数,用 null 占位
{
// 与 `v-bind:class` 的 API 相同,
// 接受一个字符串、对象或字符串和对象组成的数组
class: {
foo: true,
bar: false,
},
// 与 `v-bind:style` 的 API 相同,
// 接受一个字符串、对象,或对象组成的数组
style: {
color: "red",
fontSize: "14px",
},
// 普通的 HTML attribute
attrs: {
id: "foo",
},
// 组件 prop
props: {
myProp: "bar",
},
// DOM property
domProps: {
innerHTML: "baz",
},
// 事件监听器在 `on` 内,
// 但不再支持如 `v-on:keyup.enter` 这样的修饰器。
// 需要在处理函数中手动检查 keyCode。
on: {
click: this.clickHandler,
},
// 仅用于组件,用于监听原生事件,而不是组件内部使用
// `vm.$emit` 触发的事件。
nativeOn: {
click: this.nativeClickHandler,
},
// 自定义指令。注意,你无法对 `binding` 中的 `oldValue`
// 赋值,因为 Vue 已经自动为你进行了同步。
directives: [
{
name: "my-custom-directive",
value: "2",
expression: "1 + 1",
arg: "foo",
modifiers: {
bar: true,
},
},
],
// 作用域插槽的格式为
// { name: props => VNode | Array<VNode> }
scopedSlots: {
default: (props) => createElement("span", props.text),
},
// 如果组件是其它组件的子组件,需为插槽指定名称
slot: "name-of-slot",
// 其它特殊顶层 property
key: "myKey",
ref: "myRef",
// 如果你在渲染函数中给多个元素都应用了相同的 ref 名,
// 那么 `$refs.myRef` 会变成一个数组。
refInFor: true,
},
// 3. 第三个参数,1中渲染的标签的子元素数组【可选】,不使用此参数,用 null 占位 或不写
[
createElement("span", null, "友情链接"),
createElement(
"a",
{
attrs: {
href: "https://www.baidu.com",
},
},
"百度"
),
]
);
},
};
3.1. createElement的别名h
将h
作为createElement
的别名是 Vue
生态系统中的一个通用惯例
render: (h) => h(App),
四、render 函数与template标签
render
函数和template
一样,都是用来创建html
模板的,但是有些场景里使用template
实现起来会使代码冗余且复杂,因此产生了render
函数。
注意,
render
和template
标签无法一起使用,即当你在项目里使用了template
标签的时候,render()
函数将会失效。
<template>
<div>123</div>
</template>
<script>
export default {
data() {},
render: function (createElement) {
return createElement(
"div",
{
attrs: { id: "box" },
class: { demo: true },
style: { color: "pink" },
},
"Hello World"
);
},
};
</script>
在上述代码中,因为定义了template
标签,如果再使用render()
函数去直接写一个虚拟DOM,这样子会发现只渲染了123
,而没有显示Hello World
,这是因为这两个不能够共存,而template
的优先级明显高于render()