简述Vuex的使用

vuex是什么,引用官网的话来说。Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。通俗来说就相当于一个仓库,把你想要的值存在里面,像组件之间可以用组件的通信进行一些值的拿用,这只限于组件通信之间,而vuex小仓库里面的值在哪里都可以直接拿用。

1.安装

npm install vuex --save

下载之后在main.js里面全局引入并挂载

import Vue from 'vue'
import App from './App'
import router from './router'
import store from './store'

new Vue({
  el: '#app',
  router,
  store,
  components: { App },
  template: '<App/>'
})

 1.1.state

在src目录下创建一个store文件夹,并创建index.js文件

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)
const store = new Vuex.Store({
    state: {
        name:'张三',
        aaa:'111'
    },
    getters: {

    },
    mutations: {
       
    },
    actions: {

    }
})

export default store

如果vuex中引入的东西很多,全部写在这个页面就显得很多很乱,也是可以将state,getters,mutations,actions给抽离成单独文件出来。

import Vue from 'vue'
import Vuex from 'vuex'
import state from './state';
import mutations from './mutations';
import actions from './actions';
import getters from './getters';

Vue.use(Vuex)

const options = {
  state,
  mutations,
  actions,
  getters,
};
const store = new Vuex.Store(options);
export default store;

当然,也可以不这样处理,但是当项目大起来这样会是的代码更清晰,到这里vuex已经引入成功,我们在项目中直接就可以用,

export default {
  name: "App",
  created(){
    console.log(this.$store.state.name);//张三
  }
};

 2.mapState 辅助函数

        在每次用的时候都是this.$store.state.xxx的调用会显得非常的冗长,为此可以用mapState辅助函数帮助我们生成计算属性,

<script>
import { mapState } from "vuex";
export default {
  computed: {
    ...mapState(['aaa','name']),
  },
  mounted() {
    console.log(this.aaa);//111
    console.log(this.name);//张三
  },
 
};
</script>

2.getters

        有时候我们会对state里面的值进行一波处理,在不同的条件下输出不同的state,比如在部分页面里需要把上面的state里面的name换成'我叫张三',这时候怎么办,在需要修改的页面一个一个改太复杂,还是在state里面再定义一个新的值?这样代码看起来很乱冗长,那要是name的值在不同的条件又输出“你叫张三”,“他叫张三”,不可能一直加state的吧,这时候就需要用到了getters,能对state的值进行修改判断。

const store = new Vuex.Store({
    state: {
        aaa: 11,
        name:'张三'
    },
    getters: {
        changeName(state){
            return `我叫${state.name}`
        },
        takeName(state,getters){
            return `${state.aaa}-${getters.changeName}`
        }
    },
})

Getter 可以接受 state和getters 来作为其参数,直接处理参数输出,我们通过this.$store.getters.xxxzhi直接就可以用,当然,我们也可以使用辅助函数来使得代码更加简单

  created() {
    console.log(this.$store.getters.changeName);//我叫张三
    console.log(this.$store.getters.takeName);//11-我叫张三
  },

2.mapGetters 辅助函数

<script>
import { mapGetters } from "vuex";
export default {
  computed: {
    ...mapGetters(["changeName", "takeName"]),
  },
  created() {
    console.log(this.changeName);//我叫张三
    console.log(this.takeName);//11-我叫张三
  },
};
</script>

3.mutations

        用官网的话来解释getters和mutations的区别就是,getters是有时候我们需要从 store 中的 state 中派生出一些状态,mutations是更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。getters更像是一个对state的状态的一个修饰,而mutations则是变更状态。

const store = new Vuex.Store({
    state: {
        aaa: 11,
        name:'张三'
    },
    getters: {
        changeName(state){
            return `我叫${state.name}`
        },
        takeName(state,getters){
            return `${state.aaa}-${getters.changeName}`
        }
    },
    mutations:{
        changeAaa(state){
            state.aaa++
        },
        chagName(state,payload){
            state.name = payload.newName
        }
    }
})

mutations把state作为参数,进行修改,也可以传入额外的参数也叫mutation 的载荷(payload),调用mutation的方法需要用store.commit 方法。

