Vue是否有深度unref方法?解决Map类型响应式数据修改问题
如何深度复制响应式Map以避免直接修改原模型?
场景代码
TypeScript类型定义
interface Translation { title: string; description?: string; } interface Note { translations: Map<string, Translation>; // 其他属性... }
模态框模板
<fieldset v-for="([language, translation]) in translationsRef"> <legend>{{ language }}</legend> <p> <label for="title">Title </label> <input type="string" id="title" v-model="translation.title"> </p> <p> <label for="description">Description </label> <textarea id="description" v-model="translation.description"></textarea> </p> </fieldset>
当前实现逻辑
const model = defineModel<Note|null>(); const translationsRef: Ref<Map<string, Translation>|null> = ref(null); watch(model, (newNote) => { if (newNote != null) { translationsRef.value = toValue(newNote.translations); showModal.value = true; } });
问题
当前输入框中输入内容时会直接更新原model中的数据,因为toValue/unref只是浅处理,无法切断原响应式Map及其内部Translation对象的引用。需要找到能深度解除响应式、复制出独立数据的方法。
解决方法
方法1:手动深度复制
遍历原Map,为每个Translation对象创建独立副本,再组装成新Map:
watch(model, (newNote) => { if (newNote != null) { const copiedTranslations = new Map<string, Translation>(); newNote.translations.forEach((translation, lang) => { // 复制Translation对象属性,解除响应式绑定 copiedTranslations.set(lang, { title: translation.title, description: translation.description }); }); translationsRef.value = copiedTranslations; showModal.value = true; } });
方法2:使用structuredClone(现代环境支持)
如果你的运行环境支持结构化克隆(大部分现代浏览器、Node.js 17+),可以直接用structuredClone深度复制整个Map:
watch(model, (newNote) => { if (newNote != null) { translationsRef.value = structuredClone(newNote.translations); showModal.value = true; } });
该方法会自动复制Map及内部所有可序列化的对象,无需手动遍历。
说明
unref和toValue的作用只是获取响应式对象的原始值,但原模型中的Map本身(或其内部的Translation对象)依然是响应式引用类型,直接赋值会导致新的ref依然指向原数据。只有通过创建新的容器+复制内部属性,才能彻底切断与原响应式数据的关联,实现编辑时不影响原模型的效果。
内容的提问来源于stack exchange,提问作者Thomas
相关产品推荐
相关产品推荐

