Vue 2.0 深入源码分析 基础篇 methods属性详解

Posted greatdesert

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vue 2.0 深入源码分析 基础篇 methods属性详解相关的知识,希望对你有一定的参考价值。

用法


 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的实现是比较简单的。

以上是关于Vue 2.0 深入源码分析 基础篇 methods属性详解的主要内容,如果未能解决你的问题,请参考以下文章

动手实践去实现 Vue 2.0 的核心原理

vue 2.0源码学习笔记—new Vue ( Vue 初始化过程 )

深入vue - 源码目录及构建过程分析

vue.js基础知识篇:过渡Method和Vue实例方法

以Vuex 2.0 为例,提升源码分析技能

spring boot 2.0 源码分析