查看: 2844|回复: 3

Vue2事件绑定参数传递与this指向、methods原理

[复制链接]
发表于 3 天前 | 显示全部楼层 |阅读模式
Vue2 的事件绑定主要围绕 v-on 指令展开,简写为 @,回调函数需要定义在 Vue 实例的 methods 中,模板负责把事件名和回调关联起来。原文特别强调一个常见错误:methods 中的回调不要写成箭头函数,否则 this 不能按预期拿到 Vue 实例。下面按语法对比、参数传递、this 指向和 methods 挂载实现四个部分整理可落地的写法。

一、从原生事件绑定看 v-on
原生 JavaScript 常见的三种绑定方式如下:
  1. let btn1 = document.getElementById('btn1');
  2. btn1.addEventListener('click', () => {
  3.   console.log('hello1');
  4. });
  5. btn1.onclick = function() {
  6.   console.log('hello2');
  7. };
  8. function demo1() {
  9.   console.log('hello3');
  10. }
复制代码
Vue2 把事件绑定写成 v-on:事件名 或 @事件名。基本语法和简写形式可以这样写:
  1. <button v-on:click='demo()'>按钮</button>
  2. <button @click='demo()'>按钮</button>
复制代码
这里的 demo 需要是 Vue 实例 methods 中定义的方法。原文给出的错误示例中,v-on:click=“alert('hello')”使用了 alert,v-on:click=“demo1()”使用了全局函数,这两者都不是 Vue 实例管理的方法,所以不能按 methods 回调的方式工作。正确方式是在 methods 配置项中定义回调,再在模板中调用。

二、事件参数传递规则
当既需要自定义参数又需要事件对象时,可以用 $event 占位符显式传入当前事件对象:
  1. <input type='text' @input='fun(1, 2, 3, $event)' />
复制代码
如果只需要事件对象,可以省略小括号,直接写方法名:
  1. <input type='text' @input='fun' />
复制代码
对应的 methods 可以这样写:
  1. methods: {
  2.   fun(a, b, c, e) {
  3.     console.log(e.target.value);
  4.     console.log(a, b, c);
  5.   }
  6. }
复制代码
从原文示例可归纳:Vue 在调用回调时会自动传入当前事件对象;需要额外参数时用 $event 占位;不需要额外参数时省略小括号即可。输入框事件中可通过 e.target.value 读取当前输入值。

三、this 指向:普通函数与箭头函数的差异
普通函数写法下,methods 回调中的 this 指向 Vue 实例 vm,因此可以访问 data,也可以调用其他 methods:
  1. methods: {
  2.   add() {
  3.     this.num++;
  4.     console.log(this);
  5.     this.fun();
  6.   }
  7. }
复制代码
箭头函数写法不推荐:
  1. methods: {
  2.   add2: () => {
  3.     console.log(this);
  4.   }
  5. }
复制代码
原文说明,箭头函数没有自己的 this,它的 this 来自定义时的上下文;由于对象不能构成单独作用域,父级作用域是全局作用域,所以这里通常指向 window,无法正确访问 data 中的数据。这个因果链是 Vue2 methods 中不宜使用箭头函数定义事件回调的关键原因。

异步操作中的写法需要区分场景。如果异步回调内部要修改 Vue 实例状态,原文推荐使用箭头函数继承外层 this:
  1. methods: {
  2.   add3() {
  3.     setTimeout(() => {
  4.       this.num++;
  5.     }, 2000);
  6.   }
  7. }
复制代码
这里的 setTimeout 回调写成箭头函数,this 继承 add3 的 this,仍然指向 Vue 实例。可推导出的实践是:methods 入口函数用普通函数保证 this 指向 vm;定时器、请求等异步回调内部用箭头函数保持外层 this。

四、methods 的挂载原理与简易实现
原文给出一个简易 MyVue,用 for...in 遍历 options.methods,把每个方法挂到实例上:
  1. class MyVue {
  2.   constructor(options) {
  3.     for (const key in options.methods) {
  4.       this[key] = options.methods[key];
  5.     }
  6.   }
  7. }
  8. const vm = new MyVue({
  9.   data() {
  10.     return {
  11.       msg: 'hello vue!'
  12.     };
  13.   },
  14.   methods: {
  15.     fun1() { console.log('fun1'); },
  16.     fun2() { console.log('fun2'); },
  17.     fun3() { console.log('fun3'); }
  18.   }
  19. });
  20. vm.fun1();
