背景:将全选复选框的值用pinia进行状态管理,其中使用计算属性计算isAllSelected值,在点击全选复选框报错。
报错:TypeError: 'set' on proxy: trap returned falsish for property 'xxx'
报错原因:
由于在 Vue 的响应式系统中对计算属性进行直接赋值导致的。计算属性是只读的,不能直接修改。isAllSelected
是一个计算属性,但你尝试对其进行赋值,这会导致错误。
检查代码发现,复选框这块是直接拿了`element-plus`的代码:其中用`v-model`对数据进行双向绑定,违反了“计算属性不可赋值”的原理,因此报错。
<template>
<el-checkbox-group v-model="checkList">
<el-checkbox label="Option A" />
<el-checkbox label="Option B" />
<el-checkbox label="Option C" />
<el-checkbox label="disabled" disabled />
<el-checkbox label="selected and disabled" disabled />
</el-checkbox-group>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
const checkList = ref(['selected and disabled', 'Option A'])
</script>
解决方案:
先将`v-model`改成checked,只进行单向的绑定,全选按钮的确可以正确显示,但是点击全选按钮不起作。原因:checked属性不能进行动态显示,它只能决定初始显示的值。
之后改成用`:model-value`,成功绑定。
分析原因:
在使用 el-checkbox
和 pinia
进行状态管理时,v-model
和 :model-value
的行为有所不同。
v-model
的工作原理
v-model
是 Vue 的一个语法糖,它实际上是以下两个指令的组合:
:value
:用于绑定输入控件的值。@input
:用于监听输入控件的值变化事件。
当你使用 v-model
绑定一个 ref
或 reactive
对象时,Vue 会自动处理值的更新和事件的触发。然而,pinia
管理的 ref
对象是不可变的,这意味着你不能直接通过 v-model
来修改它,因为 v-model
会尝试直接修改 ref
的值,而这在 pinia
中是不允许的。
:model-value
的工作原理
:model-value
是一个属性绑定,它只是将值传递给组件,但不会尝试修改它。当你使用 :model-value
绑定一个 pinia
管理的 ref
对象时,组件会读取这个值,但不会尝试修改它。这意味着你可以安全地使用 :model-value
来绑定 pinia
管理的 ref
对象,而不会触发修改操作。