VueJS中如何让动态加载数据的@click/v-on事件生效?
动态渲染Vue元素的点击事件绑定问题
最初通过innerHTML拼接包含@click事件的DOM元素,点击事件完全无法触发。改用Vue的v-for指令渲染axios动态获取的数据后,控制台已显示成功拿到Proxy格式的数组,但需修正实现方式以解决点击事件绑定及响应式渲染问题。
旧代码问题分析
旧代码直接通过原生DOM操作拼接HTML字符串,Vue无法识别这种方式添加的@click指令——Vue的指令需要经过框架编译才能生效,原生innerHTML插入的内容不会被Vue编译处理,因此点击事件完全无效。
旧代码片段:
if (msg == 'mailings'){ document.getElementById("listofmailings").style.display = 'block'; document.getElementById("mainquote").style.display = 'none'; document.getElementById("displaymailing").style.display = 'block'; document.getElementById("signup").style.display = 'none'; axios.get('http://localhost:8081/getcampaigns') .then(response => { document.getElementById("holdmailings").innerHTML= ''; for (let i = 0; i < response.data.length; i++) { document.getElementById("holdmailings").innerHTML += '<div class="row"><div class="col-10" @click="setPermalink(\''+response.data[i].permalink+'\')">' +response.data[i].title + '</div><div class="col-2">'+response.data[i].createdate+'</div></div>'; } })
新代码核心问题
新代码改用v-for的思路正确,但存在3个关键错误:
- 组件外部定义的
mailings未注入Vue响应式系统,组件无法追踪其变化 - 缺少
openLink方法的具体实现,点击事件无实际处理逻辑 - 用原生DOM操作控制显示隐藏,不符合Vue数据驱动视图的开发规范
修正后的完整代码
Template部分
<template> <div class="container"> <div id="holdif"><Menus></Menus></div> <div class="row mb-2"> <div class="col-lg-6"> <!-- 用v-show替代原生DOM操作,实现数据驱动视图显示 --> <div id="listofmailings" class="col-lg-12 bg-white mt-1" v-show="currentView === 'mailings'"> <div class="row"> <div class="col-10">EMAIL SUBJECT</div> <div class="col-2" style="text-align: center">DATE</div> </div> <!-- v-for绑定响应式数据,key使用唯一id保证渲染性能 --> <div class="row" v-for="item in mailings" :key="item.id"> <div class="col-10" @click="openLink(item.permalink)">{{ item.title }}</div> <div class="col-2">{{ item.createdate }}</div> </div> </div> <div id="mainquote" class="col-lg-12 bg-white mt-1" v-show="currentView === 'home'"> Know your Town... Really know your town </div> </div> <div class="col-lg-6 "> <div class="col-lg-12 bg-white mt-1"> <div id="displaymailing" v-show="currentView === 'mailings'">{{ currentPermalink }}</div> </div> <!-- Begin Constant Contact Inline Form Code --> <div id="signup" class="ctct-inline-form" data-form-id="81c108fd-ee02-47f6-aaf3-bbe3643e328b" v-show="currentView === 'home'"></div> <!-- End Constant Contact Inline Form Code --> </div> </div> </div> </template>
Script部分
<script> import Menus from '../components/Menus' import axios from 'axios'; import { ref } from 'vue'; export default { name: 'Home', components: { Menus }, setup() { // 将响应式变量放在setup中,注入组件的响应式系统 const mailings = ref([]); const currentView = ref('home'); // 用数据控制视图切换 const currentPermalink = ref(''); // 实现点击事件处理逻辑 const openLink = (permalink) => { currentPermalink.value = permalink; // 可在此添加跳转、弹窗等额外逻辑 console.log('选中的链接:', permalink); }; const doaction = (view) => { currentView.value = view; if (view === 'mailings') { axios.get('http://localhost:8081/getcampaigns') .then(response => { mailings.value = response.data; }) .catch(e => { alert('请求失败: ' + e) console.log(e) }) } }; // 暴露变量和方法给模板使用 return { mailings, currentView, currentPermalink, openLink, doaction } } } </script>
关键修正说明
- 将响应式变量放入
setup函数并返回,确保组件能追踪数据变化 - 用
v-show替代原生DOM操作,完全遵循Vue数据驱动视图的开发模式 - 补充
openLink方法的具体实现,处理点击事件逻辑并更新页面状态 - 保留
v-for的:key绑定,保证列表渲染的性能和正确性
内容的提问来源于stack exchange,提问作者MW_DEVEL
相关产品推荐
相关产品推荐

