查看: 77|回复: 0

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

[复制链接]
发表于 1 小时前 | 显示全部楼层 |阅读模式
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 是否符合预期。
回复

使用道具 举报

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

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

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

官方核心成员

关注微信公众号

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

GMT+8, 2026-10-24 16:28 , Processed in 0.026046 second(s), 29 queries , Gzip On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部