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

Vue.js 源码分析(五) 基础篇 方法 methods属性详解的更多相关文章

  1. Vue.js 源码分析(十三) 基础篇 组件 props属性详解

    父组件通过props属性向子组件传递数据,定义组件的时候可以定义一个props属性,值可以是一个字符串数组或一个对象. 例如: <!DOCTYPE html> <html lang= ...

  2. Vue.js 源码分析(十一) 基础篇 过滤器 filters属性详解

    Vue.js 允许你自定义过滤器,可被用于一些常见的文本格式化.过滤器可以用在两个地方:双花括号插值和 v-bind 表达式 (后者从 2.1.0+ 开始支持).过滤器应该被添加在 JavaScrip ...

  3. Vue.js 源码分析(四) 基础篇 响应式原理 data属性

    官网对data属性的介绍如下: 意思就是:data保存着Vue实例里用到的数据,Vue会修改data里的每个属性的访问控制器属性,当访问每个属性时会访问对应的get方法,修改属性时会执行对应的set方 ...

  4. Vue.js 源码分析(三) 基础篇 模板渲染 el、emplate、render属性详解

    Vue有三个属性和模板有关,官网上是这样解释的: el ;提供一个在页面上已存在的 DOM 元素作为 Vue 实例的挂载目标 template ;一个字符串模板作为 Vue 实例的标识使用.模板将会 ...

  5. Vue.js 源码分析(二) 基础篇 全局配置

    Vue.config是一个对象,包含Vue的全局配置,可以在启动应用之前修改下列属性,如下: ptionMergeStrategies        ;自定义合并策略的选项silent         ...

  6. Vue.js 源码分析(九) 基础篇 生命周期详解

    先来看看官网的介绍: 主要有八个生命周期,分别是: beforeCreate.created.beforeMount.mounted.beforeupdate.updated   .beforeDes ...

  7. Vue.js 源码分析(八) 基础篇 依赖注入 provide/inject组合详解

    先来看看官网的介绍: 简单的说,当组件的引入层次过多,我们的子孙组件想要获取祖先组件的资源,那么怎么办呢,总不能一直取父级往上吧,而且这样代码结构容易混乱.这个就是这对选项要干的事情 provide和 ...

  8. Vue.js 源码分析(七) 基础篇 侦听器 watch属性详解

    先来看看官网的介绍: 官网介绍的很好理解了,也就是监听一个数据的变化,当该数据变化时执行我们的watch方法,watch选项是一个对象,键为需要观察的数据名,值为一个表达式(函数),还可以是一个对象, ...

  9. Vue.js 源码分析(十) 基础篇 ref属性详解

    ref 被用来给元素或子组件注册引用信息.引用信息将会注册在父组件的 $refs 对象上.如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素:如果用在子组件上,引用就指向组件实例,例如: ...

随机推荐

  1. 腾讯云-ASP.NET Core+Mysql+Jexus+CDN上云实践

    腾讯云-ASP.NET Core+Mysql+Jexus+CDN上云实践.md 开通腾讯云服务器和Mysql 知识点: ASP.NET Core和 Entity Framework Core的使用 L ...

  2. Comet OJ-2019国庆欢乐赛

    国庆玩的有点嗨,开学了补题. A轰炸平面镇魂曲 题目描述 虹村万泰是一位二维世界的替身使者,他的替身 "轰炸平面镇魂曲" 能产生一条直线分割整个平面. 一开始,平面上有一个矩形,其 ...

  3. LeetCode——Rank Scores

    Write a SQL query to rank scores. If there is a tie between two scores, both should have the same ra ...

  4. java中方法的重载和覆盖分别要满足的条件

    1.重载:遵循“两同三不同” 两同:同一个类中的同名方法 三不同:形参的类型,个数,顺序不同 特别提醒: 返回值不同构不能方法重载 形参名称不同构不成方法重载 2.覆盖(重写)的要求 子类方法的名称, ...

  5. Python环境安装与基础语法(4)——内存管理、if分支

    Python内存管理 python中有自动清理内存垃圾的功能,当变量的引用计数为0,则可以被有计划的垃圾回收GC 常量会在系统中被多次引用,所以常量的引用计数无法确定 程序控制 顺序:按照先后顺序逐条 ...

  6. XGBoost和LightGBM的参数以及调参

    一.XGBoost参数解释 XGBoost的参数一共分为三类: 通用参数:宏观函数控制. Booster参数:控制每一步的booster(tree/regression).booster参数一般可以调 ...

  7. C++学习视频和资料

    我在学习c++时,比较迷茫,而且当时学完c++primer时不知道该学习什么, 犹豫了好久,最后找到了一些关于c++学习路线的视频,包含源代码,我感觉还不错,分享给大家. 下载地址 https://d ...

  8. Lerp在X秒内插值

    在X秒内插值 我们知道Mathf.Lerp函数的是用在两个值之间进行插值,用于平滑过渡. var 插值结果 = Mathf.Lerp(from,to,rate) //rate是0~1的值 Unity没 ...

  9. 简单C语言程序

    #include<stdio.h> int main(void) { /* 计算两个时间的时间差 */ int hour1, minute1; int hour2, minute2; pr ...

  10. java执行hive命令或者脚本

    java执行脚本 import java.io.*; import java.text.DateFormat; import java.text.SimpleDateFormat; import ja ...