最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • Vuex 使用解析+原理模拟

    正文概述 掘金(德善啊)   2021-04-04   565

    Vuex 注册:

    // main.js 中导入 store,并在 Vue 中注册
    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,
        render: h => h(App)
    }).$mount('#app')
    

    Vuex 配置:

    // store 文件下 index.js 文件进行 vuex 的配置:
    import Vue from 'vue'
    import Vuex from 'vuex'// 导入 Vuex 对象
    
    Vue.use(Vuex)// 调用 vuex 的 install 方法
    
    // store 是一个构造函数,接受五个属性为参数
    export default new Vuex.Store({
        // 状态管理仓库,将需要统一管理的状态存储到 state 中
        state: {},
        // Vuex 允许我们在 store 中定义“getter”(可以认为是 store 的计算属性)。就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算
        getters: {},
        // 更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数
        mutations: {},
        // Action 提交的是 mutation,而不是直接变更状态; Action 可以包含任意异步操作
        actions: {},
        // Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块
        modules: {},
    })
    
    

    简而言之:vuex 中有五个属性进行状态管理,

    • state 用于统一储存 需要管理的状态;
    • getters 相当于 vue 的computed,监听状态变化执行响应操作;
    • mutations 更改状态的同步操作;
    • actions 更改状态的异步操作,最终提交 mutations;
    • modules 可以简单理解为分模块状态管理,模块中具备 vuex 的所有功能;

    Vuex 基本使用:

    mapState , mapGetters , mapMutations 辅助函数:简化使用 $store.state...

    • state
    // store 文件下 index.js
    export default new Vuex.Store({
        state: {
            count: 0,
            msg: "hello VueX"
        }
    })
    
    // ---------- state 使用 -----------
    // 1. $store.state.count 
    // 2. 简化使用:可直接使用 count
    import { mapState } from "vuex"
    export default {
        //strict:true,// 严格模式开启,只是抛出异常,生产环境不建议开启严格模式,会深度检查状态树影响性能
        strict: process.env.NODE_ENV !== "production",
        computed: {
            // mapState 会返回一个对象,包含两个计算属性对应的方法如下:
            // {count: state => state.count,..}
            // mapState 的参数可以接收数组,也可以接收对象
            // ...mapState(['count','msg'])
            // 如果 data 中已存在 count msg 设置属性名
            ...mapState({ num: 'count', message: 'msg' })
        }
    }
    
    • getters
    // store 文件下 index.js
    export default new Vuex.Store({
        state: {
            count: 0,
            msg: "hello VueX"
        },
        // getter 相当于组件的计算属性,对state的数据进行处理再展示
        getters: {
            reverseMsg(state) {
                return state.msg.split('').reverse().join('')
            }
        }
    
    })
    
    // ---------- getters 使用 -----------
    // 1. $store.getters.reverseMsg 
    // 2. 简化使用:可直接使用 reverseMsg
    import { mapGetters } from "vuex";
    export default {
        computed: {
            // mapGetters 会返回一个对象,包含两个计算属性对应的方法如下:
            // count: state => state.count
            // ...mapGetters(['reverseMsg','...'])
            // 如果 data 中已存在 reverseMsg 设置属性名
            ...mapGetters({ msg: 'reverseMsg', '...': '...' })
    
        }
    }
    
    • mutations
    // store 文件下 index.js
    // 视图中修改状态 mutation
    export default new Vuex.Store({
        // 点击按钮增加数值
        mutation: {
            // state 状态
            // payload 额外参数,可为对象
            increate(state, payload) {
                state.count += payload
            }
        }
    
    })
    
    // ---------- mutation 使用 ----------- devtools 中方便调试
    // mutation 本质是方法,使用时需要commit方法提交,使用 map 函数将 mutation 映射到当前组建的 mes 中
    // 每次点击按钮,count 值加一
    // 1. @click = "$store.commit('increate',1)"
    // 2. 简化使用:可直接使用  @click = "inc(1)"
    // mapMutations 返回一个对象,对应 mutation 中的方法,不再是计算属性,需要放到 methods 中 
    import { mapMutations } from "vuex";
    export default {
        methods: {
            ...mapMutations({ inc: 'increate', '...': '...' })
        }
    }
    
    • actions
    // store 文件下 index.js
    // 执行异步状态 actions
    export default new Vuex.Store({
        actions: {
            // context 第一个参数:包含state commit getters 成员
            increateAsync(context, payload) {
                setTimeout(() => {
                    // 提交到 mutations
                    context.commit('increate', payload)
                }, 2000)
            }
        }
    })
    
    // ---------- action 使用 ----------- 
    // 1. @click = "$store.dispatch.('increateAsync',1)"
    // 2. 简化使用:可直接使用  @click = "inc(1)"
    // mapActions 返回一个对象,对应 Actions 中的方法,不再是计算属性,需要放到 methods 中 
    import { mapActions } from "vuex";
    export default {
        methods: {
            ...mapActions({ inc: 'increateAsync', '...': '...' })
        }
    }
    
    • modles
    // 导入 vuex 的模块,模块的内容与主模块相同
    import cart from "./module/cart";
    import products from "./module/products";
    export default new Vuex.Store({
        modules: {
            cart,
            products
        }
    
    })
    
    // ---------- modules 使用 ----------- 
    // 1. @click = "$store.commit('setNums',[])
    
    // 2. cart 存储在 $store.state 中,调用使用 $store.state.cart... 调用;mutation 调用如上
    // 3. 命名空间:如 modules 中的 mutation 的方法与 state 中 mutation 的方法重名
    
    import { mapState } from "vuex"
    export default {
        computed: {
    
            ...mapState(['setCart']),// 主模块中管理的状态 setCart
            ...mapState("cart", ["setCart"]) // cart 中管理的状态 setCart
        },
        methods: {
            ...mapMutations("cart", { setc: 'setCart', '...': '...' })
        }
    
    

    模拟简易 vuex

    组件中的使用:我们将只实现以下 4 个属性功能

    <template>
      <div id="app">
        <h1>Vuex - Demo</h1>
        <h2>State</h2>  
        count:{{ $store.state.count }} <br>msg: {{ $store.state.msg }}
        <h2>Getter</h2> {{ $store.getters.reverseMsg }}
        <h2>Mutation</h2>// 修改状态调用$store.commit
        <button @click="$store.commit('increate', 2)">Mutation</button>  
        <h2>Action</h2>// 执行异步操作调用 $store.dispatch 分发action
        <button @click="$store.dispatch('increateAsync', 5)">Action</button> 
      </div>
    </template>
    

    根据配置我们知道 Vuex 返回一个对象:

    1. 使用 Vue.use() 调用 Vuex 的 install 方法,
    2. Vuex 中包含 Store 构造函数,接受 5 个属性为参数
    import Vuex from 'vuex' // 导入 Vuex 对象
    Vue.use(Vuex) // 调用 vuex 的 install 方法
    export default new Vuex.Store({}) // store 是一个构造函数,接受五个属性为参数
    

    vuex 基本结构:

    // 在install 我们可以获取到 vue 的构造函数,后面我们还会在 store 使用到 vue 的构造函数,所以提前定义 _Vue
    let _Vue = null
    // 定义 Store 类
    class Store {}
    // 所有的插件都有一个 install 方法,vuex 的install 方法将 Store 挂载到 vue.$store 上
    // install 需要接受两个参数 一个Vue 一个额外的选项,因为我们模拟的是简易的 Vuex 所以只接受 Vue 参数
    function install (Vue) {
      _Vue = Vue
    }
    // 导出内容
    export default {
      Store,
      install
    }
    

    install 实现:

    function install (Vue) {
      _Vue = Vue
      _Vue.mixin({  // 将 Store 注入 vue 实例,使 Store 在所有组件中可以通过 $store 访问
        beforeCreate () {
          // this 是 vue 实例,如果是组件实例则没有 store 对象 
          if (this.$options.store) {
            _Vue.prototype.$store = this.$options.store
          }
        }
      })
    }
    

    Store 类实现:

    class Store {
      // Store 接受 5 个属性参数
      constructor(options){
        const { 
          state = {}, // 设置默认值{},防止用户未传入该属性时报错
          getters = {},
          mutations = {},
          actions = {}
        } = options // 参数中的属性结构
        // state
        this.state = _Vue.observable(state) // 将state属性设置响应式数据
        // getters
        this.getters = Object.create(null)
        Object.keys(getters).forEach(key => {
          // 创建 getters 对象,遍历对象属性,利用 definedProperty 将 key 注册到 this.getters 对象中
          Object.defineProperty(this.getters, keys, {
            get: () => getters[key](state)
          })
        })
        // 将 mutations,actions 存储到对应的属性中,在 commit ,dispatch 中要获取
        this._mutations = mutations
        this._actions = actions
      }
      // commit 方法
      commit( type, payload){
        this._mutations[type](this.state, payload)
      }
      diapatch( type, payload){
        this._actions[type](this, payload)
      }
    }
    

    总结:

    • state:利用 vue 的 observable 将 state 中的状态设置为响应式数据
    • getters:利用 Object.defineProperty() 将 getters 中定义的方法挂载到 store 上,传入 state 并执行响应方法
    • mutations,action :则是通过 commit 与 dispatch 方法,进行调用内部方法

    结语:以上内容全学习时手敲记录,无复制粘贴,全原创,希望可以给各位小伙伴带来收获,如有错误的地方或有疑问欢迎留言,感谢阅读!

    祝各位前端程序猿前程似锦,一路向北!


    起源地下载网 » Vuex 使用解析+原理模拟

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元