• Vue.js 源码分析(五) 基础篇 方法 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()进行初始化,如下:

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

  • 相关阅读:
    Lucene in action 笔记 case study
    关于Restful Web Service的一些理解
    Lucene in action 笔记 analysis篇
    Lucene in action 笔记 index篇
    Lucene in action 笔记 term vector
    Lucene in action 笔记 search篇
    博客园开博记录
    数论(算法概述)
    DIV, IFRAME, Select, Span标签入门
    记一个较困难的SharePoint性能问题的分析和解决
  • 原文地址:https://www.cnblogs.com/greatdesert/p/11038026.html
Copyright © 2020-2023  润新知