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

原文地址:https://www.cnblogs.com/greatdesert/p/11038026.html

时间: 2024-10-11 17:20:15

Vue 2.0 深入源码分析(五) 基础篇 methods属性详解的相关文章

Vue 2.0 深入源码分析(六) 基础篇 computed 属性详解

用法 模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的.在模板中放入太多的逻辑会让模板过重且难以维护,比如: <div id="example">{{ message.split('').reverse().join('') }}</div> <script> var app = new Vue({ el:'#example', data:{message:'hello world'} }) </script> 这样模板不再是简

Vue系列---理解Vue.nextTick使用及源码分析(五)

_ 阅读目录 一. 什么是Vue.nextTick()? 二. Vue.nextTick()方法的应用场景有哪些? 2.1 更改数据后,进行节点DOM操作. 2.2 在created生命周期中进行DOM操作. 三. Vue.nextTick的调用方式如下: 四:vm.$nextTick 与 setTimeout 的区别是什么? 五:理解 MutationObserver 六:nextTick源码分析 回到顶部 一. 什么是Vue.nextTick()? 官方文档解释为:在下次DOM更新循环结束之

JDK源码分析(12)之 ConcurrentHashMap 详解

本文将主要讲述 JDK1.8 版本 的 ConcurrentHashMap,其内部结构和很多的哈希优化算法,都是和 JDK1.8 版本的 HashMap是一样的,所以在阅读本文之前,一定要先了解 HashMap,可以参考 HashMap 相关:另外 ConcurrentHashMap 中同样有红黑树,这部分可以先不看不影响整体结构把握,有兴趣的可以查看 红黑树: 一.ConcurrentHashMap 结构概述 1. 整体概述 CHM 的源码有 6k 多行,包含的内容多,精巧,不容易理解:建议在

jQuery源码分析(九) 异步队列模块 Deferred 详解

deferred对象就是jQuery的回调函数解决方案,它解决了如何处理耗时操作的问题,比如一些Ajax操作,动画操作等.(P.s:紧跟上一节:https://www.cnblogs.com/greatdesert/p/11433365.html的内容) 异步队列有三种状态:待定(pending).成功(resolved)和失败(rejected),初始时处于pending状态 我们可以使用jQuery.Deferred创建一个异步队列,返回一个对象,该对象含有如下操作: done(fn/arr

jQuery 源码分析(十九) DOM遍历模块详解

jQuery的DOM遍历模块对DOM模型的原生属性parentNode.childNodes.firstChild.lastChild.previousSibling.nextSibling进行了封装和扩展,用于在DOM树中遍历父元素.子元素和兄弟元素. 可以通过jQuery的实例来访问,方法如下: parent()             ;获取匹配元素的父元素 parents(selector)         ;获取匹配元素的所有祖先元素                        ;s

转载Aaron ---- jQuery 2.0.3 源码分析core - 选择器

jQuery 2.0.3 源码分析core - 选择器(02) 声明:本文为原创文章,如需转载,请注明来源并保留原文链接Aaron,谢谢! 打开jQuery源码,一眼看去到处都充斥着正则表达式,jQuery框架的基础就是查询了,查询文档元素对象,所以狭隘的说呢,jQuery就是一个选择器,并这个基础上构建和运行查询过滤器! 工欲善其事,必先利其器,所以先从正则入手 我们来分解一个表达式 // A simple way to check for HTML strings // Prioritize

baksmali和smali源码分析(五)

官方文档对于dex中的class数据结构表示如下: class_idx uint index into the type_ids list for this class. This must be a class type, and not an array or primitive type. access_flags uint access flags for the class (public, final, etc.). See "access_flags Definitions&quo

Nouveau源码分析(五):NVIDIA设备初始化之nouveau_drm_load (2)

Nouveau源码分析(五) 接着上一篇来,先把nouveau_drm_load再贴出一遍来吧: // /drivers/gpu/drm/nouveau/nouveau_drm.c 364 static int 365 nouveau_drm_load(struct drm_device *dev, unsigned long flags) 366 { 367 struct pci_dev *pdev = dev->pdev; 368 struct nouveau_drm *drm; 369 i

[Android] Volley源码分析(五)答疑

Volley源码分析系列出了有一段日子了,有不少看官私底下给我留言,同时抛出了一些问题.对于一些比较简单的问题我们跳过去,这两天接到网友是@smali提出的问题.不得不赞一下这位看官看源码时候的细腻程度,我引出这个问题供大家一块思考一下. Q:在写入文件头数据的时候为何不直接写入Int而是通过移位的方式来完成? 我们来看一下对应的源码: writeInt(os, CACHE_MAGIC); static void writeInt(OutputStream os, int n) throws I