<p>我們決定逐漸從淘汰賽轉向使用 typescript 的 vue 3 組合 api,並且我正在嘗試了解變異道具的反模式。我有一個正在執行其預期工作的工作組件,但基本上我想確認它的編寫方式是建議的方法。 </p>
<p>一個相當簡單的例子是一個複選框清單元件,上面有一個切換開關:</p>
<p>我最大的問題是我在AppList.vue 中所做的是否正確,我正在做<code>const internalModel = toRef(props.selected ?? []);</code> 以獲得不可變的元件中的變數和<code>selectedHandler</code> - 事件和<code>toggleAll</code> - 計算為發出OUT,但在這裡我手動保留<code>selected</code> 和<程式碼>內部模型</程式碼>同步。對於同一件事使用兩個變數感覺很麻煩,但同時它確實有意義,因為內部模型不需要幹擾視圖。 </p>
<p>我知道vuejs.org 上有一個範例,其中可以在<code>v-model</code> 上使用數組來表示多個複選框,但它不在組件內部或作為道具,因此它不完全是一樣,感覺更複雜。我花了一天中的大部分時間試圖讓它正確,但沒有那麼多 vue 3 搜尋結果,對於這個特定問題我根本沒有找到任何結果。 </p>
<p>HomeView.vue:</p>
<p>
<pre class="brush:html;toolbar:false;"><script set lang="ts">
import { ref } 從 'vue';
import AppList, { type Item } from '@/components/AppList.vue';
const fooItems = ref<Item[]>([
{ id: 1, name: 'foo 1' },
{ id: 2, name: 'foo 2' },
{ id: 3, name: 'foo 3' },
{ id: 4, name: 'foo 4' },
{ id: 5, name: 'foo 5' },
]);
const fooSelected = ref<number[]>([]);
</script>
<template>
<AppList :items="fooItems" v-model:selected="fooSelected"></AppList>
<div>fooselected: {{ fooSelected }}</div>
</範本></pre>
</p>
<p>組件/Applist.vue:</p>
<p>
<腳本設定lang="ts">
從“vue”導入{計算,toRef};
導出介面項{
身分證字號;
名稱:字串;
}
const 道具 = DefineProps<{
項目:項目[];
已選擇?:編號[];
}>();
const internalModel = toRef(props.selected ?? []);
const 發出 = DefineEmits<{
'更新:選定':[選定:數字[]];
}>();
const selectedHandler = (e: 事件) => {
const target = e.target;
if (props.selected && target) {
if (目標.檢查) {
發出('更新:選定',[...props.selected,Number(目標.值)]);
} 別的 {
發射(
'更新:已選擇',
props.selected.filter((i: number) => i !== Number(target.value))
);
}
}
};
consttoggleAll = 計算({
得到:() => InternalModel.value.length === props.items.length && InternalModel.value.every((s) => props.items.map((item) => item.id).includes(s)),
設定:(值)=> {
如果(值){
發射(
'更新:已選擇',
props.items.map((i) => i.id)
);
InternalModel.value = props.items.map((i) => i.id);
} 別的 {
發出('更新:所選',[]);
內部模型.值= [];
}
},
});
</腳本>
<模板>
<標籤>
>
全部切換
</標籤>
在我看來,這可以以某種更簡單的方式完成。
fooItems
可能應該有一個初始狀態「已檢查」。在
selectedHandler
中,只需呼叫emit()
即可。toggleAll
最終將建立一個與internalModel
配合使用的函數。這是一個範例 Vue SFC Playground。
HomeView.vue:
AppList.view: