项目目录
附件代码下载
安装 vuex 插件
-
vue 入口文件
import Vue from 'vue' import App from './App.vue' import store from './store' Vue.config.productionTip = false let vm = new Vue({ name:'root', store, // 此 store 的目的是让所有组件都能访问到 store 对象 render: h => h(App) }).$mount('#app') // 所有组件都能执行的方法 Vue.mixin({beforeCreate}), 拿到 store 挂载到自己的身上
-
store.js
import Vue from 'vue' import Vuex from '@/vuex' Vue.use(Vuex) let store = new Vuex.Store({ plugins: [ // logger(), // persists() // 每次状态变化都可以存入到localStorage中 ], state: { // state = > data name: 'zhangsan', age: 12 }, mutations: { // method commit 同步更改状态 changeAge(state, payload) { state.age += payload } }, actions: { // 异步操作 调用api接口 dispatch, 多次commit mutation changeAge({ commit }, payload) { setTimeout(() => { commit('changeAge', payload); }, 1000); } }, getters: { // 计算属性 myAge(state) { return state.age + 10 } }, strict: true, // 如果不是在 mutation 中操作的状态会发生警告 modules: { // 进行模块分割 // namespaced 能解决子模块和父模块的命名冲突文件,相当于增加了一个命名空间 // 如果没有 namespaced 默认 getters 都会被定义到父模块上,mutations 会被合并在一起,最终一起调用,有了命名空间就没有这个问题了 // 子模块的名字不能和父模块中的状态重名 a: { namespaced: true, state: { name: 't1', age: 10 }, // 所有的getters 都会被合并到跟上 getters: { // 首页一个模块 home 订单页一个模块 order 用户一个模块 user myAge(state) { return state.age + 20; } }, mutations: { changeAge(state, payload) { state.age += payload } }, modules: { c: { namespaced: true, state: { age: 100 }, mutations: { changeAge(state, payload) { state.age += payload } }, modules: { d: { namespaced: true, state: { age: 100 }, } } } } }, b: { namespaced: true, state: { name: 'b' }, } } }) export default store;
-
vuex/index.js
import install from './install'; import Store from './store' export default { install, Store, }
-
vuex/install.js
// 此处将引入的 Vue 存储起来,避免了 vuex 与 vue 版本的强依赖 export let Vue; function install(_Vue) { Vue = _Vue; Vue.mixin({ beforeCreate() { // this 代表的是每个组件实例 // 获取根组件上的 store 将他共享给每个组件 // 每个组件中都应该有 $store let options = this.$options; if (options.store) { // 将 store 挂载到根实例上 this.$store = options.store } else { // 孩子组件获取 $store,由于渲染流程先父后子,父亲一定先有 $store 属性 if (this.$parent && this.$parent.$store) { this.$store = this.$parent.$store } } } }) } export default install
-
store.js
import { Vue } from './install' import { forEach } from './util' class Store { // new Vue.Store 缠身一个实例 constructor(options) { // 以下这些变量都是用户传递的 let { state, getters, mutations, actions, module, strict } = options; this.getters = {}; // 我再取getters属性的时候 把他代理到计算属性上 const computed = {}; forEach(getters, (fn, key) => { computed[key] = () => { return fn(this.state); // 为了保证参数是state } // 当我们去getters上取值 需要对computed取值 Object.defineProperty(this.getters, key, { get: () => this._vm[key] // 具备了缓存的功能 }) }); // ---------- this.mutations = {}; forEach(mutations, (fn, key) => { this.mutations[key] = (payload) => fn.call(this, this.state, payload); }); // ------dispatch中派发的是动作,里面可以有异步逻辑,更改状态都要通过mutation,mutation是同步更改的------- this.actions = {} forEach(actions, (fn, key) => { this.actions[key] = (payload) => fn.call(this, this, payload); }); // 这个状态在页面渲染时需要收集对应的渲染watcher,这样状态更新才会更新视图 this._vm = new Vue({ data: { // $符号开头的数据不会被挂载到实例上,但是会挂载到当前的_data上,减少了一次代理 $$state: state // 状态在哪里取值,就会收集对应的依赖 }, computed }); // 用户组件中使用的$store = this } // 类的属性访问器 get state() { // this.$store.state => defineProperty中的get // 依赖于 vue的响应式原理 return this._vm._data.$$state } dispatch = (type, payload) => { // 根据commit还是dispatch 找对应的存储结果 this.actions[type](payload) } commit = (type, payload) => { this.mutations[type](payload) } } // state getters action mutation (modules 分层) export default Store;
打赏作者
您的打赏是我前进的动力
微信
支付宝
linux 网络
上一篇
评论