Vue通用表格组件动态渲染三类单元格时事件监听器绑定问题
解决方案
核心问题说明
v-html只会将字符串解析为普通DOM节点,不会编译Vue指令、也不会处理绑定事件,你当前给<span>加的click.native写法错误:native修饰符仅用于给自定义组件绑定原生事件,<span>是原生DOM元素,加native修饰符会导致事件无法触发。- JSON格式无法直接序列化函数,直接在配置中传递方法实例的写法不通用,也不符合组件传值规范。
通用改造方案
第一步:调整表格配置结构
统一用「事件名+触发参数」的方式配置,不要直接传递方法实例:
// 父组件传入的表格单元格配置 const cellConfig = { "cell-1": { "type": "html", "data": "<h4>text-1</h4>", "events": { "click": { emitName: "cell-click", params: { cellId: "cell-1", value: "text-1" } } } } } // 父组件引用表格组件时监听对应事件 <TableComponent :cellConfig="cellConfig" @cell-click="someMethod" />
第二步:改造表格组件的动态事件绑定逻辑
利用Vue的v-on支持传入对象的特性,动态生成事件绑定对象:
<template> <tbody> <tr v-for="row in tableRows" :key="row.id"> <td v-for="cell in row.cells" :key="cell.key"> <!-- HTML类型单元格 --> <span v-if="cell.type === 'html'" v-html="cell.data" v-on="getCellEventHandlers(cell.events)" ></span> <!-- 文本类型单元格 --> <span v-else-if="cell.type === 'text'" v-on="getCellEventHandlers(cell.events)" > {{ cell.data }} </span> <!-- 组件类型单元格 --> <component v-else-if="cell.type === 'component'" :is="cell.data.compName" v-bind="cell.data.props" v-on="getCellEventHandlers(cell.events)" /> </td> </tr> </tbody> </template> <script> export default { props: { cellConfig: { type: Object, required: true } }, methods: { getCellEventHandlers(events = {}) { const handlers = {} Object.keys(events).forEach(eventType => { const { emitName, params } = events[eventType] handlers[eventType] = () => this.$emit(emitName, params) }) return handlers } } } </script>
特殊场景:给v-html内部元素绑定事件
如果需要把事件绑定到v-html渲染出来的内部DOM节点上,需要手动监听并销毁:
export default { updated() { // 找到v-html渲染出的目标节点,手动绑定事件 this.$el.querySelectorAll('td span h4').forEach(el => { el.addEventListener('click', this.someMethod) }) }, beforeUnmount() { // 组件销毁前移除事件监听,避免内存泄漏 this.$el.querySelectorAll('td span h4').forEach(el => { el.removeEventListener('click', this.someMethod) }) } }
内容的提问来源于stack exchange,提问作者Bhavik Patel
相关产品推荐
相关产品推荐

