如何让Vue指令在字符串渲染的HTML中生效?(Todo应用场景)
问题描述
开发Todo应用时,希望通过字符串拼接HTML的方式(不使用v-for或emit)渲染列表并删除选中项,但v-html中拼接的@click指令无法生效——原因是v-html仅渲染纯HTML内容,不会解析Vue的指令语法。
原始代码
脚本代码
<script> import { ref, reactive } from 'vue'; export default { data() { const todo = ref(''); const list = reactive([]); return { todo, list }; }, components: { navbar, }, methods: { render() { console.log(this.list.length); return this.list .map((item, index) => { return `<div class="task"><p>${item.todo}</p><button @click="list.splice(index, 1)">del</button></div>`; }) .join(''); }, }, }; </script>
HTML代码
<div class="list-container"> <div class="task-container" v-if="list.length" v-html="render()"></div> <div class="task-container" v-else>nothing in here</div> </div>
列表数据结构
{todo: 'text', checked: false}, ...
解决方案
修改后的脚本代码
<script> import { ref, reactive } from 'vue'; export default { data() { const todo = ref(''); const list = reactive([]); return { todo, list }; }, components: { navbar, }, created() { // 将Vue实例挂载到全局window对象,供原生事件调用 window.todoApp = this; }, methods: { render() { console.log(this.list.length); return this.list .map((item, index) => { // 替换Vue指令@click为原生onclick,调用全局挂载的实例删除方法 return `<div class="task"><p>${item.todo}</p><button onclick="todoApp.deleteItem(${index})">del</button></div>`; }) .join(''); }, deleteItem(index) { this.list.splice(index, 1); } }, }; </script>
核心逻辑说明
- 因为v-html不解析Vue指令,所以改用原生HTML的
onclick事件属性; - 通过
created钩子将Vue实例挂载到全局window,让原生事件能直接访问实例内的方法; - 单独抽离
deleteItem方法处理删除逻辑,避免拼接字符串时的代码冗余。
内容的提问来源于stack exchange,提问作者Estif
相关产品推荐
相关产品推荐

