用法
methods中定义了Vue实例的方法,官网是这样介绍的:

例如::
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <script src="https://cdn.bootcss.com/vue/2.5.16/vue.js"></script>
- <title>Document</title>
- </head>
- <body>
- <div id="app">{{message}}<button @click="ChangeMessage">测试按钮</button></div>
- <script>
- new Vue({
- el:'#app',
- data:{message:"Hello World!"},
- methods:{
- ChangeMessage:function(){this.message="Hello Vue!";}
- }
- })
- </script>
- </body>
- </html>
显示的样式为:

当我们点击按钮后变为了:

methods方法中的上下文为当前实例,也就是this为当前实例。
注:不应该使用箭头函数来定义 method 函数 (例如ChangeMessage:()=>this.message="Hello Vue")。理由是箭头函数绑定了父级作用域的上下文,所以 this 将不会按照期望指向 Vue 实例,this.message 将是 undefined。
源码分析
Vue实例后会先执行_init()进行初始化(4579行)时,会执行initState()对props, methods, data, computed 和 watch 进行初始化,如下:
- function initState (vm) { //第3303行
- vm._watchers = [];
- var opts = vm.$options;
- if (opts.props) { initProps(vm, opts.props); }
- if (opts.methods) { initMethods(vm, opts.methods); } //如果定义了methods,则调用initMethods初始化data
- if (opts.data) {
- initData(vm);
- } else {
- observe(vm._data = {}, true /* asRootData */);
- }
- if (opts.computed) { initComputed(vm, opts.computed); }
- if (opts.watch && opts.watch !== nativeWatch) {
- initWatch(vm, opts.watch);
- }
- }
initMethods()定义如下:
- function initMethods (vm, methods) { //第3513行
- var props = vm.$options.props;
- for (var key in methods) { //遍历methods对象,key是每个键,比如例子里的ChangeMessage
- {
- if (methods[key] == null) { //如果值为null,则报错
- warn(
- "Method \"" + key + "\" has an undefined value in the component definition. " +
- "Did you reference the function correctly?",
- vm
- );
- }
- if (props && hasOwn(props, key)) { //如果props中有同名属性,则报错
- warn(
- ("Method \"" + key + "\" has already been defined as a prop."),
- vm
- );
- }
- if ((key in vm) && isReserved(key)) { //如果key是以$或_开头则,也报错
- warn(
- "Method \"" + key + "\" conflicts with an existing Vue instance method. " +
- "Avoid defining component methods that start with _ or $."
- );
- }
- }
- vm[key] = methods[key] == null ? noop : bind(methods[key], vm); //如果key对应的值不是null,则执行bind()函数
- }
- }
执行bind()函数,参数1为对应的函数体,参数2是当前的Vue实例,bind()函数定义在第196行,如下:
- function polyfillBind (fn, ctx) { //当Function的原型上不存在bind()函数时,自定义一个函数实现同样的功能,用apply()或call()来实现
- function boundFn (a) {
- var l = arguments.length;
- return l
- ? l > 1
- ? fn.apply(ctx, arguments)
- : fn.call(ctx, a)
- : fn.call(ctx)
- }
- boundFn._length = fn.length;
- return boundFn
- }
- function nativeBind (fn, ctx) { //调用Function的原型上的bind()方法,上下文闻ctx
- return fn.bind(ctx)
- }
- var bind = Function.prototype.bind //如果Function的原型上有bind方法,则调用该方法,否则用自定义的polyfillBind()方法
- ? nativeBind
- : polyfillBind;
相比较其它API,method的实现是比较简单的。