项目目录

附件代码下载

安装 vuex 插件

  1. 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 挂载到自己的身上
    
  2. 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;
    
  3. vuex/index.js

    import install from './install';
    import Store from './store'
    
    export default {
      install,
      Store,
    }
    
  4. 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
    
  5. 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;
    
打赏作者
您的打赏是我前进的动力
微信
支付宝
评论

中午好👏🏻,我是 ✍🏻   疯狂 codding 中...

粽子

这有关于前端开发的技术文档和你分享。

相信你可以在这里找到对你有用的知识和教程。

了解更多

目录

  1. 1. 项目目录
  2. 2. 附件代码下载
  3. 3. 安装 vuex 插件