[VUE/Ant Design Vue] 渲染函式— 可以像 React 一樣用 JavaScript 渲染節點
最近開始使用 Ant Design,因為是在 VUE 的專案所以我們是用 Ant Design Vue。
在看文件時就發現範例中很常出現 h(),是之前很少用到的 VUE 渲染函式。
h()
的用途:要在 <template>
加一個 vnode 節點時,不需要先建一個 xxx.vue 元件檔案,直接用 h()
就可以達成。
可是沒實際用過,對 h()
就是一直呈現一知半解的狀態😂
多虧專案開始使用 Ant Design 讓我有機會使用到了!
我遇到的情境
因為這個畫面我想使用 Ant Design Vue Select 選擇器 的 dropdownRender
這個 api,在列表最上面新增一個被 fixed 且可以點擊前往其他分頁的選項。
原本 Ant Design Vue 的範例 是這樣,固定在最下面:
參考 Ant Design Vue 的範例把固定元素搬到最上面會是這樣:
<template #dropdownRender="{ menuNode: menu }">
<div
class="flex justify-between items-center"
@mousedown="e => e.preventDefault()"
@click="handleClickCreateBot"
>
<span>
前往新增機器人
</span>
<SvgIcon />
</div>
<a-divider style="margin: 4px 0" />
<v-nodes :vnodes="menu" />
</template>
<script lang="ts">
import { defineComponent } from 'vue';
export default defineComponent({
components: {
VNodes: (_, { attrs }) => {
return attrs.vnodes;
},
},
setup() {
const handleClickCreateBot = () => {
console.log('handleClickCreateBot');
};
return {
handleClickCreateBot,
};
},
});
</script>
讓我最不懂的就是 <script> 裡這段:
components: {
VNodes: (_, { attrs }) => {
return attrs.vnodes;
},
}
VNodes
這到底是專有名詞還是什麼?它是做什麼的??
我照著範例直接把 code 貼進專案中是可以成功沒錯~
但我們的專案是用 <script setup>
寫的,我很想把這段搬進來,可是沒弄懂實在不知道怎麼搬😂
一開始方向整個錯,一直在查 VNodes
以為他是專有名詞😅
也確實可以查到跟 VNode
有關的文章、官方文件之類的。
但原來這個 VNodes
原來根本就不是專有名詞,它就是在寫一個可以放進 Vue 節點的元件!
我真的是研究了一整個下午還是搞不懂,到公司立刻找資深同事討論,才透過在 <script setup>
的寫法看懂了!
在 <script setup>
改寫成這樣:
const VNodes = (_, { attrs }) => {
return attrs.vnodes;
};
用 h()
寫法是這樣:
const VNodes = (_, { attrs }) => h('div', attrs.vnodes);
突然整個好懂多了!
而且 VNodes
可以是其他名字,他就是元件名稱。
例如改寫成:
const VNodeMenu = (_, { attrs }) => h('div', attrs.vnodes);
對應的 Vue 節點就會是:
<v-node-menu :vnodes="menu" />
<v-node-menu>
渲染出的是下拉選單的選項列表:
成功🥳
最後的小閒聊~
為什麼 Ant Design Vue 的範例這麼喜歡用渲染函式這種寫法?
覺得很不像 VUE 的風格🤔
跟同事閒聊才發現,應該是因為 Ant Design 本身是用 React 寫成的,所以直接改寫成 Vue 就會變成用 React 腦寫 Vue 的感覺,充滿了渲染函式😂
有同事可以一起討論真的好棒,讓我除了弄懂寫法,還懂了背後的因果,真是太有趣啦!
不過我不太愛在 Vue 裡使用渲染函式,覺得這寫法看起來好怪有點醜不好讀😝
除非是非不得已(例如用到 React 風格的 Framwork),不然還是寫一個 component 比較好。