Vue3 是可以用 JSX 語法直接寫的, 大體可以從 https://sfc.vuejs.org/ 的示例看到,
其中 <div>
會編譯為 h('div')
, 具體參考 https://vuejs.org/guide/extra... .
完整的元件定義形如:
import { defineComponent, PropType } from 'vue';
import { onMounted, ref, watch } from 'vue';
const App = defineComponent({
name: "App"
props: {
appId: {
type: String as PropType<string>,
default: '',
},
},
emits: [],
setup(props, {emit, expose, slots}) {
return () => (
<div>TODO</div>
);
},
});
export default App;
其中
name
除錯中元件的名字,props
需要用這樣的寫法用 Object 格式傳入, 型別部分用PropType<T>
做標記,emits
可以用字串格式指定事件, 而emit
函式從引數中拿到,slots
也是從引數當中拿到,expose
也是從引數當中得到的,- 注意最終的 render 函式, 範圍與
setup
函式有區別, 其中setup
函式只會被執行一次, 而render
函式可能多次執行. 而需要響應式追蹤的邏輯, 需要寫在setup
函式里邊, 否則行為不能達到預期,
有了 JSX, 原有的 v-if
和 v-else
可以和 React 一樣直接寫了,
<div>
{!!a ? <span>true</span> : null}
</div>
v-model
較為特殊, 轉換後需要手動繫結 modelValue
的行為:
<A modelValue={a.value} onUpdate:modelValue={(v) => a.value = v} />
expose
的用法, 傳入一個物件, 參考 https://www.vuemastery.com/bl...
expose({ reset })
@click
寫法統一變成 on
加上大寫首字元,
<div onClick={() => console.log("TODO")} >
v-slots
用法比較複雜, 參考 https://github.com/vuejs/babe... :
const A = (props, { slots }) => (
<>
<h1>{ slots.default ? slots.default() : 'foo' }</h1>
<h2>{ slots.bar?.() }</h2>
</>
);
有個 slot/template 寫法比較繞, 定製插槽的寫法:
<NSelect>
<template #optionEmptyRender>
<div>Demo</div>
</template>
</NSelect>
寫成:
<NSelect
v-slots={{
optionEmptyRender: () => {
return (
<div>Demo</div>
);
},
}}
/>