mutation是更改Vuex的store中的状态的唯一方法,mutation类似于事件注册,每个mutation都可以带两个参数,如下:

  state     ;当前命名空间对应的state

  payload     ;传入的参数,一般是一个对象

创建Vuex.Store()仓库实例时可以通过mutations创建每个mutation

我们不能直接调用一个mutation,而是通过 store.commit来调用,commit可以带两个参数,如下:

  type     ;对应的mutation名

  payload    ;传入的参数

commit还有一种写法,就是传入一个对象即可,该对象可以带一个type参数,type指定为mutation的名称,整个对象会作为参数传递给mutation。注意:mutation里包含的是同步操作

例如:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script src="https://unpkg.com/vuex@3.1.0/dist/vuex.js"></script>
</head>
<body> <div id="app">
<p>{{no}}</p>
<button @click="test1">测试1</button>
<button @click="test2">测试2</button>
</div>
<script>
const store = new Vuex.Store({
state:{no:100},
mutations:{
increment(state,payload){state.no+=payload.no;}
}
})
var app = new Vue({
el:"#app",
store:store,
computed:{
no(){return this.$store.state.no }
},
methods:{
test1(){
this.$store.commit('increment',{no:100}) //一般调用mutation的方法
},
test2(){
this.$store.commit({type:'increment',no:100}) //mutation的另一种写法
},
}
})
</script> </body>
</html>

源码分析


在创建Vuex.Store()初始化时会执行installModule()安装根模块,和mutation相关的如下:

  function installModule (store, rootState, path, module, hot) {      //安装模块
/*略*/ module.forEachMutation(function (mutation, key) { //遍历module模块的mutations对象,如果找到了,则执行这个匿名函数 参数1:每个mutation值 key:对应的键名
var namespacedType = namespace + key; //拼凑namespacedType
registerMutation(store, namespacedType, mutation, local); //调用registerMutation注册mutation
});
/*略*/
}

registerMutation用于注册mutation的,如下:

  function registerMutation (store, type, handler, local) {             //注册Mutations
var entry = store._mutations[type] || (store._mutations[type] = []); //如果store对象的_mutations对应的为空,则初始化为数组
entry.push(function wrappedMutationHandler (payload) { //则将一个匿名函数push到entry里面
handler.call(store, local.state, payload); //上下文是store,参数1为local.state,参数2为payload
});
}

writer by:大沙漠 QQ:22969969

也就是说注册完后对应的mutation会存储在store._mutations里,这是一个对象,每个键是一个mutation,而值就是对应的mutation,是个数组,例如例子里执行到这里时对应的_mutation如下:

等到我们调用this.$store.commit('increment',{no:100})去触发一个mutation时首先会触发Store函数内重定义的commit,它会以当前Store函数对象为上下文继续执行Store原型上的commit函数,如下:

  Store.prototype.commit = function commit (_type, _payload, _options) {      //对mutation的处理
var this$1 = this; // check object-style commit
var ref = unifyObjectStyle(_type, _payload, _options); //规范一下参数,返回一个对象,例如:{options: undefined,payload: {no: 100},type: "increment"}
var type = ref.type; //mutagion类型:比如:increment
var payload = ref.payload; //传递过来的参数
var options = ref.options; //选项 var mutation = { type: type, payload: payload };
var entry = this._mutations[type]; //直接从this._mutations里获取type类型的mutaion,是个函数数组
if (!entry) { //如果该mutaion不存在,则报错
{
console.error(("[vuex] unknown mutation type: " + type));
}
return
}
this._withCommit(function () { //在this._withCommit()环境下执行该函数
entry.forEach(function commitIterator (handler) { //遍历entry,依次执行每个handler函数,参数为payload
handler(payload);
});
});
this._subscribers.forEach(function (sub) { return sub(mutation, this$1.state); }); if (
options && options.silent
) {
console.warn(
"[vuex] mutation type: " + type + ". Silent option has been removed. " +
'Use the filter functionality in the vue-devtools'
);
}
};

unifyObjectStyle是一个工具函数,它会修正参数,并返回一个对象,如下:

  function unifyObjectStyle (type, payload, options) {        //统一object的类型
if (isObject(type) && type.type) { //如果type是个类型且含有type属性,比如这样的格式:this.$store.commit({type:'increment',no:1000})
options = payload;
payload = type;
type = type.type;
} {
assert(typeof type === 'string', ("expects string as the type, but found " + (typeof type) + "."));
} return { type: type, payload: payload, options: options } //最后返回该对象
}

我们在例子里可以用两种方式来调用mutation也是这个unifyObjectStyle函数的作用

_withCommit是一个工具函数,如下:

Store.prototype._withCommit = function _withCommit(fn) {                //执行fn函数 执行时设置this._committing为true,执行完后设置为false
var committing = this._committing; //保存this._committing到局部变量committing里
this._committing = true; //设置this._committing为true
fn(); //执行fn函数
this._committing = committing; //恢复this._committing
};

它在执行传入的函数时会设置Store._committing为true,这样就相当于设置了一个标记,表示当前是通过mutation来修改state的,还记得上一节说的strict严格模式吗,它就是通过这里的_committing来判断是否合法的。

