还记得 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 的使用啦.
来源: http://www.jianshu.com/p/45abfd439010