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

Vue.js:contenteditable容器添加文本与下拉框后选中值获取异常

问题解决:contenteditable中下拉框选中值无法正确获取

问题分析

当前代码的核心问题是:dropdowns数组里的selectedOption仅在下拉框创建时初始化,后续用户修改下拉框选中项时,没有同步更新这个值;而getDataModel方法又依赖这个数组里的旧值,导致始终拿到第一个选项。另外,克隆DOM后匹配选项的逻辑完全没必要,直接从真实DOM的select元素取当前选中值更可靠。

修复方案

直接从DOM读取选中值(更简洁,避免数据与DOM同步的潜在问题):在getDataModel方法里,遍历页面上的select元素,直接获取每个元素的当前选中值,无需依赖dropdowns数组的存储。同时优化下拉框插入位置,实现光标处插入的需求。

以下是完整修改代码:

<template>
  <div>
    <div class="content-editable" contenteditable="true" @input="onInput" ref="contentEditable"></div>
    <button @click="addDropdown">Add Dropdown</button>
    <button @click="getDataModel">Get Data Model</button>
    <div>{{ dataModel }}</div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      content: '',
      dropdownOptions: ['Option 1', 'Option 2', 'Option 3'],
      dataModel: '',
    };
  },
  methods: {
    onInput(event) {
      this.content = event.target.innerHTML.replace(/<div><br><\/div>/g, '');
    },
    addDropdown() {
      const editableDiv = this.$refs.contentEditable;
      const dropdownSelect = document.createElement('select');
      dropdownSelect.style.width = '100px';

      this.dropdownOptions.forEach((option) => {
        const dropdownOption = document.createElement('option');
        dropdownOption.value = option;
        dropdownOption.text = option;
        dropdownSelect.appendChild(dropdownOption);
      });

      // 插入到光标所在位置
      const selection = window.getSelection();
      if (selection.rangeCount > 0) {
        const range = selection.getRangeAt(0);
        range.deleteContents();
        range.insertNode(dropdownSelect);
        // 将光标移动到下拉框后方
        const newRange = document.createRange();
        newRange.setStartAfter(dropdownSelect);
        newRange.collapse(true);
        selection.removeAllRanges();
        selection.addRange(newRange);
      } else {
        editableDiv.appendChild(dropdownSelect);
      }
    },
    getDataModel() {
      const editableDiv = this.$refs.contentEditable;
      const clonedDiv = editableDiv.cloneNode(true);
      const selectElements = clonedDiv.querySelectorAll('select');

      selectElements.forEach(select => {
        // 直接获取当前选中的文本
        const selectedText = select.options[select.selectedIndex].text;
        select.replaceWith(document.createTextNode(` ${selectedText}`));
      });

      this.dataModel = clonedDiv.textContent.trim();
    },
  },
};
</script>

<style scoped>
.content-editable {
  border: 1px solid #ccc;
  padding: 10px;
  min-height: 100px;
  margin-bottom: 10px;
}
/* 优化下拉框在contenteditable中的交互 */
.content-editable select {
  pointer-events: auto;
}
</style>

额外优化说明

  • 实现了下拉框插入到光标位置的需求,替代原代码直接追加到末尾的逻辑
  • 移除了无用的dropdowns数组,减少不必要的状态维护
  • 添加了下拉框交互样式优化,避免在contenteditable中出现光标异常问题

内容的提问来源于stack exchange,提问作者Shibbir

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 14:33:07