使用 v-html 指令渲染的标签, 标签内绑定的 click 事件不生效

背景

在项目开发中,实现用户友好的输入交互是提升用户体验的关键之一。例如,在客服对话框中,其中有包含多个快捷选项用于快速问答,每个快捷选项都是一个可点击的按钮,并需要绑定点击事件来执行相应操作。然而,直接在 v-html 渲染的标签内绑定的 click 事件不生效。这是因为 v-html 只是将 HTML 字符串插入到 DOM 中,并不会编译其中的 Vue 指令。

v-html 工作原理

  1. 基本用途

    • v-html 指令用于将一个字符串作为 HTML 插入到 DOM 中。

    • 这意味着任何包含在字符串中的 HTML 都会被原样插入,而不会被 Vue 编译。

  2. 工作原理

    • 当 Vue.js 执行 v-html 指令时,它会将字符串解析为 DOM 节点,并将其插入到指定的位置。

    • 这个过程是通过浏览器的 DOM API 完成的,具体来说是通过 innerHTML 属性。

    • 由于插入的是原生的 DOM 节点,而不是经过 Vue 编译的虚拟 DOM,因此其中的 Vue 指令不会被识别和执行。

代码示例

<template><div><el-dialog width="68%" :visible.sync="isShow" :before-close="close" class="kefu" :show-close="false":close-on-click-modal="false"><div class="kefu-con"><i class="el-icon-close close" @click="close" /><div class="header"><img :src="kefuImg" alt=""><div class="title">小奶龙智能问答助手</div></div><div class="container" ref="container"><div class="content" ref="content"><div v-for="item in messageForm"><div class="reply-container" v-if="item.type === 'reply'"><div class="reply-content"><div class="img-con"><img :src="kefuImg" alt=""></div><div class="reply"><div v-if="item.isXml" v-html="item.content"></div><p v-else>{{ item.content }}</p></div></div></div><div class="qs-container" v-if="item.type === 'qs'"><div class="qs-content"><div class="qs"><p>{{ item.content }}</p></div></div></div></div></div></div><div class="footer"><img :src="kefuImg" alt=""><div class="question-con"><el-input class="ipt" v-model="question" placeholder="请输入想咨询的问题"></el-input><el-button class="btn" type="warning" round @click="send">发送</el-button></div></div></div></el-dialog></div>
</template><script>
import { getAnswer } from '@/api/checkin.js';
export default {data() {return {isShow: false,kefuImg: require("@/assets/images/headshot.png"),question: '',messageForm: [{content: "<p>您好, 我是您的小奶龙,你的智能助手。 你可以问我编码相关的问题,也可以一起更高效、更高质量地完成编码工作。比如 “<span class='quick' style='color: #5094d5;cursor: pointer;' @click='quick'>动态路由实现</span>”, “<span class='quick' style='color: #5094d5;cursor: pointer;' @click='quick'>移动端适配</span>” 等等一些问题。</p>",type: "reply", // reply 回答  qs 问题isXml: true,},{content: '动态路由实现',type: "qs", // reply 回答  qs 问题isXml: false,}]}},methods: {quick() {console.log('quick方法触发了::: ');},show() {this.isShow = true;},close() {this.isShow = false;},send() {// console.log('this.$refs.content.scrollHeight::: ', this.$refs.content.scrollHeight);let NewQuestion = this.question.trim();if (NewQuestion === '') {return;}// console.log('this.question::: ', NewQuestion);this.messageForm.push({content: NewQuestion,type: 'qs',isXml: false,});setTimeout(()=>{// 模拟异步请求this.question = '';})}},
}
</script>

页面展示如下,点击快捷问答选项 “动态路由实现” 没有触发 quick 事件
在这里插入图片描述

解决方法

1. 在父容器上监听点击事件,并通过事件对象判断点击的目标元素。

<template><div class="reply" @click="handleProxyClick"><div v-html="htmlContent"></div></div>
</template>
<script>
export default {data() {return {htmlContent: '<button class="my-button">点击我</button>'};},methods: {handleProxyClick(event) {console.log('event::: ', event);// 获取触发事件的目标元素  event 事件对象const target = event.target;},}
}
</script>

事件对象里 eventtarget 就是鼠标点击的元素
在这里插入图片描述

2. 如果渲染多个标签,可以通过声明 id 属性或者 class 类名 来判断。

<template><div class="reply" @click="handleProxyClick"><div v-html="htmlContent"></div></div>
</template>
<script>
export default {data() {return {htmlContent: '<button id="222" class="my-button">点击我</button>'};},methods: {handleProxyClick(event) {// 获取触发事件的目标元素  event 事件对象const target = event.target;console.log("target.classList::: ", target.classList);console.log("target.id::: ", target.id);},}
}
</script>

如图所示
在这里插入图片描述

代码实现

<template><div><el-dialog width="68%" :visible.sync="isShow" :before-close="close" class="kefu" :show-close="false":close-on-click-modal="false"><div class="kefu-con"><i class="el-icon-close close" @click="close" /><div class="header"><img :src="kefuImg" alt=""><div class="title">小奶龙智能问答助手</div></div><div class="container" ref="container"><div class="content" ref="content"><div v-for="item in messageForm"><div class="reply-container" v-if="item.type === 'reply'"><div class="reply-content"><div class="img-con"><img :src="kefuImg" alt=""></div><div class="reply" @click="handleProxyClick"><div v-if="item.isXml" v-html="item.content"></div><p v-else>{{ item.content }}</p></div></div></div><div class="qs-container" v-if="item.type === 'qs'"><div class="qs-content"><div class="qs"><p>{{ item.content }}</p></div></div></div></div></div></div><div class="footer"><img :src="kefuImg" alt=""><div class="question-con"><el-input class="ipt" v-model="question" placeholder="请输入想咨询的问题"></el-input><el-button class="btn" type="warning" round @click="send">发送</el-button></div></div></div></el-dialog></div>
</template><script>
import { getAnswer } from '@/api/checkin.js';
export default {data() {return {isShow: false,kefuImg: require("@/assets/images/headshot.png"),question: '',messageForm: [{content: "<p>您好, 我是您的小奶龙,你的智能助手。 你可以问我编码相关的问题,也可以一起更高效、更高质量地完成编码工作。比如 “<span class='quick' style='color: #5094d5;cursor: pointer;' @click='quick'>动态路由实现</span>”, “<span class='quick' style='color: #5094d5;cursor: pointer;' @click='quick'>移动端适配</span>” 等等一些问题。</p>",type: "reply", // reply 回答  qs 问题isXml: true,},{content: '动态路由实现',type: "qs", // reply 回答  qs 问题isXml: false,}]}},methods: {handleProxyClick(event) {// 获取触发事件的目标元素  event 事件对象const target = event.target;// 判断目标元素是否包含指定类名if (target.classList.contains('quick')) {// 传递目标元素的文本内容this.quick(target.outerText);}},quick(text) {console.log('quick方法触发了::: ');this.question = text;// 发送this.send();},show() {this.isShow = true;},close() {this.isShow = false;},send() {let NewQuestion = this.question.trim();if (NewQuestion === '') {return;}this.messageForm.push({content: NewQuestion,type: 'qs',isXml: false,});setTimeout(() => {// 模拟异步请求this.question = '';})}},
}
</script>

实现效果
在这里插入图片描述

总结

在项目开发中,某些对话框中的快捷选项使用 v-html 渲染,导致标签内绑定的 click 事件不生效。为了解决这一问题,可以通过在父容器上使用事件代理(如 @click 事件监听器),并通过事件对象判断点击的目标元素,从而调用相应的处理方法,确保点击事件能够正常触发。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/456317.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据类型【MySQL】

文章目录 建立表查看表删除表数据类型floatcharvarcharchar&&varchar 时间日期类型enum和setenum和set查找 建立表 mysql> create table if not exists user1(-> id int ,-> name varchar (20) comment 用户名 ,-> password char (32) comment 用户名的…

软考(中级-软件设计师)算法分析篇(1024)

三、算法设计与分析 #1024程序员节|正文# 一、分治法 1.1 分而治之 对于一个规模为n的问题&#xff0c;若该问题可以容易的解决&#xff08;比如说规模较小&#xff0c;则直接解决&#xff0c;否则将其分解为k个规模较小的问题&#xff0c;这些子问题相互独立且与原问题形…

数组类型应用举例

在main.cpp里输入程序如下&#xff1a; #include "stdio.h" //使能printf()函数 #include <stdlib.h> //使能exit(); #define My_array_Size 10 //定义用My_array_Size代替 unsigned char My_array[My_array_Size]; //声明数组My_arra…

集群分发脚本

我的后端学习大纲 我的Linux环境搭建学习大纲 8.2.scp安全拷贝: 1.命令格式&#xff1a;scp -r $pdir/$fname $user$host:$pdir/$fname2.具体命令&#xff1a; scp -r jdk1.8.0_321/ rootHadoop104:/opt/module 3.实际操作&#xff1a; 3.1.在hadoop2和hadoop3&#xff0c;had…

Verilog 0x01 基础

硬件描述语言 0x00 数电逻辑符号 与 & 或 | 异或 ^ 同或 ~^0x01 基本结构 1.1 线网&#xff08;wire&#xff09; wire 类型表示硬件单元之间的物理连线&#xff0c;由其连接的器件输出端连续驱动 如果没有驱动元件连接到 wire 型变量&#xff0c;缺省值一般为 “Z” …

h5页面与小程序页面互相跳转

小程序跳转h5页面 一个home页 /pages/home/home 一个含有点击事件的元素&#xff1a;<button type"primary" bind:tap"toWebView">点击跳转h5页面</button>toWebView(){ wx.navigateTo({ url: /pages/webview/webview }) } 一个webView页 /pa…

数据结构——队列和栈

目录 一、栈 1、概念与结构 2、栈的结构与初始化 3、入栈 4、出栈 5、取栈顶元素 6、取栈中有效元素个数 7、栈是否为空 二、队列 1、概念与结构 2、队列的结构与初始化 3、入队列 4、出队列 5、取队头数据 6、取队尾数据 7、队列判空 8、队列中有效元素个数 练习题目链 一…

(一)Mysql篇---Mysql整体架构

MySql框架浅析 首先&#xff0c;上一张图先让各位看看大致结构&#xff1a; 从上到下&#xff0c;依次说一下结构&#xff1a; 连接层&#xff1a;这里主要是处理客户端和数据库连接的&#xff0c;直接使用的Tomcat的连接池&#xff0c;可以调整最大连接数&#xff1b; 服务…

精益思维在新能源汽车研发中的应用体现

近年来&#xff0c;新能源汽车作为绿色出行的重要载体&#xff0c;其研发与生产模式正经历着深刻的变革。精益思维&#xff0c;这一源自制造业的管理理念&#xff0c;正逐步渗透并深刻影响着新能源汽车的研发过程&#xff0c;不仅提升了产品质量与生产效率&#xff0c;还促进了…

汽车级DC-DC转换器英飞凌TLF35584

上汽荣威都在用的汽车级DC-DC转换器英飞凌TLF35584 今天平台君从IPBrain数据库中给大家带来的一款由Infineon(英飞凌)推出的一款多路输出安全电源芯片,具备高可靠性和安全性。适用于汽车电子系统中的多种应用场景,如车身控制、安全气囊、防抱死制动系统,电子稳定控制系统等。…

数据结构:堆的应用

堆排序 假定有一组数据极多的数&#xff0c;让我们进行排序&#xff0c;那我们很容易想到一种经典的排序方法&#xff0c;冒泡排序&#xff0c;我们对冒泡排序的时间复杂度进行分析&#xff1a; 显然&#xff0c;冒泡排序的时间复杂度是O&#xff08;n^2&#xff09;,当数据量…

软考(中级-软件设计师)计算机系统篇(1024)

#1024程序员节|正文# 六、树和二叉树 6.1 树的基本概念 描述结果结点的度子结点的个数树的度最大结点的度叶子结点没有子结点的结点内部结点除根结点和叶子结点外的结点父节点有子结点的结点子节点有父结点的结点兄弟节点有同一个父结点的结点层次4层 6.2 二叉树的基本概念…

【Javaee】网络原理—TCP协议的核心机制

前言 TCP/IP五层协议是互联网中的主流模型&#xff0c;为网络通信提供了一个稳固的框架。 主要包含了应用层&#xff0c;传输层&#xff0c;网络层&#xff0c;数据链路层&#xff0c;物理层。 本篇主要介绍传输层的TCP协议的核心机制 一. 确认应答&#xff08;ack&#xf…

线程本地变量-ThreadLocal

一、ThreadLocal简介 ThreadLocal叫做线程变量&#xff0c;意思是ThreadLocal中填充的变量属于当前线程&#xff0c;该变量对其他线程而言是隔离的&#xff0c;也就是说该变量是当前线程独有的变量。ThreadLocal为变量在每个线程中都创建了一个副本&#xff0c;那么每个线程可…

量子纠错--shor‘s 码

定理1 (量子纠错的条件) C是一组量子编码&#xff0c;P是映射到C上的投影算子。假设是一个算子元素描述的量子操作&#xff0c;那么基于量子编码C&#xff0c;存在一个能对抗描述的噪声的纠错操作R的充要条件是 对某个复元素厄米矩阵成立。 将算子元素称为导致的错误。如果这样…

[C++进阶数据结构]红黑树(半成品)

我们讲完了AVL树,它追求绝对平衡&#xff0c;从而导致插入和删除性能较差。今天我们来讲讲&#xff0c;红黑树&#xff0c;它是另一种平衡二叉搜索树&#xff0c;它追求相对平衡&#xff0c;使得增删查改的性能都极佳&#xff0c;时间复杂度皆为O(log2N)。 一、红黑树的概念 …

CSS3 动画相关属性实例大全(三)(columns、filter、flex、flex-basis 、flex-grow、flex-shrink属性)

CSS3 动画相关属性实例大全&#xff08;三) &#xff08;columns、filter、flex、flex-basis 、flex-grow、flex-shrink属性&#xff09; 本文目录&#xff1a; 一、columns属性&#xff08;设置元素的列宽和列数&#xff09; 二、filter属性&#xff08;调整图像、背景和边…

Ribbon客户端负载均衡策略测试及其改进

文章目录 一、目的概述二、验证步骤1、源码下载2、导入IDE3、运行前修改配置4、策略说明5、修改策略 三、最终结论四、改进措施1. 思路分析2. 核心代码3. 测试页面 一、目的概述 为了验证Ribbon客户端负载均衡策略在负载节点失效的情况下&#xff0c;是否具有故障转移的功能&a…

【逆向基础】十七、PE文件格式(二)

一、简介 本篇章主要PE文件组成部分中使用的结构体&#xff1b;根据结构体的成员变量去了解各个字节的含义。&#xff08;ps:我们依旧以”cmd.exe“为例展开解析&#xff1b;) 二、DOS Header 1、结构体&#xff1a;IMAGE_DOS_HEADER IMAGE_DOS_HEADER结构体的背景是为了兼…

忘记7-zip文件7-zip文件,还可以解压zip文件吗?

文件压缩与解压已成为我们日常处理数据和存储信息的常规操作。7-Zip&#xff0c;作为一款开源且功能强大的文件压缩工具&#xff0c;凭借其高压缩率、支持多种格式以及免费使用的特点&#xff0c;赢得了广大用户的青睐。然而&#xff0c;出于保护文件内容安全的考虑&#xff0c…