【Vue.js】方法声明 methods

269 阅读2分钟

概述

methods 是 Vue options API 中声明组件方法的选项

基本使用

export default {
  methods: {
    doSomething() {
      // ...
    },

    // ...
  },
};

具体步骤

  1. methods中声明需要使用到的方法
  2. 在实例中使用 this.方法名(args)调用方法;在模板中直接挂载使用即可

注意

声明的方法可以直接通过组件实例访问,或者在模板语法表达式中使用。所有的方法都会将它们的 this 上下文自动绑定为组件实例,即使在传递时也如此。

在声明方法时避免使用箭头函数,因为它们不能通过 this 访问组件实例。

代码示例

import { defineComponent } from 'vue';

const Comp = defineComponent({
  name: 'Comp',
  
  // ...
  
  methods: {
    handleClick() {
      console.log('click');
    }
  },
  
  template: `
    <div>
      <h1>Comp</h1>
      <button @click="handleClick">Click</button>
    </div>
  `
});

export default Comp;

methods 向组件实例添加方法时的特点

  1. 组件实例创建时, 会自动为 methods 绑定当前的实例 this - 确保在方法调用时, 注册的方法始终指向当前的组件实例 vm (所以,组件的 methods 要避免使用箭头函数, 箭头函数会阻止当前 method 的 this 指向)
  2. Vue 对于模板中调用的方法进行了优化:模板内的方法名后面的()不是执行符号, 而是传入实参的容器
  3. methods 上的方法也能直接被视图绑定使用,但是每次更新都会导致方法的重新运算,一般这种情况更推荐使用计算属性
  4. 模板调用的方法尽量避免副作用操作 (事件处理函数除外)
  5. 经过 Vue 的代理(劫持)后, 所有的 method 都挂载到了 vm 实例上面, 而 methods 并没有暴露出来(所以,methods 注册的方法不能通过this.methods访问)

简单实现一下 methods

var Vue = (function () {
  function Vue(options) {
    this.$data = options.data();
    this._methods = options.methods;

    this._init(this);
  }

  Vue.prototype._init = function (vm) {
    initData(vm);
    initMethods(vm);
  }

  function initData(vm) {
    for (var key in vm.$data) {
      (function (key) {
        Object.defineProperty(vm, key, {
          get: function () {
            return vm.$data[key];
          },
          set: function (newValue) {
            vm.$data[key] = newValue;
          }
        })
      })(key);
    }
  }

  function initMethods(vm) {
    for (var key in vm._methods) {
      // vm[key] = vm._methods[key]
      vm[key] = vm._methods[key]?.bind(vm);
    }
  }

  return Vue;
})();

;(function (Vue) {
  var vm = new Vue({
    data() {
      return {
        count: 1,
      };
    },

    methods: {
      addCount() {
        this.count += 1;
      },
      minusCount() {
        this.count -= 1;
      }
    }
  });
})(Vue);