Vue中methods的this指向问题浅析

 更新时间:2022年10月27日 14:36:13   作者:天地会珠海分舵  
相信我们写Vue代码时肯定都会在methods中用过this这个关键字,甚至还打印过this查看其内容。最终发现该实例对象竟然是我们的Vue实例对象

如果是组件的话,将会是VueComponent实例对象,Vue和VueComponent两个类其实差不都,今后会另外开章节描述两者差别,这里先飘过。

比如下面的简单的一个demo代码,点击按钮打印出this。

<!DOCTYPE html>
<html lang="en">
  <head>
    <script src="../../dist/vue.js"></script>
  </head>
  <body>
    <div id="app">
      <button @click="printThis">What is this</button>
    </div>
    <script>
      const vm = new Vue({
        el: "#app",
        data: {
          counter: 0,
        },
        methods: {
          printThis() {
            console.log("this:", this);
          },
        },
      });
    </script>
  </body>
</html>

最终打印的结果将会如下:

很明显,vue框架通过某种方法自动帮我们将methods下面的this指向到vue的实例对象了。

下面跟踪下vue的源代码,看下是怎么实现的。

首先,我们看下new Vue的入口,也即是Vue类的构造函数

function Vue(options) {
  ...
  this._init(options);
}

构造函数的参数options就是我们前面new Vue时传入的带有methods和data这些配置项的对象。

构造函数里面会做很多初始化的动作,这些动作都被封装到_init这个方法中了。因为是通过this调用的,所以我们可以猜想到这个方法应该是写到了Vue的prototype上的。

Vue.prototype._init = function (options?: Object) {
    const vm: Component = this;
    ...
    // 将含有methods和data等配置项的对象合并并挂到Vue实例对象vm的$options属性上
    if (options && options._isComponent) {
      // optimize internal component instantiation
      // since dynamic options merging is pretty slow, and none of the
      // internal component options needs special treatment.
      initInternalComponent(vm, options);
    } else {
      vm.$options = mergeOptions(
        resolveConstructorOptions(vm.constructor),
        options || {},
        vm
      );
    ...
    initState(vm);
    ...
  };
}

该方法会将我们new Vue时提供的带有methods和data的配置项放入到Vue实例对象的$options属性中,然后调用initState方法。

export function initState(vm: Component) {
  ...
  if (vm.$options.methods) initMethods(vm, vm.$options.methods);
  ...
}

因为我们提供了methods选项,记得吧?我们上面methods写了printThis方法。所以这里会调用到initMethods方法,传入的参数是Vue实例对象vm和我们传进来的methods选项。

function initMethods(vm: Component, methods: Object) {
  ...
  for (const key in methods) {
    ...
    vm[key] =
      typeof methods[key] !== "function" ? noop : bind(methods[key], vm);
  }
}

上面的代码逻辑主要就是循环methods里面的每个方法,然后将这些方法以相同的名字在vue实例对象中也放一份,比如我们的printThis方法,在vue实例对象中也来一份。

但是放到vue实例对象中的这些方法和原来的有一些区别,什么区别呢?就是通过上面的bind方法做了些调整。

这个bind方法看上去是不是很眼熟,名字和我们javascript用来修改this指向的bind方法一样。

而事实上这个bind方法最终调用的是一个叫做nativeBind的方法

function nativeBind (fn: Function, ctx: Object): Function {
  return fn.bind(ctx)
}

该方法做的事情就是将我们传入来的method,即我们这里的printThis方法的this的指向,指向到了传进来的vm,即我们的vue实例对象。

而这,也即是为什么我们在methods里面的方法可以通过this直接访问到Vue实例对象的原因了。

到此这篇关于Vue中methods的this指向问题浅析的文章就介绍到这了,更多相关Vue methods内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Vue-cli3项目引入Typescript的实现方法

    Vue-cli3项目引入Typescript的实现方法

    这篇文章主要介绍了Vue-cli3项目引入Typescript的实现方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-10-10
  • vue2+elementui的el-table固定列会遮住横向滚动条及错位问题解决方案

    vue2+elementui的el-table固定列会遮住横向滚动条及错位问题解决方案

    这篇文章主要介绍了vue2+elementui的el-table固定列会遮住横向滚动条及错位问题解决方案,主要解决固定列错位后, 接下来就是把固定列往上提滚动条的高度就不会影响了,需要的朋友可以参考下
    2024-01-01
  • Vue2+SpringBoot实现数据导出到csv文件并下载的使用示例

    Vue2+SpringBoot实现数据导出到csv文件并下载的使用示例

    本文主要介绍了Vue2+SpringBoot实现数据导出到csv文件并下载,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-10-10
  • vue之“} expected“和“at-rule or selector expected“报错的解决

    vue之“} expected“和“at-rule or selector ex

    这篇文章主要介绍了vue之“} expected“和“at-rule or selector expected“报错的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-03-03
  • vue3  mixin 混入使用方法

    vue3  mixin 混入使用方法

    这篇文章主要介绍了 vue3  mixin 混入使用方法,mixin 混入,提供了一种非常灵活的方式,来分发 vue 组件中的可复用功能,一个mixin 对象可以包含任意组件选项,当组件使用 mixin 对象时,所有的 mixin 对象的选项将被混入组件本身的选项。,需要的朋友可以参考一下
    2021-11-11
  • vue3+element Plus实现表格前端分页完整示例

    vue3+element Plus实现表格前端分页完整示例

    这篇文章主要给大家介绍了关于vue3+element Plus实现表格前端分页的相关资料,虽然很多时候后端会把分页,搜索,排序都做好,但是有些返回数据并不多的页面,或者其他原因不能后端分页的通常会前端处理,需要的朋友可以参考下
    2023-08-08
  • vue自定义实例化modal弹窗功能的实现

    vue自定义实例化modal弹窗功能的实现

    这篇文章主要介绍了vue自定义实例化modal弹窗,Vue.extend 属于Vue的全局 api,在实际业务开发中我们很少使用,因为相比常用的 Vue.component写法使用 extend 步骤要更加繁琐一些,本文结合实例代码给大家介绍的非常详细,需要的朋友参考下
    2022-09-09
  • vue3 中v-model语法糖示例详解

    vue3 中v-model语法糖示例详解

    vue3中的v-model相当于vue2中的v-model和v-bind.sync 修饰符组合在一起的产物(择优整合)v-bind.sync 在 vue3 中被移除了可以在组件标签上使用多个 v-model 绑定属性,使用参数区分,这篇文章主要介绍了vue3 中v-model语法糖,需要的朋友可以参考下
    2024-06-06
  • VUE Elemen-ui之穿梭框使用方法详解

    VUE Elemen-ui之穿梭框使用方法详解

    这篇文章主要为大家详细介绍了VUE Elemen-ui之穿梭框使用方法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-09-09
  • vue3动态路由+菜单栏的实现示例

    vue3动态路由+菜单栏的实现示例

    在后台管理系统,可以根据登录用户的不同返回不同路由,页面也会根据这些路由生成对应的菜单,本文主要介绍了vue3动态路由+菜单栏的实现示例,感兴趣的可以了解一下
    2024-04-04

最新评论