Vue中v-for循环时如何为每个项绑定不同的onClick点击事件
问题原因
你遇到的报错和this指向问题本质是两个原因导致的:
- 包含函数的
list被Vue做了响应式代理:Vue2默认不会对函数做响应式处理,代理后直接从item上取onClick会取不到;Vue3同理,响应式代理对象上的函数属性会丢失原始引用,所以报not a function的错误。而你用list[i].onClick能运行,是因为直接取到了原始数组的属性,绕过了代理层。 onClick用箭头函数定义:箭头函数的this会绑定定义时的上下文,在data里定义的箭头函数this不会指向Vue实例,自然无法访问实例上的属性和方法。
最优解决方案
核心思路是不要让操作列表被响应式代理,这类静态操作列表本身不需要响应式更新,避免代理即可解决所有问题。
选项式API实现
不要把list放在data中,直接在created钩子中挂载为实例的普通属性,onClick用普通函数定义即可正常访问this:
export default { data() { return { // 不要把带函数的list放这里,避免被代理 } }, created() { this.operationList = [ { text: 'a', icon: 'a-icon', onClick() { // 这里this直接指向Vue实例,可以正常访问this.xxx console.log(this.formData) } }, { text: 'b', icon: 'b-icon', onClick() { // 处理b的逻辑 } } ] }, methods: { handleItemClick(item) { item.onClick() } } }
模板写法非常简洁:
<div v-for="(item, i) in operationList" :key="i" @click="handleItemClick(item)" ></div>
组合式API实现
用markRaw标记函数为非响应式即可,不需要处理this指向,直接访问作用域内的响应式变量:
import { ref, markRaw } from 'vue' const formData = ref({}) const operationList = [ { text: 'a', icon: 'a-icon', onClick: markRaw(() => { // 直接访问作用域内的响应式变量 console.log(formData.value) }) }, { text: 'b', icon: 'b-icon', onClick: markRaw(() => { // 处理b的逻辑 }) } ] const handleItemClick = (item) => { item.onClick() }
模板写法和选项式完全一致。
其他优化点
如果你的列表确实需要动态更新,可以保留在响应式数据中,只给每个对象的onClick属性包裹markRaw标记为非响应式,同样可以正常取到函数。
内容的提问来源于stack exchange,提问作者Zaya
相关产品推荐
相关产品推荐