复制代码
这个简易实现说明了 methods 方法能被实例直接调用的基本思路。原文还总结 Vue 实际实现特点:methods 中的方法通过数据代理挂载到 Vue 实例;方法中的 this 被自动绑定到 Vue 实例;可以通过 vm 直接访问 methods 中的方法。理解这一点后,排查事件回调不生效时,可以先检查方法是否在 methods 中、模板调用名是否匹配、是否误用了箭头函数导致 this 异常。

五、落地实践清单
1. 事件处理方法统一放在 methods 中定义,模板使用 @click、@input、@keydown 等绑定。
2. 需要在回调中访问 data 或调用其他方法时,methods 入口使用普通函数。
3. 需要自定义参数时写成 @click='fun(param1, param2, $event)',用 $event 占位事件对象。
4. 只需要事件对象时写成 @click='fun',省略小括号,让 Vue 自动传入事件对象。
5. 异步回调中推荐箭头函数,以继承外层指向 Vue 实例的 this。
6. 不要把 alert 或全局函数直接当作 Vue 实例方法使用,模板中的回调应由 methods 管理。

以上写法覆盖了 Vue2 事件绑定的主要代码实践。原文的重点可以归纳为:v-on 负责事件关联,methods 负责回调管理,$event 负责参数传递,普通函数与箭头函数的选择决定 this 是否符合预期。
回复

使用道具 举报

发表于 3 天前 | 显示全部楼层

Re: Vue2事件绑定参数传递与this指向、methods原理

楼主这篇整理得很细,Vue2 事件绑定里几个容易踩的点基本都覆盖到了。我自己看下来感触比较深的是 this 指向那一块,尤其是异步回调的分场景写法:methods 入口用普通函数、setTimeout 里用箭头函数继承外层 this,这条经验很实用,比单纯背结论好记很多。 另外想补充一点理解,$event 这个占位符本质上是让模板在传参时显式把事件对象带进去;不需要自定义参数时直接写方法名,Vue 就会自动把事件对象作为第一个参数传进来,这个规则和楼主的示例是对得上的。 还有 methods 挂载那段的简易实现,虽然代码很精简,但把“方法挂到实例上、this 指向实例、可以直接用 vm 调方法”这条链路讲清楚了。排查问题时顺着“是否在 methods 里、模板名是否匹配、是否误用箭头函数”这三步走,确实能省不少时间。感谢整理。
回复 支持 反对

使用道具 举报

发表于 3 天前 | 显示全部楼层

Re: Vue2事件绑定参数传递与this指向、methods原理

这篇整理得很实用,语法对比、参数传递、this 指向和 methods 挂载几个部分串得比较顺。我最有共鸣的是 methods 入口用普通函数、定时器或请求等异步回调里用箭头函数这个区分,实际写 Vue2 时确实容易在箭头函数上踩 this 的坑。$event 显式占位和只传事件对象时省略小括号这两条也很适合当作排查清单。另外第四部分简易 MyVue 里 `this = options.methods;` 看着像笔误,按上下文意图应该是把 methods 的每个 key 挂到实例上,比如 `this = options.methods`,这样后面的 vm.fun1() 才说得通。整体清单可以直接拿来对照检查事件回调不生效的问题。
回复 支持 反对

使用道具 举报

发表于 3 天前 | 显示全部楼层

Re: Vue2事件绑定参数传递与this指向、methods原理

写得很系统,尤其把 this 指向这条因果关系讲清楚了,很多人踩坑就是没想明白箭头函数没有自己的 this 这一点。 不过第四部分那段 MyVue 的代码贴出来时似乎有一处笔误,`for (const key in options.methods)` 循环里写成了 `this = options.methods;`,这样既赋不了值也会直接报错,本意应该是 `this = options.methods;`。这种简易实现拿来讲解原理挺好的,但示例代码最好能跑通,不然新手照着抄会卡住。 另外补充一点使用上的细节:模板里 `@click='demo()'` 和 `@click='demo'` 在大多数场景效果一样,但前者是在表达式里主动调用,后者是把函数引用交给 Vue 去调。正因为后者是 Vue 内部调用,所以事件对象能作为第一个参数自动传进来;如果加了小括号又不写 `$event`,事件对象就丢了。这一点和帖子里讲的 `$event` 占位规则正好能对上,配合理解会更顺。 整体清单部分可以直接当速查表用,收藏了。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-10-27 18:10 , Processed in 0.023957 second(s), 29 queries , Gzip On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部