vuex 源码解析(四) mutation 详解的更多相关文章

  1. 【源码解析】BlockManager详解

    1 Block管理模块的组件和功能 BlockManager:BlockManager源码解析 Driver和Executor都会创建 Block的put.get和remove等操作的实际执行者 Bl ...

  2. vuex 源码分析(六) 辅助函数 详解

    对于state.getter.mutation.action来说,如果每次使用的时候都用this.$store.state.this.$store.getter等引用,会比较麻烦,代码也重复和冗余,我 ...

  3. vuex 源码分析(五) action 详解

    action类似于mutation,不同的是Action提交的是mutation,而不是直接变更状态,而且action里可以包含任意异步操作,每个mutation的参数1是一个对象,可以包含如下六个属 ...

  4. 我的书籍《深入解析Java编译器:源码剖析与实例详解》就要出版了

    一个十足的技术迷,2013年毕业,做过ERP.游戏.计算广告,在大公司呆过,但终究不满足仅对技术的应用,在2018年末离开了公司,全职写了一本书<深入解析Java编译器:源码剖析与实例详解> ...

  5. Mybatis源码解析(四) —— SqlSession是如何实现数据库操作的?

    Mybatis源码解析(四) -- SqlSession是如何实现数据库操作的?   如果拿一次数据库请求操作做比喻,那么前面3篇文章就是在做请求准备,真正执行操作的是本篇文章要讲述的内容.正如标题一 ...

  6. nginx源码分析线程池详解

    nginx源码分析线程池详解 一.前言     nginx是采用多进程模型,master和worker之间主要通过pipe管道的方式进行通信,多进程的优势就在于各个进程互不影响.但是经常会有人问道,n ...

  7. 【集合框架】JDK1.8源码分析之ArrayList详解(一)

    [集合框架]JDK1.8源码分析之ArrayList详解(一) 一. 从ArrayList字表面推测 ArrayList类的命名是由Array和List单词组合而成,Array的中文意思是数组,Lis ...

  8. Sentinel源码解析四(流控策略和流控效果)

    引言 在分析Sentinel的上一篇文章中,我们知道了它是基于滑动窗口做的流量统计,那么在当我们能够根据流量统计算法拿到流量的实时数据后,下一步要做的事情自然就是基于这些数据做流控.在介绍Sentin ...

  9. Spring源码之九finishRefresh详解

    Spring源码之九finishRefresh详解 公众号搜索[程序员田同学],专职程序员兼业余写手,生活不止于写代码 Spring IoC 的核心内容要收尾了,本文将对最后一个方法 finishRe ...

随机推荐

  1. Spring Boot2 系列教程(二十二)整合 MyBatis 多数据源

    关于多数据源的配置,前面和大伙介绍过 JdbcTemplate 多数据源配置,那个比较简单,本文来和大伙说说 MyBatis 多数据源的配置. 其实关于多数据源,我的态度还是和之前一样,复杂的就直接上 ...

  2. .NET 使用OLEDB导入Excel数据

    /** * *在本章节中主要讲解的是如何使用OLEDB将Excel中的数据导入到数据库中 * */using System; using System.Data; using System.Data. ...

  3. oidc hybrid flow 与另外两种模式的异同

    很多学习identityserver的文章都没有解释清楚oidc hybrid混合模式的含义.本文将解释hybrid模式与另外两种模式的主要区别. 我们先看一下一手文档: https://openid ...

  4. [IDA] 将变量索引进行计算

    按 k 键 [ebp+var+arg_0] - > [ebp+value]

  5. U8 BOM数据结构

    U8 BOM涉及的数据表有四张 bom_bom     BOM资料  该表主要记录BOM表的一些基本信息,版本.创建.审核等信息,不包括任何子件.母件信息:bomid是BOM主键 bom_parent ...

  6. wpf 两个自定义控件

    wpf 两个自定义控件 一个是IP控件,一个滑动条.先看下效果图 IPControl 1.实际工作中有时需要设置IP信息,就想着做一个ip控件.效果没有window自带的好,需要通过tab切换.但也能 ...

  7. java基础(28):数据库、表及表数据、SQL语句

    1. 数据库 1.1 数据库概述 什么是数据库 数据库就是存储数据的仓库,其本质是一个文件系统,数据按照特定的格式将数据存储起来,用户可以对数据库中的数据进行增加,修改,删除及查询操作. 什么是数据库 ...

  8. MVC模式和Spring MVC初识

    概述 传统的Model1和Model2 在Model1的模式下,整个Web应用几乎全部是由JSP页面组成,接受和处理用户请求,并对请求处理后直接做出响应:JSP身兼View和Controller两个角 ...

  9. querySelectorAll和getElementsByClassName获取元素的区别

    querySelectorAll()方法是HTML5新增的方法,通过传入一个css选择符,返回所有匹配的元素而不仅仅是一个元素.这个方法返回的是一个NodeList的实例.那么它和通过getEleme ...

  10. JavaScript初探 四 (程序结构)

    JavaScript 结构 JavaScript 程序结构 JavaScript支持几乎和C语言一样的程序结构 分支结构 循环结构 分支结构 条件分支 if-else if语句:判断条件为true则执 ...