vuex (状态管理模式) 详细介绍及使用


    vuex是什么
        是实现组件全局状态(数据)管理的一种机制,可以方便的实现组件之间数据的共享
    好处
        能够在vuex中,集中管理共享的数据,易于开发和后期维护
        能够高效地实现组件之间的数据共享,提高开发效率
        存放在vuex中的数据都是响应式的,能够实时保持数据与页面的同步
    安装 npm install vuex --save
    src里面创建store文件夹
        创建index.js配置vuex

//在mian.js里面写入:
        import Vue from "vue";
       import Vuex from "vuex";

        Vue.use(Vuex);
export default new Vuex.Store({
  state: {
    //存放的内容所有组件都可以访问,类似于data
    name:"张三'
    },
  mutations: {},
  actions: {},
  modules: {},
});

    在main.js
        import store from "./store";

Vue.config.productionTip = false;

new Vue({
  router,
  store,
  render: (h) => h(App),
}).$mount("#app");
    其他组件中使用
        <template>
  <div class="about">
    <h1>This is an about page</h1>
    {{name}}
  </div>
</template>
<script>
export default {
  computed:{
    name(){
      return this.$store.state.name
    }
  }
}
</script>
    state    
        提供唯一的公共数据源,所有共享数据都要统一放到Store的State中进行存储
        创建store数据源,
const store = new Vuex.Store({
    state:{
        name:"张三"
    }
})
        组件访问State中的数据
            第一种
this.$store.state.全局数据名称
this.$store.state.name
            第二种
1.从vuex 中按需导入mapState 函数
import {mapState} from "vuex"  
2.通过刚才导入的mapState函数,将当前组件需要的全局数据,映射为当前组件的computed计算属性
computed:{
    ...mapState(['name'])
}
        单一状态树
state里面的状态
            state:{
    name:"张三"
}
            使用计算属性获取最简单
