Vue.js DataTables:渲染方法中的点击函数无法生效
问题:DataTables渲染的按钮点击事件无响应
在Vue3项目中使用datatables.net-vue3展示数据,Action列通过render方法生成带删除按钮的HTML,但点击删除按钮时handleDeleteClick函数完全没反应。
用户代码片段:
<script setup> import DataTable from 'datatables.net-vue3'; import DataTablesCore from 'datatables.net'; DataTable.use(DataTablesCore); const options = ref({ columns: [ { data: 'id', title: 'Action', render: (data) => { return ` <div class="flex items-center px-6 py-4 gap-3"> <div class="cursor-pointer bg-green-600 p-1 rounded-md"> <svg class="w-[20px] h-[20px] fill-[#d1e5d4] " viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg"> <path d="M410.3 231l11.3-11.3-33.9-33.9-62.1-62.1L291.7 89.8l-11.3 11.3-22.6 22.6L58.6 322.9c-10.4 10.4-18 23.3-22.2 37.4L1 480.7c-2.5 8.4-.2 17.5 6.1 23.7s15.3 8.5 23.7 6.1l120.3-35.4c14.1-4.2 27-11.8 37.4-22.2L387.7 253.7 410.3 231zM160 399.4l-9.1 22.7c-4 3.1-8.5 5.4-13.3 6.9L59.4 452l23-78.1c1.4-4.9 3.8-9.4 6.9-13.3l22.7-9.1v32c0 8.8 7.2 16 16 16h32zM362.7 18.7L348.3 33.2 325.7 55.8 314.3 67.1l33.9 33.9 62.1 62.1 33.9 33.9 11.3-11.3 22.6-22.6 14.5-14.5c25-25 25-65.5 0-90.5L453.3 18.7c-25-25-65.5-25-90.5 0zm-47.4 168l-144 144c-6.2 6.2-16.4 6.2-22.6 0s-6.2-16.4 0-22.6l144-144c6.2-6.2 16.4-6.2 22.6 0s6.2 16.4 0 22.6z"></path> </svg> </div> <div class="cursor-pointer bg-red-600 p-1 rounded-md" @click="handleDeleteClick(${data})"> <svg class="w-[20px] h-[20px] fill-[#d1e5d4]" viewBox="0 0 448 512" xmlns="http://www.w3.org/2000/svg"> <path d="M135.2 17.7C140.6 6.8 151.7 0 163.8 0H284.2c12.1 0 23.2 6.8 28.6 17.7L320 32h96c17.7 0 32 14.3 32 32s-14.3 32-32 32H32C14.3 96 0 81.7 0 64S14.3 32 32 32h96l7.2-14.3zM32 128H416V448c0 35.3-28.7 64-64 64H96c-35.3 0-64-28.7-64-64V128zm96 64c-8.8 0-16 7.2-16 16V432c0 8.8 7.2 16 16 16s16-7.2 16-16V208c0-8.8-7.2-16-16-16zm96 0c-8.8 0-16 7.2-16 16V432c0 8.8 7.2 16 16 16s16-7.2 16-16V208c0-8.8-7.2-16-16-16zm96 0c-8.8 0-16 7.2-16 16V432c0 8.8 7.2 16 16 16s16-7.2 16-16V208c0-8.8-7.2-16-16-16z"></path> </svg> </div> </div> ` } } // ...其他列 ], data: [], searching: false, lengthMenu: [10, 15, 25], pageLength: 10, }); const handleDeleteClick = (id) => { console.log('Delete button clicked for ID:', id); }; </script>
原因分析
DataTables的render方法返回的是纯HTML字符串,这部分内容会直接被插入到DOM中,不会经过Vue的模板编译流程。所以你写的@click指令对Vue来说完全不识别,自然不会绑定事件。
解决方案
方法1:使用DataTables的事件委托(推荐)
利用DataTables提供的API结合事件委托来绑定点击事件:
- 修改
render函数,给删除按钮添加唯一类名和存储ID的自定义属性:
render: (data) => { return ` <div class="flex items-center px-6 py-4 gap-3"> <!-- 编辑按钮部分不变 --> <div class="cursor-pointer bg-red-600 p-1 rounded-md delete-btn" data-id="${data}"> <!-- SVG内容不变 --> </div> </div> ` }
- 给DataTable组件绑定
@init事件,在表格初始化完成后添加事件监听:
<template> <DataTable :options="options" @init="onTableInit" /> </template> <script setup> // ...其他导入和定义 const onTableInit = (table) => { // 给删除按钮绑定点击事件 table.on('click', '.delete-btn', function() { const id = this.getAttribute('data-id'); handleDeleteClick(id); }); }; </script>
方法2:使用Vue的虚拟节点渲染(适合复杂场景)
如果需要在渲染内容中使用Vue响应式特性或组件,可以用Vue的h函数创建虚拟节点,再转换成HTML字符串:
- 安装依赖:
npm install @vue/server-renderer
- 修改
render函数为异步函数,用虚拟节点生成HTML:
import { h, renderToString } from 'vue'; // ...其他代码 const options = ref({ columns: [ { data: 'id', title: 'Action', render: async (data) => { // 创建Vue虚拟节点 const vnode = h('div', { class: 'flex items-center px-6 py-4 gap-3' }, [ // 编辑按钮的虚拟节点 h('div', { class: 'cursor-pointer bg-green-600 p-1 rounded-md' }, [ h('svg', { class: 'w-[20px] h-[20px] fill-[#d1e5d4]', viewBox: '0 0 512 512', xmlns: 'http://www.w3.org/2000/svg' }, [ h('path', { d: 'M410.3 231l11.3-11.3-33.9-33.9-62.1-62.1L291.7 89.8l-11.3 11.3-22.6 22.6L58.6 322.9c-10.4 10.4-18 23.3-22.2 37.4L1 480.7c-2.5 8.4-.2 17.5 6.1 23.7s15.3 8.5 23.7 6.1l120.3-35.4c14.1-4.2 27-11.8 37.4-22.2L387.7 253.7 410.3 231zM160 399.4l-9.1 22.7c-4 3.1-8.5 5.4-13.3 6.9L59.4 452l23-78.1c1.4-4.9 3.8-9.4 6.9-13.3l22.7-9.1v32c0 8.8 7.2 16 16 16h32zM362.7 18.7L348.3 33.2 325.7 55.8 314.3 67.1l33.9 33.9 62.1 62.1 33.9 33.9 11.3-11.3 22.6-22.6 14.5-14.5c25-25 25-65.5 0-90.5L453.3 18.7c-25-25-65.5-25-90.5 0zm-47.4 168l-144 144c-6.2 6.2-16.4 6.2-22.6 0s-6.2-16.4 0-22.6l144-144c6.2-6.2 16.4-6.2 22.6 0s6.2 16.4 0 22.6z' }) ]) ]), // 删除按钮的虚拟节点,直接绑定点击事件 h('div', { class: 'cursor-pointer bg-red-600 p-1 rounded-md', onClick: () => handleDeleteClick(data) }, [ h('svg', { class: 'w-[20px] h-[20px] fill-[#d1e5d4]', viewBox: '0 0 448 512', xmlns: 'http://www.w3.org/2000/svg' }, [ h('path', { d: 'M135.2 17.7C140.6 6.8 151.7 0 163.8 0H284.2c12.1 0 23.2 6.8 28.6 17.7L320 32h96c17.7 0 32 14.3 32 32s-14.3 32-32 32H32C14.3 96 0 81.7 0 64S14.3 32 32 32h96l7.2-14.3zM32 128H416V448c0 35.3-28.7 64-64 64H96c-35.3 0-64-28.7-64-64V128zm96 64c-8.8 0-16 7.2-16 16V432c0 8.8 7.2 16 16 16s16-7.2 16-16V208c0-8.8-7.2-16-16-16zm96 0c-8.8 0-16 7.2-16 16V432c0 8.8 7.2 16 16 16s16-7.2 16-16V208c0-8.8-7.2-16-16-16zm96 0c-8.8 0-16 7.2-16 16V432c0 8.8 7.2 16 16 16s16-7.2 16-16V208c0-8.8-7.2-16-16-16z' }) ]) ]) ]); // 将虚拟节点转换为HTML字符串返回 return await renderToString(vnode); } } ] });
注意:方法2需要render函数为异步,因为renderToString是异步方法,需确保表格数据加载和渲染顺序正常。
内容的提问来源于stack exchange,提问作者Newbi
相关产品推荐
相关产品推荐