created() {
    console.log(this.$store.state.aaa);//11
    this.$store.commit('changeAaa')
    console.log(this.$store.state.aaa);//12
  },

2.mapMutations辅助函数

mapMutations不是解析到计算属性里面,而是解析到方法里去,

<script>
import { mapMutations, mapState, mapGetters } from "vuex";
export default {
  data() {
    return {
      myname: "",
    };
  },
  computed: {
    ...mapState(["name", "aaa"]),
    ...mapGetters(["changeName", "takeName"]),
  },
  mounted() {
    console.log(this.aaa); //11
    this.$store.commit('changeAaa');
    console.log(this.aaa); //12

    console.log(this.name); //张三
    this.chagName({ newName: "李四" });//传入一个参数
    console.log(this.name); //李四
  },
  methods: {
    ...mapMutations(["changeAaa", "chagName"]),
  },
};
</script>

注意一条重要的原则就是要记住 mutation 必须是同步函数

4.actions

mutation必须是同步函数,在处理异步的时候,我们就需要用到actions。actions类似于mutation,不同在于:

  • Action 提交的是 mutation,而不是直接变更状态。
  • Action 可以包含任意异步操作。
const store = new Vuex.Store({
    state: {
        aaa: 11,
        name:'张三'
    },
    getters: {
        changeName(state){
            return `我叫${state.name}`
        },
        takeName(state,getters){
            return `${state.aaa}-${getters.changeName}`
        }
    },
    mutations:{
        changeAaa(state){
            state.aaa++
        },
        chagName(state,payload){
            state.name = payload.newName
        }
    },
    actions:{
        makeAction(context){
            setTimeout(() => {
                context.commit('changeAaa')
            }, 1000);
        }
    }
})

在上面代码中我们用个计数器来进行异步操作,因为Action不能去操作状态,vuex中只有mutation可以去改变状态,所以我们需要去用mutation方法,这里的action会接收一个参数context,通过context.commit('mutation里面的方法')来异步操作mutilation改变状态。

<template>
  <div>
    <button @click="look">查看</button>
  </div>
</template>

<script>
import { mapMutations, mapState, mapGetters } from "vuex";
export default {
  computed: {
    ...mapState(["name", "aaa"]),
    ...mapGetters(["changeName", "takeName"]),
  },
  mounted() {
    // console.log(this.aaa, 999); //11
    // this.$store.commit('changeAaa');
    // console.log(this.aaa, 888); //12

    // console.log(this.name, 12); //张三
    // this.chagName({ newName: "李四" });
    // console.log(this.name, 23); //李四
        
       console.log(this.aaa,'没触发action的state的aaa的值')
       this.$store.dispatch("makeAction");
  },
  methods: {
    ...mapMutations(["changeAaa", "chagName"]),
    look() {
      console.log(this.aaa, '触发action的state的aaa改变的值');
    },
  },
};
</script>

action通过this.$store.dispatch方法触发,在mouted里触发方法,异步计数器一秒后提交mutation改变状态。

 2.mapActions辅助函数

mapActions和mapMutations一样都是解析到methods中,

const store = new Vuex.Store({
    state: {
        aaa: 11,
        name:'张三'
    },
    getters: {
        changeName(state){
            return `我叫${state.name}`
        },
        takeName(state,getters){
            return `${state.aaa}-${getters.changeName}`
        }
    },
    mutations:{
        changeAaa(state){
            state.aaa++
        },
        chagName(state,payload){
            state.name = payload.newName
        },
        actionsAaa(state,n){
            state.aaa +=n
        }
    },
    actions:{
        makeAction(context){
            setTimeout(() => {
                context.commit('changeAaa')
            }, 1000);
        },
        takeAcion(context,n){
            setTimeout(() => {
                context.commit('actionsAaa',n)
            }, 1000);
        }
    }
})

在actions中新加一个takeAcion并传入一个参数n,将这个参数n再传给mutations给actionsAaa,再引入mapActions,解析到methods中,和前面的类似。

<template>
  <div>
    <button @click="look">查看</button>
  </div>
</template>

