vue3组件中使用render函数
为了制作一个下面这样的自定义组件,满足: 传入值作为heading的层级,并将自定义中的内容作为heading的内容。
<anchored-heading :level="1">Hello world!</anchored-heading>
如果不用render()函数,那么你的代码可能是这样的:
const { createApp } = Vue
const app = createApp({})
app.component('anchored-heading', {
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>
`,
props: {
level: {
type: Number,
required: true
}
}
})
使用render(),你的代码可能是这样的:
const { createApp, h } = Vue
const app = createApp({})
app.component('anchored-heading', {
render() {
return h(
'h' + this.level, // tag name
{}, // props/attributes
this.$slots.default() // array of children
)
},
props: {
level: {
type: Number,
required: true
}
}
})
我们再来看一个例子:
Goal
Implement the "example" component which given the following usage:
<example :tags="['h1', 'h2', 'h3']"></example>
which renders the expected output:
<div>
<h1>0</h1>
<h2>1</h2>
<h3>2</h3>
</div>
Solution
Vue.component('example', {
props: ['tags'],
render (h) {
// Note that the second argument (data object) can be omitted, and the
// children argument can accept strings or numbers besides Array of vnodes.
// api 可以参考 https://v3.vuejs.org/api/global-api.html#h
return h('div', this.tags.map((tag, i) => h(tag, i)))
}
})
我们还可以将一个组件作为第一个参数传入render函数。下面的这个例子中,我们将一个[functional组件](https://v3.vuejs.org/guide/render-function.html#functional-components)作为参数传入了render函数, 并将render函数结果作为这个组件的内容传递出去:
Goal
-
Implement a
Foo
component which simply renders<div>foo</div>
, and aBar
component which simply renders<div>bar</div>
(using render functions, obviously). -
Implement an
<example>
component which renders theFoo
component or theBar
component based on itsok
prop. Forif ok
is true, the final rendered dom should be<div>foo</div>
. -
Implement a button in the root component that toggles
<example>
betweenFoo
andBar
by controlling itsok
prop.
Solution
const Foo = {
render (h) {
return h('div', 'foo')
}
}
const Bar = {
render (h) {
return h('div', 'bar')
}
}
Vue.component('example', {
props: ['ok'],
render (h) {
return h(this.ok ? Foo : Bar)
}
})
new Vue({
el: '#app',
data: { ok: true }
})