v-model 绑定代码编辑器需满足接收 modelValue prop 并触发 update:modelValue 事件;主流封装如 vue-codemirror 已支持,轻量场景可手动封装 textarea,结构化数据需用 computed 桥接,注意避免 :value 冲突、初始化时机错误及事件未声明等问题。

v-model 绑定代码编辑器内容,核心是让编辑器的值与 Vue 响应式变量保持双向同步。Vue 3 中不直接操作 DOM,而是依赖编辑器组件是否支持标准 v-model 协议(即接收 modelValue prop、触发 update:modelValue 事件)。
确认编辑器组件是否原生支持 v-model
主流 Vue 3 代码编辑器封装(如 vue-codemirror、@uiw/react-codemirror 的 Vue 封装版、或自研基于 CodeMirror 6 的组件)基本都已适配 Vue 3 的 v-model 规范。只要它满足以下两点,就能直接用 v-model:
- 接收名为 modelValue 的 prop(类型通常为 string)
- 在内容变化时,通过 $emit('update:modelValue', newValue) 通知父组件
例如使用 vue-codemirror:
<codemirror v-model="code" :extensions="extensions" />
立即学习“前端免费学习笔记(深入)”;
这里 code 是一个 ref 或 computed 响应式变量,编辑器内部会自动读取它的值并更新它。
手动封装简易代码编辑器(input/textarea 场景)
若仅需轻量级语法高亮(比如用 prismjs + textarea),且不依赖完整编辑器引擎,可自行封装并支持 v-model:
子组件(CodeEditor.vue):
<template>
<textarea
:value="modelValue"
@input="$emit('update:modelValue', $event.target.value)"
spellcheck="false"
class="code-editor"
/>
</template>
<script setup>
defineProps(['modelValue'])
defineEmits(['update:modelValue'])
</script>
父组件中即可:
<CodeEditor v-model="sourceCode" />
处理非字符串内容(如 AST、JSON 对象)
v-model 默认绑定字符串,但若编辑器底层操作的是结构化数据(例如 JSON 编辑器解析后输出对象),需额外桥接:
- 用
computed({ get, set })包一层:get 返回 JSON.stringify,set 解析字符串并校验 - 避免直接把对象传给 modelValue —— 这会导致响应式失效或序列化问题
示例:
const editorContent = computed({
get() { return JSON.stringify(jsonData.value, null, 2) },
set(str) {
try { jsonData.value = JSON.parse(str) }
catch (e) { /* 忽略非法 JSON */ }
}
})
然后在模板中:
<codemirror v-model="editorContent" />
注意几个常见断连点
即使写了 v-model,内容也不更新?检查这些:
- 别混用 :value 和 v-model:二者冲突,v-model 会覆盖 :value
-
编辑器初始化时机晚于 modelValue 赋值:确保
code = ref('')在组件 setup 中已声明,而非异步后才赋值 -
未监听 update:modelValue 事件:子组件必须
defineEmits(['update:modelValue']),否则事件被静默丢弃 -
TS 类型未对齐:若 props 声明为
modelValue?: string但传入 undefined,可能触发空值渲染异常


