<script>
import { mapMutations, mapState, mapGetters, mapActions } from "vuex";
export default {
  computed: {
    ...mapState(["name", "aaa"]),
    ...mapGetters(["changeName", "takeName"]),
  },
  mounted() {
    console.log(this.aaa, "没触发action的state的aaa的值");
    this.takeAcion(6);
  },
  methods: {
    ...mapMutations(["changeAaa", "chagName"]),
    ...mapActions(["makeAction", "takeAcion"]),
    look() {
      console.log(this.aaa, "触发action的state的aaa改变的值");
    },
  },
};
</script>

给解析的takeAcion传入一个参数,异步改变state的aaa的值。

 5.Modules

 官网的解释。当项目大起来,vuex中的东西很多时,通过module来进行模块的分割十分的有必要的。首先我们在父模块中引入一个子模块modulesA,并在store文件夹下创建一个modulesA文件,

import Vue from 'vue'
import Vuex from 'vuex'
import modulesA from "./modulesA/index";

Vue.use(Vuex)
const store = new Vuex.Store({
    state: {
        aaa: 11,
        name: '张三'
    },
    getters: {
    },
    mutations: {
    },
    actions: {
    },
    modules: {
        modulesA
    }
})

export default store

在modulesA文件夹下创建一个index.js文件,

export default {
    namespaced:true,//命名空间的模块
    state: {
        bbb:'模块A的东西'
    },
    getters: {
        bbbGetters(state){
            return `模块B${state.bbb}`
        }
    },
    mutations: {
        bbbMutations(state,n){
            state.bbb = n
        }
    },
    actions: {
        bbbAcions(context,n){
            setTimeout(() => {
                context.commit('bbbMutations',n)
            }, 1000);
        }
    },
    modules:{ //可以继续嵌套命名空间
    }
}

 当然我们也可以将父模块和子模块的state,getters,mutations,actions抽离成单独的文件出来,这里就不做处理了。在页面获取子模块的state的状态值。

<script>
import { mapState } from "vuex";
export default {
  computed: {
     ...mapState({
        bbb:state=>state.modulesA.bbb
    })
  },
  mounted() {
     console.log(this.$store.state.modulesA.bbb);
  },
};

通过$store.state.子模块.state和辅助函数来获取子模块里面的状态。

<script>
import { mapGetters } from "vuex";
export default {
  computed: {
    ...mapGetters({
      'bbbGetters':'modulesA/bbbGetters'
    })
  },
  mounted() {
    console.log(this.$store.getters['modulesA/bbbGetters']);
    console.log(this.bbbGetters);
  },
};
</script>

通过$store.getters['modulesA/bbbGetters']和辅助函数来获取子模块里面的状态。这里和之前都有所不同,辅助函数中需要指定为子模块的方法,而不是父模块的那种形式。

使用mutations时,可以使用

this.$store.commit('modulesA/bbbMutations')

来改变state的状态,这是不传参数的方式,如果只需给mutations传入参数即可

this.$store.commit('modulesA/bbbMutations',88)

当然还可以使用辅助函数mapMutations,

<script>
import { mapMutations } from "vuex";
export default {
  mounted() {
    this.bbbMutations(99)
  },
  methods: {
    ...mapMutations({
      'bbbMutations':'modulesA/bbbMutations'
    }),
  },
};
</script>

为异步时候的actions也是同理

<script>
import { mapActions } from "vuex";
export default {
  mounted() {
    this.$store.dispatch('modulesA/bbbAcions',''参数)
    this.bbbAcions('参数')
  },
  methods: {
    ...mapActions({
      'bbbAcions':'modulesA/bbbAcions'
    }),
  },
};
</script>

使用 Vuex 并不意味着你需要将所有的状态放入 Vuex。虽然将所有的状态放到 Vuex 会使状态变化更显式和易调试,但也会使代码变得冗长和不直观。如果有些状态严格属于单个组件,最好还是作为组件的局部状态。你应该根据你的应用开发需要进行权衡和确定,所以对于组件之间的通信还是要掌握的。至此,vuex简单的概述完了,其中还有一些知识点啥的rootState,createNamespacedHelpers,subscribe,subscribeAction,模块重用等等没有涉及到,后续慢慢补充。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值