[VUE/Ant Design Vue] 渲染函式— 可以像 React 一樣用 JavaScript 渲染節點

Juju 的自學筆記
5 min readJul 12, 2024

--

最近開始使用 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 比較好。

--

--

No responses yet