Vue3中如何用渲染函数实现带v-model的插槽功能?
解决方案
一、用渲染函数实现原声明式模板的插槽逻辑
原声明式模板的核心是给ChildComponent传递默认插槽,插槽内包含绑定myValue的输入框。用Vue3的h渲染函数实现如下:
import { h } from 'vue' import ChildComponent from './ChildComponent.vue' export default { components: { ChildComponent }, data() { return { myValue: '' } }, render() { // 渲染ChildComponent并传入默认插槽 return h(ChildComponent, {}, { default: () => // 插槽内容:div包裹input,手动实现v-model双向绑定逻辑 h('div', {}, [ h('input', { type: 'text', value: this.myValue, onInput: (e) => { this.myValue = e.target.value } }) ]) }) } }
注意:渲染函数没有v-model语法糖,需要手动拆解为value绑定和onInput事件监听,实现双向绑定。
二、解决API返回HTML插入插槽不生效的问题
v-html只能渲染静态DOM,无法解析Vue指令(如v-model)或绑定响应式数据,因此需要动态编译API返回的HTML为可执行的渲染函数,步骤如下:
1. 确保项目支持运行时编译
- Vue CLI项目:在
vue.config.js中设置runtimeCompiler: true - Vite项目:安装
@vue/runtime-dom,并确保配置允许运行时编译
2. 动态编译API HTML并渲染到插槽
假设API返回的HTML字符串为:<div><input type="text" v-model="myValue"/></div>,修改渲染函数如下:
import { h, compile } from 'vue' import ChildComponent from './ChildComponent.vue' export default { components: { ChildComponent }, data() { return { myValue: '', apiHtml: '' // 存储API返回的HTML内容 } }, async mounted() { // 模拟从API获取HTML this.apiHtml = await fetch('/api/get-slot-content').then(res => res.text()) }, render() { let slotContent = h('div', '加载中...') if (this.apiHtml) { // 编译HTML字符串为渲染函数 const renderFn = compile(this.apiHtml) // 传入组件上下文,让编译后的渲染函数能访问myValue等响应式数据 slotContent = renderFn(this.$.setupState, this.$.ctx) } return h(ChildComponent, {}, { default: () => slotContent }) } }
关键注意事项
- 必须使用可信的API数据源,避免XSS攻击;若HTML来自不可信源,需先做转义处理
- 运行时编译会有一定性能损耗,生产环境建议后端预编译模板或提前处理HTML内容
内容的提问来源于stack exchange,提问作者pilifi
相关产品推荐
相关产品推荐

