shallowRef 应用于富文本编辑器实例(如 wangEditor 的 IDomEditor),避免 Vue 深度响应式追踪引发性能问题;大文本内容用 ref 存储,通过 @onChange 同步更新;v-if 隐藏时须调用 destroy() 销毁实例。

shallowRef 在富文本编辑器中不是用来缓存大文本的,而是用来安全持有编辑器实例(Editor 对象),避免 Vue 对其做深度响应式追踪——这恰恰能防止因编辑器内部复杂状态引发的性能问题或意外响应。
大文本内容(比如 ... 这类 HTML 字符串)本身是普通字符串,直接用 ref 或 computed + v-model 绑定即可,不需要、也不适合用 shallowRef 存储。
下面说清楚三个关键点:
为什么编辑器实例必须用 shallowRef
- wangEditor 的
IDomEditor实例内部有大量嵌套对象、函数、DOM 引用、事件监听器等。 - 若用
ref(editor),Vue 会尝试递归将其转为响应式,造成:- 内存占用上升
- 初始化变慢
- 可能触发无限循环或警告(如
Maximum recursive updates)
-
shallowRef只让.value本身可响应,内部结构完全跳过响应式系统,正适合这种“只读引用、不追踪内部”的场景。
const editorRef = shallowRef<idomeditor null>(null) // ✅ 正确 // 不要写成: // const editorRef = ref<idomeditor null>(null) // ❌ 潜在风险</idomeditor></idomeditor>
大文本内容该怎么存和更新
HTML 字符串内容应走标准响应式流程:
- 用
ref或computed双向绑定v-model - 编辑器内容变更时,通过
@onChange或@onCreated中监听editor.txt.html()获取最新值 - 提交前直接取
valueHtml.value即可,无需额外“缓存”
const valueHtml = ref<string>('<p>初始内容</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill11189" title="Element Plus UI Vue3"><img
src="https://img.php.cn/upload/skill/001/246/273/6adaf20dbae7c507.jpg" alt="Element Plus UI Vue3" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/skill11189" title="Element Plus UI Vue3" class="overflowclass">Element Plus UI Vue3</a>
<p class="overflowclass">Element Plus Vue3 桌面组件库。在开发 Vue 3.x 页面时调用,使用 Element Plus 组件(如 el-button、el-input、el-form、el-table 等)。</p>
</div>
<a rel="nofollow" href="/xiazai/skill11189" title="Element Plus UI Vue3" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>') // ✅ 文本内容用 ref
// 编辑器创建后,可手动同步一次(可选)
const handleCreated = (editor: IDomEditor) => {
editorRef.value = editor
// 首次回显:若 props 传了初始 HTML,可设 editor.txt.html(props.modelValue)
if (props.modelValue) editor.txt.html(props.modelValue)
}
// 内容变化时更新 ref(推荐用 @onChange,比定时轮询更准)
const handleChange = () => {
valueHtml.value = editorRef.value?.txt.html() || ''
}</string>
动态显示/隐藏时注意彻底销毁
如果富文本区域被 v-if 控制显隐(比如表单切换、弹窗打开关闭),每次 v-if="false" 后组件卸载,必须销毁实例:
onBeforeUnmount(() => {
editorRef.value?.destroy() // ✅ 必须调用,释放 DOM 和事件
editorRef.value = null
})
不用 v-show,因为 v-show 只切 display,编辑器实例还在内存里跑,容易内存泄漏或状态错乱。
不复杂但容易忽略
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!









