还记得Vue2.x中组件的 render 方法么?我们除了可以用template来进行模板化的渲染输出,还可以用 render 方法进行编程式的渲染。模板有着看起来更易于阅读、更直观的优点,而 render 方法有着更好的灵活性。在Vue3.0中依然保留了这个功能,而且还为符合Composition API的编程理念做了调整。
让我们来用 render 方法改写一下之前的计数器代码,看起来就会是这样的:
const { createApp, ref, h } = Vue
// 计数器组件
const Counter = {
setup() {
const countOps = useCount()
return { ...countOps }
},
render() {
return [
h('div', { class: 'counter-display' }, [
h('span', { class: 'counter-label' }, '恭喜你,你已经写了'),
h('span', { class: 'counter-text' }, this.count),
h('span', { class: 'counter-label' }, '斤代码!'),
]),
h('div', { class: 'counter-btns' }, [
h('button', { class: 'btn', onClick: this.increase }, '写一斤'),
h('button', { class: 'btn', onClick: this.reset }, '删库啦'),
])
]
}
}
function useCount() {
const count = ref(0)
const increase = () => { count.value++ }
const reset = () => { count.value = 0 }
return { count, increase, reset }
}
// 根组件
const App = {
render() {
return h('div', { class: 'container' }, [
h('h3', '计数器示例'),
h(Counter)
])
}
}
// 启动
const container = document.querySelector('#app')
const app = createApp()
app.mount(App, container)
我们可以看到变化的地方:原先的 template 不见了,取而代之的是一个 render 方法,方法中通过 h 函数创建虚拟DOM节点(这个h 函数和Vue2.0中 render 方法的参数 createElement 是类似的)。如果我们使用了 JSX,那 render 方法中更可以使用 JSX 的语法来编写虚拟DOM的创建,看起来会是这样:
const App = {
render() {
return (
<div className="container">
<h3>计数器示例</h3>
<Counter />
</div>
)
}
}
然而,有心的朋友可能会从上面这些代码中观察到一个问题,我们还是在 render 方法中使用到了 this 对象,当然这在实现功能上面并不存在什么问题,但是,这跟Composition API提倡的函数式做法的理念并不一致。
其实,新的框架已经考虑到了这一点,并给出了方案:在 setup 方法中返回这个 render 方法。我们的 Counter 组件如果按照上面的方案改写一下,就会是这样:
const Counter = {
setup() {
const { count, increase, reset } = useCount()
return () => [
h('div', { class: 'counter-display' }, [
h('span', { class: 'counter-label' }, '恭喜你,你已经写了'),
h('span', { class: 'counter-text' }, count.value),
h('span', { class: 'counter-label' }, '斤代码!'),
]),
h('div', { class: 'counter-btns' }, [
h('button', { class: 'btn', onClick: increase }, '写一斤'),
h('button', { class: 'btn', onClick: reset }, '删库啦'),
])
]
}
}
如此一来,我们就完全摆脱对 this 的使用啦。