vuex的实现
源代码可以查看我的github: https://github.com/Jasonwang911/TryHardEveryDay/tree/master/Vuex/vuex-resouce 欢迎star
先描述一下vuex的使用:
store.js
import Vue from "vue";
import Vuex from "./vuex/myVuex"; Vue.use(Vuex); export default new Vuex.Store({
state: {
age: 20
},
getters: {
// date 的 computed
myAge(state) {
return state.age + 10;
}
},
mutations: {
syncAdd(state, payload) {
state.age += payload;
},
syncMinuts(state, payload) {
state.age -= payload;
}
},
actions: {
asyncMinus({ commit }, payload) {
setTimeout(() => {
commit("syncMinuts", payload);
}, 1000);
}
}
});
main.js中引用:
import Vue from "vue";
import App from "./App.vue";
import router from "./router";
import store from "./store"; Vue.config.productionTip = false; new Vue({
router,
store, // 在每个实例上添加一个 $store 对象
render: h => h(App)
}).$mount("#app");
先说这两点
1. Store是一个类
2. Vue.use(Vuex);
首先建立一个类并导出,同时导出一个install的方法,这个方法接收一个参数 _Vue,即 vue实例
let Vue
class Store {
}
const install = _Vue => {
Vue = _Vue
}
export default {
Store,
install
}
然后再main.js 中所作的就是讲store实例注册到vue的跟组件和所有的子组件上, 这里使用了Vue.mixin()的方法,在每个组件中注入$store,并在子组件中通过 this.$parents来拿到父组件的$store并添加到子组件的实例上
const install = _Vue => {
Vue = _Vue;
// console.log(Vue);
Vue.mixin({
beforeCreate() {
if (this.$options && this.$options.store) {
// 根组件
this.$store = this.$options.store;
} else {
this.$store = this.$parent && this.$parent.$store;
}
}
});
};
先来看看state是怎么用的
import Vue from "vue";
import Vuex from "./vuex/myVuex"; Vue.use(Vuex); export default new Vuex.Store({
state: {
age: 20
},
});
在new Vuex.Store的实例的时候传入了一个对象,这个对象options
然后我们添加state的这个属性
class Store {
constructor(options) {
// options 是 new Vuex时注入的对象
this._vm = options.state || {};
}
get state() {
// store.state
return this._vm;
}
}
这里有一个问题,通过options获取的state并不是Observe状态的,并不能响应式的更新视图,如何做才能使state变成响应式的并触发视图的更新呢,也就是通过Vue的数据劫持进行包装转换,
这里通过new Vue,并把state放入创建的Vue的data中来实现这个操作
class Store {
constructor(options) {
// options 是 new Vuex时注入的对象
this._vm = new Vue({
data: {
state: options.state
}
});
}
get state() {
// store.state
return this._vm.state;
}
}
这样,$store.state就变成了响应式的状态了
接下来,同理 getters,mutations, actions 也是通过options传入获取的
import Vue from "vue";
import Vuex from "./vuex/myVuex"; Vue.use(Vuex); export default new Vuex.Store({
state: {
age: 20
},
getters: {
// date 的 computed
myAge(state) {
return state.age + 10;
}
},
mutations: {
syncAdd(state, payload) {
state.age += payload;
},
syncMinuts(state, payload) {
state.age -= payload;
}
},
actions: {
asyncMinus({ commit }, payload) {
setTimeout(() => {
commit("syncMinuts", payload);
}, 1000);
}
}
});
先来实现一下getters方法: 每一个getter方法其实都是getters的一个属性,但是这个属性返回了一个函数。属性可以返回函数的方法可以通过Object.definedProperty()中的get()来实现:
class Store {
constructor(options) {
// options 是 new Vuex.Store时注入的对象
// getters 拿到new Store的时候传入的getters
let getters = options.getters || {};
// 创建 Store 的 getters 属性
this.getters = {};
Object.keys(getters).forEach(getterName => {
// 是个函数,但是返回的是个属性
Object.defineProperty(this.getters, getterName, {
get() {
return getters[getterName](this.state);
}
});
});
}
}
这里其实只做了一件事情: 循环传入的options上的getters对象,并在用户调用getters中的每一个属性的时候返回一个getter函数并执行,
同理,mutations和actions也是如此实现的,只不过各自多了一个commit和dispatch的方法。
commit 和 dispatch 方法的原理就是通过参数type去对应的mutations和actions中查找对应的mutation或者action传入payload并执行
dispatch = (type, payload) => {
this.actions[type](payload);
};
commit = (type, payload) => {
this.mutations[type](payload);
};
查看Vuex源码,作者巧妙的将这个通过对象key进行循环的方法封装成了一个forEach函数:
const forEach = (obj, callback) => {
Object.keys(obj).forEach(key => {
callback(key, obj[key]);
});
};
这个函数传入了一个对象和一个回调函数,通过对key的循环,执行了回调函数,并向回调函数中传入了循环出对象obj的key和value,整理后整个Store对象变成了如下:
const forEach = (obj, callback) => {
Object.keys(obj).forEach(key => {
callback(key, obj[key]);
});
};
class Store {
constructor(options) {
// options 是 new Vuex时注入的对象
// this._s = options.state || {};
// 将store中的状态变成可被观测的数据
this._vm = new Vue({
data: {
state: options.state
}
});
// getters 拿到new Store的时候传入的getters
let getters = options.getters || {};
// 创建 Store 的 getters 属性
this.getters = {};
forEach(getters, (getterName, fn) => {
Object.defineProperty(this.getters, getterName, {
get: () => {
return fn(this.state);
}
});
});
// mutations
let mutations = options.mutations || {};
this.mutations = {};
forEach(mutations, (mutationName, fn) => {
this.mutations[mutationName] = payload => {
fn(this.state, payload);
};
});
// actions
let actions = options.actions || {};
this.actions = {};
forEach(actions, (actionName, fn) => {
this.actions[actionName] = payload => {
fn(this, payload);
};
});
}
dispatch = (type, payload) => {
this.actions[type](payload);
};
commit = (type, payload) => {
this.mutations[type](payload);
};
get state() {
return this._vm.state;
}
}
以上基本实现了一个简单的vuex的基本流程,所有的源码可以在我的github上查看,后续会继续修改支持vuex的模块化。
vuex的实现的更多相关文章
- 关于Vue.js 2.0 的 Vuex 2.0,你需要更新的知识库
应用结构 实际上,Vuex 在怎么组织你的代码结构上面没有任何限制,相反,它强制规定了一系列高级的原则: 应用级的状态集中放在 store 中. 改变状态的唯一方式是提交mutations,这是个同步 ...
- vuex复习方案
这次复习vuex,发现官方vuex2.0的文档写得太简略了,有些看不懂了.然后看了看1.0的文档,感觉很不错.那以后需要复习的话,还是先看1.0的文档吧.
- vuex 初体验
vuex是vue的状态管理工具,vue进阶从es6和npm开始,es6推荐阮一峰大神的教程. vuex学习从官方文档和一个记忆小游戏开始.本着兴趣为先的原则,我先去试玩了一把-->. Vuex ...
- vuex(1.0版本写法)
Vuex 是一个专门为 Vue.js 应用所设计的集中式状态管理架构. 官方文档:http://vuex.vuejs.org/zh-cn/ 2.0和1.0都能在此找到 每一个 Vuex 应用的核心就 ...
- 关于Vue vuex vux 文档
01. vue 链接 http://vuejs.org.cn/guide/ 02. vuex ----->>状态管理模块儿<<------- https://vuex.vue ...
- vuex
英文:(Introduction)中文:https://github.com/vuejs/vuex/issues/176(贡献者努力中)
- Vue 2.0 + Vue Router + Vuex
用 Vue.js 2.x 与相配套的 Vue Router.Vuex 搭建了一个最基本的后台管理系统的骨架. 当然先要安装 node.js(包括了 npm).vue-cli 项目结构如图所示: ass ...
- Vue2.X的状态管理vuex记录
记住上述的顺序情况:想要改变state,只能通过Mutation,虽然action可以直接改变state,这样会使每个状态可以方便的跟踪和记录(用Devtools跟踪) vue Method -- ...
- 在vue1.0遇到vuex和v-model的坑
事情是这样的,在开发项目的过程中我使用了vuex并且在store中定义了一个保存用户信息的对象 userInfo : { 'nickName' : '', // 昵称 'password' :'', ...
- vuex 笔记
Vuex 笔记 一个简单的状态管理 单一数据源: const sourceOfTruth = {} const vmA = new Vue({ data: sourceOfTruth }) const ...
随机推荐
- MySQL之SQL优化详解(三)
目录 MySQL 之SQL优化详解(三) 1. 索引优化 2. 剖析报告:Show Profile MySQL 之SQL优化详解(三) 1. 索引优化 一旦建立索引,select 查询语句的where ...
- Storm 学习之路(二)—— Storm核心概念详解
一.Storm核心概念 1.1 Topologies(拓扑) 一个完整的Storm流处理程序被称为Storm topology(拓扑).它是一个是由Spouts 和Bolts通过Stream连接起来的 ...
- 以实现MongoDB副本集状态的监控为例,看Telegraf系统中Exec输入插件如何编写部署
既有的Telegraf 关于MongoDB的输入插件很难实现对副本集节点状态的监控,副本集节点状态有 PRIMARY.SECONDARY.RECOVERYING.ARBITER 等.现在我们尝试通过 ...
- 【安装】Hadoop2.8.0搭建过程整理版
Hadoop搭建过程 前期环境搭建主要分为软件的安装与配置文件的配置,集成的东西越多,配置项也就越复杂. Hadoop集成了一个动物园,所以配置项也比较多,且每个版本之间会有少许差异. 安装的方式有很 ...
- Java进阶——高性能MySQL(一)
MySQL逻辑架构: 链接管理与安全性: MySQL5.5或更高版本版本提供了一个API,支持线程池(Thread-Pooling)插件,可以使用池中的少量线程来服务大量的连接. 优化与并行: MyS ...
- node中websocket的使用
web Socket和Socket.IO框架 http协议是无状态的,就是说客户端可以给服务器提交请求,但是服务器不能向客户端提交请求,但是我们实际项目中会要求客户和服务器双方是类似电话那种关系, 一 ...
- 为什么很多IT公司不喜欢进过培训机构的人呢
这几天在知乎看到一个问题“为什么很多IT公司不喜欢进过培训机构的人呢?” 身为IT培训师,这样的问题必然会引起我的关注, 花时间看了各路人士的回答, 我了个去,尽是对培训机构排山倒海的谩骂声, 负面评 ...
- Apicloud 接入海康摄像头
1准备工作 , 加载apicloud 海康视频模块. 引入 SDK 重新生成项目测试 再config.xml写入appid 话不多说直接上代码 video=api.require("haik ...
- shell遍历文件
取文件每行的数据,需要按列取 可以 sed 加管道 使用 awk 取列 platform="list.txt" line=`grep -vc '^$' $platform` ; ...
- 201907 TIOBE 编程语言排行榜-Python坐稳第三
目录 一.编程语言7月排行榜 二.Top10编程语言指数走势(2002-2018) 三.历史排名(1988-2019) 四.编程语言"名人榜"( 2003-2018) 五.Top2 ...