讲师中心 微信公众号
AI工具推荐 视频效率加速

Vue.js 实现可编辑内容中动态插入下拉选择框的正确方式

星涛大大_3041

星涛大大_3041

发布时间:2025-12-25 21:35:02

|

240人浏览过

|

来源于php中文网

原创

Vue.js 实现可编辑内容中动态插入下拉选择框的正确方式

本文详解如何在 vue 中基于响应式数据驱动,安全、可靠地在 contenteditable 区域内插入多个受控下拉框,并准确获取其选中值,避免手动 dom 操作导致的状态不同步问题。

在 Vue 开发中,直接操作 contenteditable 的 DOM(如 appendChild 创建 <select>)会绕过 Vue 的响应式系统,导致组件状态(如 selectedOption)与真实 DOM 选中值脱节——这正是原代码中“始终返回第一个选项”的根本原因:v-model 缺失,select 元素未与数据双向绑定,getDataModel 读取的是初始静态值而非实时用户选择。

✅ 正确做法是放弃手动 DOM 插入,转而采用 Vue 推荐的声明式、数据驱动模式:将每个下拉框抽象为一个响应式对象,用 v-for 渲染,并通过 v-model 绑定选中值。这样,Vue 自动同步视图与数据,无需手动查询 select.options 或克隆节点。

以下是优化后的完整实现方案:

Html2md
Html2md

使用 Readability + Turndown 将 HTML 页面转换为干净的、Agent 友好的 Markdown。去除导航栏、广告、页脚、Cookie 横幅、社交按钮等干扰元素。支持 URL...

下载
<template>
  <div class="editor-container">
    <!-- 可编辑区域(仅用于纯文本输入,不混入表单控件) -->
    <div 
      class="content-editable" 
      contenteditable="true" 
      @input="onTextChange"
      ref="textArea"
      placeholder="在此输入普通文本..."
    ></div>

    <!-- 动态下拉框列表(独立于 contenteditable,通过视觉布局模拟嵌入效果) -->
    <div class="dropdown-zone" v-if="dropdowns.length">
      <div 
        v-for="(dropdown, index) in dropdowns" 
        :key="dropdown.id"
        class="dropdown-item"
      >
        <span class="label">下拉框 #{{ index + 1 }}:</span>
        <select 
          v-model="dropdown.selectedValue" 
          class="custom-select"
        >
          <option 
            v-for="opt in dropdown.options" 
            :key="opt.value" 
            :value="opt.value"
          >
            {{ opt.label }}
          </option>
        </select>
      </div>
    </div>

    <div class="controls">
      <button @click="addDropdown">+ 添加下拉框</button>
      <button @click="getDataModel">获取完整数据模型</button>
    </div>

    <div class="output">
      <h3>输出结果:</h3>
      <pre>{{ JSON.stringify(dataModel, null, 2) }}</pre>
    </div>
  </div>
</template>

<script>
export default {
  name: 'EditableWithDropdowns',
  data() {
    return {
      // 纯文本内容(来自 contenteditable)
      textContent: '',
      // 下拉框配置集合(每个含 options 和 selectedValue)
      dropdowns: [],
      // 全局可选选项(可复用)
      dropdownOptions: [
        { value: 'opt-1', label: '选项一' },
        { value: 'opt-2', label: '选项二' },
        { value: 'opt-3', label: '选项三' }
      ],
      // 最终结构化数据模型
      dataModel: {
        text: '',
        dropdowns: []
      }
    }
  },
  methods: {
    onTextChange(e) {
      this.textContent = e.target.innerText.trim()
    },
    addDropdown() {
      const id = Date.now() + '-' + Math.random().toString(36).substr(2, 9)
      this.dropdowns.push({
        id,
        selectedValue: this.dropdownOptions[0].value,
        options: [...this.dropdownOptions]
      })
    },
    getDataModel() {
      this.dataModel = {
        text: this.textContent,
        dropdowns: this.dropdowns.map(d => ({
          id: d.id,
          selectedValue: d.selectedValue,
          selectedLabel: this.dropdownOptions.find(o => o.value === d.selectedValue)?.label || ''
        }))
      }
    }
  }
}
</script>

