Vue.js 中动态渲染带交互逻辑的自定义 HTML 元素的正确方式

在 vue 模板中直接拼接 html 字符串并用 `v-html` 渲染,无法绑定响应式事件;真正可靠的方式是使用 render functions(或 jsx),通过 `h()` 函数创建可交互的虚拟节点。

在 Vue 开发中,常有需求根据参数动态生成具有特定行为(如点击事件)的 HTML 元素。初学者容易尝试在模板中调用方法返回 HTML 字符串,例如:



⚠️ 这种写法不会生效

  • {{ }} 插值仅作纯文本渲染,返回的字符串会被原样显示为 HTML 源码;
  • 即使改用 v-html(如 ),Vue 不会编译其中的指令(如 @click),事件绑定完全失效,handleClick 也无法被识别——因为 v-html 仅插入静态 DOM,不经过 Vue 的模板编译器。

✅ 正确解法:使用 Render Functions(组合式 API 中的 setup() 返回函数 + h())

Render Functions 是 Vue 的底层渲染机制,允许你以编程方式创建响应式、可交互的 VNode。它绕过模板编译限制,直接控制虚拟 DOM 结构与行为:

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

import { h } from 'vue'

export default {
  props: ['param1', 'param2', 'param3'],
  setup(props) {
    const handleClick = () => {
      alert(`Clicked with: ${props.param1}, ${props.param2}, ${props.param3}`)
    }

    return () => h('button', {
      class: 'custom-btn',
      onClick: handleClick,
      type: 'button'
    }, 'Click Me!')
  }
}

该写法优势显著:

  • ✅ 事件处理器(onClick)是真实函数引用,具备完整响应式上下文;
  • ✅ 支持传入 props、slots、attrs 等所有组件能力;
  • ✅ 可复用、可测试、类型安全(配合 TypeScript 更佳);
  • ✅ 兼容 Vue 3 的 Composition API 与响应式系统。

? 补充说明:

  • 若需更接近模板语法的体验,可选用 JSX / TSX(需配置 Babel 或 Vite 插件);
  • 避免滥用 v-html 处理用户输入内容,存在 XSS 风险;仅用于可信的静态 HTML 片段;
  • 对简单条件渲染(如不同标签、类名),优先使用 v-if/v-for/:class 等声明式指令,保持可维护性。

总之,当 HTML 结构与交互逻辑需动态组合时,Render Functions 不是“高级技巧”,而是 Vue 官方推荐的标准解决方案——它让动态性与响应式完美共存。