我们决定逐渐从淘汰赛转向使用 typescript 的 vue 3 组合 api,并且我正在尝试了解变异道具的反模式。我有一个正在执行其预期工作的工作组件,但基本上我想确认它的编写方式是建议的方法。
一个相当简单的例子是一个复选框列表组件,上面有一个切换开关:
我最大的问题是我在 AppList.vue 中所做的是否正确,我正在做 const internalModel = toRef(props.selected ?? []);
以获得不可变的组件中的变量和 selectedHandler
- 事件和 toggleAll
- 计算为发出 OUT,但在这里我手动保留 selected
和 <代码>内部模型代码>同步。对于同一件事使用两个变量感觉很麻烦,但同时它确实有意义,因为内部模型不需要干扰视图。
我知道 vuejs.org 上有一个示例,其中可以在 v-model
上使用数组来表示多个复选框,但它不在组件内部或作为道具,因此它不完全是同样,这感觉更复杂。我花了一天中的大部分时间试图让它正确,但没有那么多 vue 3 搜索结果,对于这个特定问题我根本没有找到任何结果。
HomeView.vue:
fooselected: {{ fooSelected }}模板>
组件/Applist.vue:
<脚本设置lang="ts"> 从“vue”导入{计算,toRef}; 导出接口项{ 身份证号; 名称:字符串; } const 道具 = DefineProps<{ 项目:项目[]; 已选择?:编号[]; }>(); const internalModel = toRef(props.selected ?? []); const 发出 = DefineEmits<{ '更新:选定':[选定:数字[]]; }>(); const selectedHandler = (e: 事件) => { const target =标签> 标签> 模板> 脚本设置lang="ts">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); } 别的 { 发出('更新:所选',[]); 内部模型.value = []; } }, }); 脚本> <模板> <标签> <输入类型=“复选框”v-model=“toggleAll”/> 全部切换 标签> 内部模型:{{内部模型}} 模板>
- <标签> > id {{ item.name }}; 标签>
在我看来,这可以以某种更简单的方式完成。
fooItems
可能应该有一个初始状态“已检查”。在
selectedHandler
中,只需调用emit()
即可。toggleAll
最终将创建一个与internalModel
配合使用的函数。这是一个示例Vue SFC Playground。
HomeView.vue:
AppList.view: