You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 12:48:18