computed:{
    name(){
      return this.$store.state.name
    }
        注意在其他方法中不要直接修改state里面的属性,想要修改请使用Mutation
    mutation
        用于变更Store中的数据
        提交更新数据的方法,必须是同步的(如果需要异步使用action)
        1.只能通过mutation变更store数据,不可以直接操作Store中的数据
        2. 通过这个方式虽然操作起来稍微繁琐一些,但是可以集中监听所有数据的变化
        注意:里面不要执行异步操作
        第一种触发
            //定义mutation
const store = new Vuex.Store({
    state:{
        count:0
    },
    mutations:{
    //第一个参数是state对象
        add(state){
        //变更状态
        state.count++
    }
    }
})


            //触发mutation
methods:{
    aa(){
        //add是mutation里面的方法
        this.$store.commit('add',)
    }
}
            可以在触发mutation时传递参数
                
                    //定义mutation
const store = new Vuex.Store({
    state:{
        count:0
    },
    mutations:{
    //第一个参数是state对象
    //va自定义的参数    
        add(state,va){
        //变更状态
        state.count += va
    }
    }
})

                    //触发mutation
methods:{
    aa(){
        //add是mutation里面的方法
        //携带参数 2
        this.$store.commit('add',2)
    }
}
        第二种触发
            1.从 vuex中按需导入mapMutations 函数

            import {mapMutations} from 'vuex'
            2. 将制定的mutations函数,映射为当前组件的methods函数中
            methods:{
    ...mapMutations(['add','ooo'])
}
        commit
            用来触发mutation里面方法用的
            this.$store.commit('mutations方法名',值)
        注意:  commit('方法名',参数1)  只支持传入一个参数数据 

注意:  commit('方法名',参数1,参数2)  参数2mutation里面获取不到,解决方法,可以把参数1和参数2和是一个数组用一个参数传递过去
    action
        和mutation功能大致相同,不同之处在与action提交的是mutation,而不是直接变更状态,可以包含异步操作
        用于处理异步任务
        如果通过异步操作变更数据,必须通过action,而不能使用mutation,但是在action中还是要通过触发mutation的方式间接变更数据
        //定义action
const store = new Vuex.Store({
    state:{
        count:0
    },
    mutations:{
        add(state){
        state.count++
    }
    },
actions:{
//第一个参数是context
    addAsync(context){
        setTimeout(()=>{
        context.commit('add')
},1000)
    }
}
})
        //触发action
            methods:{
    abc(){
        //addAsynce 是actions里面的方法
        this.$store.dispatch('addAsynce')
    }
}
            第二种触发
                1.从 vuex中按需导入mapActions 函数

                import {mapActions} from 'vuex'
                2. 将制定的mapActions函数,映射为当前组件的methods函数中
                methods:{
    ...mapAction(['addAsync'])
}
        dispatch
            用来触发action里面的方法
            this.$store.dispatch('addAsynce',值)
        携带参数
            //定义action
const store = new Vuex.Store({
    state:{
        count:0
    },
    mutations:{
        add(state,num){
        state.count+=num
    }
    },
actions:{
//第一个参数是context
    addAsync(context,num){
        setTimeout(()=>{
        context.commit('add',num)
},1000)
    }
}
})
            methods:{
    abc(){
        //addAsynce 是actions里面的方法
        this.$store.dispatch('addAsynce',4)
    }
}
        注意 action方法 返回的是一个Promise对象
    getter
        从基本数据state派生的数据,相当于state的计算属性,具有返回值的方法
        会返回一个新数据,不会影响到state里面的老数据
        store中的数据发生变化.getter的数据也会跟着变化
        const store = new Vuex.store({
    state:{
        count:0
    },
getters:{
    userId1:function(state){
        return state.count * 2
    }
}
})
        第一种使用方式  this.$store.getters.userId1
        第二种
import {mapGetters} form 'vuex'
computed:{
    ...mapGetters(['userId'])
}
        mapGetters 辅助函数
            辅助函数仅仅是将 store 中的 getter 映射到局部计算属性
            第一步 引入  import { mapGetters } from 'vuex'
            第二步
 computed: {
  // 使用对象展开运算符将 getter 混入 computed 对象中
//就可以以访问计算属性的形式去访问这些方法了
    ...mapGetters([
      'doneTodosCount',  //是getters里面的方法
      'anotherGetter',
      // ...
    ])
  }
            第三步使用  
{{doneTodosCount}}
    modules
        模块化vuex
        可以让每一个模块拥有自己的state,mutation,action,getters,使得结构非常清晰,方便管理
        由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。

为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割:
            const moduleA = {
  state: () => ({ name:"李四" }),
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}
            const store = new Vuex.Store({
    state:{
        name:"张三"
    }
  modules: {
    a: moduleA,
  }
})
            store.state.a // -> moduleA 的状态
        对于模块内部的 mutation 和 getter,接收的第一个参数是模块的局部状态对象
        mutations 使用mutations('aa/xx')
        getter模块内的不加命名空间的情况下
            const moduleA = {
  // ...
  getters: {
    sumWithRootCount (state, getters, rootState) {
      return state.count + rootState.count
    }
  }
}
            参数1是 当前模块内的state
            参数2 是当前store内的getters,包含其他modules里面定义的getters
            参数3是最外层根的state
            组件中使用
                $store.getters.名字
            命名空间下使用
                $store.getters['路径/名字']
        命名空间下的getter如果你希望使用全局 state 和 getter
            rootState 和 rootGetters 会作为第三和第四参数传入 getter
            也会通过 context 对象的属性传入 action
        命名空间
            默认情况下,模块内部的 action、mutation 和 getter 是注册在全局命名空间
            namespaced: true
                如果希望你的模块具有更高的封装度和复用性,你可以通过添加 namespaced: true 的方式使其成为带命名空间的模块
                当模块被注册后,它的所有 getter、action 及 mutation 都会自动根据模块注册的路径调整命名。
                const store = new Vuex.Store({
  modules: {
    account: {
      namespaced: true,

      // 模块内容(module assets)
      state: () => ({ ... }), // 模块内的状态已经是嵌套的了,使用 `namespaced` 属性不会对其产生影响
      getters: {
        isAdmin () { ... } // -> getters['account/isAdmin']
      },
      actions: {
        login () { ... } // -> dispatch('account/login')
      },
      mutations: {
        login () { ... } // -> commit('account/login')
      },

      // 嵌套模块
      modules: {
        // 继承父模块的命名空间
        myPage: {
          state: () => ({ ... }),
          getters: {
            profile () { ... } // -> getters['account/profile']
          }
        },

        // 进一步嵌套命名空间
        posts: {
          namespaced: true,

          state: () => ({ ... }),
          getters: {
            popular () { ... } // -> getters['account/posts/popular']
          }
        }
      }
    }
  }
})
        若需要在全局命名空间内分发 action 或提交 mutation
            将 { root: true } 作为第三参数传给 dispatch 或 commit 即可
        带命名空间的模块注册全局 action
            添加 root: true
            并将这个 action 的定义放在函数 handler
              modules: {
    foo: {
      namespaced: true,

      actions: {
        someAction: {
          root: true,
          handler (namespacedContext, payload) { ... } // -> 'someAction'
        }
      }
    }
  }

        带命名空间的绑定函数
            当使用 mapState, mapGetters, mapActions 和 mapMutations 这些函数来绑定带命名空间的模块时,写起来可能比较繁琐:
            computed: {
  ...mapState({
    a: state => state.模块名.属性名,
    b: state => state.some.nested.module.b
  })
},
methods: {
  ...mapActions([
    'some/nested/module/foo', // -> this['some/nested/module/foo']()
    'some/nested/module/bar' // -> this['some/nested/module/bar']()
  ])
}
            可以简化为
                computed: {
  ...mapState('some/nested/module', {
    a: state => state.a,
    b: state => state.b
  })
},
methods: {
  ...mapActions('some/nested/module', [
    'foo', // -> this.foo()
    'bar' // -> this.bar()
  ])
}
            你可以通过使用 createNamespacedHelpers 创建基于某个命名空间辅助函数
                import { createNamespacedHelpers } from 'vuex'

const { mapState, mapActions } = createNamespacedHelpers('some/nested/module')

export default {
  computed: {
    // 在 `some/nested/module` 中查找
    ...mapState({
      a: state => state.a,
      b: state => state.b
    })
  },
  methods: {
    // 在 `some/nested/module` 中查找
    ...mapActions([
      'foo',
      'bar'
    ])
  }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值