Vue3响应式异常:reactive包裹computed值报只读错误如何解决
报错原因
- 不带setter的
computed返回值默认是只读属性,你直接将jobsParams这个只读computed实例传入reactive(),本质是让reactive代理了这个只读实例,而非代理它的返回值对象 - 子组件通过
v-model修改params的属性时,等价于直接修改这个被代理的只读computed内部值,因此触发只读报错,和你有没有直接修改jobsParams没有关系
正确实现方案
根据你的业务需求从两种场景中选择即可:
场景1:修改参数后需要同步更新Vuex store中的值
使用带setter的可写computed实现双向绑定,修改时主动提交mutation更新store:
<template> <Pagination v-model="params" /> </template> <script> import { defineComponent, computed } from 'vue' import { useStore } from 'vuex' export default defineComponent({ name: 'Jobs', setup(){ const store = useStore() const params = computed({ get() { return store.getters['Jobs/getParams'] }, set(newVal) { // 替换成你实际对应的Vuex mutation名称即可 store.commit('Jobs/setParams', newVal) } }) return { params } } }) </script>
场景2:仅需要从store拿初始值,后续修改不需要同步回store
初始化reactive时直接取computed的当前值,相当于拷贝一份独立的响应式对象:
<template> <Pagination v-model="params" /> </template> <script> import { defineComponent, reactive, computed, watch } from 'vue' import { useStore } from 'vuex' export default defineComponent({ name: 'Jobs', setup(){ const store = useStore() const jobsParams = computed(() => store.getters['Jobs/getParams']) // 直接取computed的value拷贝初始值,生成独立响应式对象 const params = reactive({...jobsParams.value}) // 如果需要同步store后续的params更新,可加以下监听逻辑,不需要则删除 watch(jobsParams, (newVal) => { Object.assign(params, newVal) }, { deep: true }) return { params } } }) </script>
内容的提问来源于stack exchange,提问作者Riza Khan
相关产品推荐
相关产品推荐

