vue3 报错 Set operation on key “xxx“ failed: target is readonly.

报错场景再现

由于原来做的组件代码行太多并且有个抽屉组件被复制粘贴3次,按照我的习惯,同段代码被引用3次以上就要做组件抽离方便后续维护

需求

把抽屉部分抽离,显隐由父组件控制

于是,问题出现当初次打开抽屉,好好的,但让抽屉关闭时,抽屉是关闭了,但弹出警告Set operation on key “showDrawer” failed: target is readonly. 并且再也不能打开

代码
抽屉组件

<template>
  <div>
	<ElDrawer
	    v-model="showDrawer"
	    :size="50%"
	    title="签批进度"
	  >
	 ....
	 </ElDrawer>
  </div>
</template>

<script lang="ts" setup>
const props = defineProps({
  showDrawer: Boolean
})
const { showDrawer } = toRefs(props)
</script>

父组件

<template>
 <div>
  ...
  <button @click="openDrawer">签批进度</button>
  ...
  <!-- 签批进度 -->
  <drawer-c :show-drawer="drawerr" />
  ...
 </div>
</template>

<script lang="ts" setup>
const drawerr = ref(false)

function openDrawer() {
	drawerr.value = true
}
</script>

找寻原因

在点击关闭时,由于双向绑定,vue去更改抽屉组件showDrawer,想将其真变假,但其只读不让改,所以报错并阻止了修改,但抽屉为什么能在showDrawer没变的情况下关闭,这个没去研究

探索解决 办法

看到前辈们也曾遇到同样的问题,一开始共找到两种解决办法

办法
v-model 改为 :model-value
若用的是antd,需要调下版本

以上两个办法,对我都没作用,首先,方法一就是从双向绑定变为单向绑定,这是不报错了,但还是不能再次打开了

解决

寻寻觅觅,查阅很多文章了解原理,终于解决,话不多说,上代码

抽屉组件

<template>
  <div>
	<ElDrawer
	    v-model="visibleD "
	    :size="50%"
	    title="签批进度"
	  >
	 ....
	 </ElDrawer>
  </div>
</template>

<script lang="ts" setup>
const props = defineProps({
  showDrawer: Boolean
})
const { showDrawer } = toRefs(props)
const emits = defineEmits(['toggleStatus'])
//先用自己的属性
const visibleD = ref(false)
const toggle = (newVal: boolean) => (visibleD.value = newVal)
//监测showDrawer触发visibleD
watch(
  () => showDrawer .value,
  (newVal) => {
    toggle(newVal)
  }
)
//监测visibleD触发showDrawer的变值方法
watch(
  () => visibleD.value,
  (newVal) => {
    console.log('visible=------', newVal)
    emits('toggleStatus', newVal)
  }
)
</script>

父组件

<template>
 <div>
  ...
  <button @click="openDrawer">签批进度</button>
  ...
  <!-- 签批进度 -->
  <drawer-c :show-drawer="drawerr" @toggle-status="switchDrawerr" />
  ...
 </div>
</template>

<script lang="ts" setup>
const drawerr = ref(false)

function openDrawer() {
	drawerr.value = true
}
function switchDrawerr(show: boolean) {
  drawerr.value = show
}
</script>

至此问题解决!

参考过的博客
vue3源码:探秘 toRefs/ref
Vue3 了解这 20 个响应式 API,写码如有神

  • 11
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值