<style scoped>
.editor-container {
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}
.content-editable {
  border: 1px solid #ddd;
  padding: 12px;
  min-height: 80px;
  margin-bottom: 16px;
  border-radius: 4px;
  background-color: #f9f9f9;
}
.dropdown-zone {
  margin-bottom: 16px;
}
.dropdown-item {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 8px;
}
.label {
  font-weight: 500;
  color: #555;
}
.custom-select {
  padding: 6px 10px;
  border: 1px solid #ccc;
  border-radius: 4px;
  background-color: white;
  font-size: 14px;
}
.controls {
  margin-bottom: 16px;
}
.controls button {
  margin-right: 8px;
  padding: 6px 12px;
  background-color: #007bff;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}
.controls button:hover {
  background-color: #0056b3;
}
.output {
  background-color: #f5f5f5;
  padding: 12px;
  border-radius: 4px;
  overflow-x: auto;
}
.output pre {
  margin: 0;
  font-size: 13px;
  line-height: 1.5;
}
</style>

? 关键改进说明:

立即学习“前端免费学习笔记(深入)”;

  • ✅ 状态完全受控:每个 select 通过 v-model="dropdown.selectedValue" 实时绑定,选中值变更即更新对应 dropdown 对象;
  • ✅ 结构清晰分离:纯文本(contenteditable)与交互控件(v-for 渲染的 select)逻辑解耦,规避 DOM 混淆风险;
  • ✅ 数据模型可扩展:getDataModel() 输出结构化 JSON,包含文本 + 每个下拉框的 ID、值、标签,便于后续序列化或提交;
  • ⚠️ 注意事项:若需“在光标位置插入下拉框”(如富文本编辑器场景),应使用 document.execCommand(已废弃)或现代 InputEvent + Range API 配合 v-html 安全渲染,但需额外处理 Vue 响应式劫持限制——此时建议选用 Tiptap 或 Slate 等专业编辑器框架。

本方案兼顾简洁性、可维护性与 Vue 最佳实践,是构建可控、可预测的混合编辑界面的推荐路径。

热门AI工具

更多
WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

Laper
Laper Hot

Laper是专为编剧、导演和制片人推出的 AI 原生剧本创作工具。

PixTV
PixTV Hot

PixTV是一款面向AIGC内容创作的AI视频生成工具。

UpDream
UpDream Hot

一款AI视频创作工具,主要用于哔哩哔哩推出的自研AI视频创作工具,适合需要提升相关任务效率的用户。

VibeKnow
VibeKnow Hot

一款AI视频创作工具,主要用于全球首个AI知识视频创作平台,文档、文章、网页,一键生成视频,适合需要提升相关任务效率的用户。

Lovart
Lovart Hot

一款面向视觉设计创作的AI设计平台,可通过智能体和画布工作流辅助制作海报、Logo、网页、PPT及其他视觉内容。

UP简历
UP简历 Hot

一款AI办公效率工具,主要用于基于AI技术的免费在线简历制作工具,适合需要提升相关任务效率的用户。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

相关专题

更多
json数据格式
json数据格式

JSON是一种轻量级的数据交换格式。本专题为大家带来json数据格式相关文章,帮助大家解决问题。

2135

2023.08.07

json是什么
json是什么

JSON是一种轻量级的数据交换格式,具有简洁、易读、跨平台和语言的特点,JSON数据是通过键值对的方式进行组织,其中键是字符串,值可以是字符串、数值、布尔值、数组、对象或者null,在Web开发、数据交换和配置文件等方面得到广泛应用。本专题为大家提供json相关的文章、下载、课程内容,供大家免费下载体验。

3302

2023.08.23

jquery怎么操作json
jquery怎么操作json

操作的方法有:1、“$.parseJSON(jsonString)”2、“$.getJSON(url, data, success)”;3、“$.each(obj, callback)”;4、“$.ajax()”。更多jquery怎么操作json的详细内容,可以访问本专题下面的文章。

1116

2023.10.13

go语言处理json数据方法
go语言处理json数据方法

本专题整合了go语言中处理json数据方法,阅读专题下面的文章了解更多详细内容。

3779

2025.09.10

js正则表达式
js正则表达式

php中文网为大家提供各种js正则表达式语法大全以及各种js正则表达式使用的方法,还有更多js正则表达式的相关文章、相关下载、相关课程,供大家免费下载体验。

4396

2023.06.20

js获取当前时间
js获取当前时间

JS全称JavaScript,是一种具有函数优先的轻量级,解释型或即时编译型的编程语言;它是一种属于网络的高级脚本语言,主要用于Web,常用来为网页添加各式各样的动态功能。js怎么获取当前时间呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

1355

2023.07.28

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

1758

2023.08.03

js是什么意思
js是什么意思

JS是JavaScript的缩写,它是一种广泛应用于网页开发的脚本语言。JavaScript是一种解释性的、基于对象和事件驱动的编程语言,通常用于为网页增加交互性和动态性。它可以在网页上实现复杂的功能和效果,如表单验证、页面元素操作、动画效果、数据交互等。

9963

2023.08.17

Playwright 测试失败怎么办
Playwright 测试失败怎么办

Playwright测试失败专题汇集超时、定位器匹配、浏览器提前关闭、依赖与插件配置、文件上传、SSL及Docker启动等故障文章,并介绍通过截图、报告和Trace定位错误。

20

2026.10.21

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
uni-app快速上手
uni-app快速上手

共0课时 | 0人学习

Vue 教程
Vue 教程

共42课时 | 17.2万人学习

Vue3.x 工具篇--十天技能课堂
Vue3.x 工具篇--十天技能课堂

共26课时 | 2.5万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn