Vue中contenteditable span模拟输入框如何获取值实现双向绑定
问题核心原因
contenteditable 元素本身不是Vue默认支持v-model双向绑定的表单元素,你写的{{speed}}只是单向把响应式变量渲染到span里,手动修改span内容时不会自动反向同步给speed变量。
另外补充:原生<input>完全可以实现内容自适应宽度,不需要用contenteditable模拟,下面给两种可直接运行的实现方案。
方案一:兼容你现有contenteditable写法
只需要补全双向同步逻辑即可:
- 给span绑定
input事件,输入内容时把文本转成数字更新到speed - 加监听处理加减按钮触发的
speed变化,避免变量更新后span显示不同步 - 做非数字输入的兜底,避免出现NaN异常
完整代码:
<script setup> import { ref, watch } from 'vue' const speed = ref(20) const speedInput = ref(null) const minus = () => speed.value-- const plus = () => speed.value++ // 输入内容同步到响应式变量 const onInput = (e) => { const value = parseInt(e.target.innerText.trim()) speed.value = isNaN(value) ? 0 : value } // 按钮修改值时同步回显到输入框 watch(speed, (newVal) => { if (speedInput.value && speedInput.value.innerText !== String(newVal)) { speedInput.value.innerText = newVal } }, { immediate: true }) </script> <template> <h2>Speed:</h2> <button @click="minus">−</button> <span ref="speedInput" class="input" role="textbox" contenteditable @input="onInput" ></span> <button @click="plus">+</button> </template>
方案二:原生input实现自适应宽度(推荐)
原生input的v-model绑定更稳定,不会出现contenteditable常见的光标错位、粘贴带格式、意外换行等问题,自适应宽度实现非常简单:
<script setup> import { ref, watch, onMounted, nextTick } from 'vue' const speed = ref(20) const speedInput = ref(null) const minus = () => speed.value-- const plus = () => speed.value++ // 自动适配输入框宽度 const resizeInput = () => { nextTick(() => { speedInput.value.style.width = 'auto' // 加2px冗余避免内容贴边 speedInput.value.style.width = `${speedInput.value.scrollWidth + 2}px` }) } onMounted(resizeInput) watch(speed, resizeInput) </script> <template> <h2>Speed:</h2> <button @click="minus">−</button> <input ref="speedInput" v-model.number="speed" type="number" class="speed-input" > <button @click="plus">+</button> </template> <style scoped> .speed-input { border: none; outline: none; min-width: 24px; /* 隐藏数字输入框默认上下箭头 */ -moz-appearance: textfield; } .speed-input::-webkit-outer-spin-button, .speed-input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; } </style>
优先选择方案二,符合原生表单控件的交互逻辑,踩坑概率远低于contenteditable模拟方案。
内容的提问来源于stack exchange,提问作者sam_cyan
相关产品推荐
相关产品推荐

