vuex是什么?

vuex是专为vue应用程序开发的状态管理模式,你可以简单的将其看成是把多个组件需要共享的变量全部存储在一个对象里面,将这个对象放在顶层的vue实例中,让其他组件都可以使用,这样的话,我们是不是可以自己封装一个对象来管理呢?当然可以,但是vuejs给我们最大的便利就是响应式,如果我们自己封装一个对象可能稍微麻烦一些。

什么情况下使用vuex?

多个界面共享数据时使用,比如用户的登录状态,用户名称,头像等等,还有商品的收藏,购物车中的物品。

如何使用?

初级版(适合小白):

在src目录下新建一个文件夹store(仓库),在store文件夹下新建index.js:

1.index.js:

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

//1.安装插件
Vue.use(Vuex)

const state = {
  // 应用启动时,username 置为空
  username: ''
}

const mutations = {
  // mutation 的第一个参数是当前的 state
  // 你可以在函数里修改 state,第二个参数传过来的参数
   saveName(state, name){
     state.username = name;
   }
}

//2.创建对象
const store = new Vuex.Store({
  state,
  mutations
})

export default store;

这里的state是一些自定义的变量,需要共享出去的变量,组件不允许直接修改vuex store的状态,因为我们想要让状态的每次改变都很明确且可追踪,vuex状态的所有改变都必须在store的mutation中进行修改

这里的mutations是用来触发事件,用来修改state状态的,用户需要触发这个方法,借此来修改state里面的状态,传入的第二个参数就是要赋值给state中的变量

2.main.js中引用

import Store from './store'

Vue.prototype.$store = Store//挂载在vue原型上,这样组件就可以通过this.$store.state来访问

new Vue({
  el: '#app',
  Store,
  router,
  render: h => h(App)
})

3.保存数据:(当我点击登录时,我需要把用户名存储到vuex中)

login.vue

<template>
  <div>
    <button @click="login">登录</button>
    <!-- 这里方便查看 -->
    <h2>{{$store.state.username}}</h2>
  </div>
</template>

<script>
  export default {
      methods: {
         login(){
           this.$store.commit('saveName','huahua')
         }
      },
  }
</script>

效果:

这里的第一个参数就是要触发的方法名,第二个参数是你要传递的数据

获取变量名:this.$store.state.变量名

一般获取变量名都是在计算属性里面获取:

<template>
  <div>
    <h3>my name is {{name}}</h3>
  </div>
</template>

<script>
  export default {
    computed: {
      name() {
        return this.$store.state.username
      }
    },
  }
</script>

效果如下:

高级版(模块化,适合有基础的人,也适合中大型项目):

如果整个项目需要共享的数据之多,把这些数据和mutations写在一个文件夹的话,很难维护,耦合度高

先看这官方上的这张图,组件components派发任务到actions,actions再触发mutations中的方法,mutations再修改state中的数据,数据改变后响应推送给组件,组件渲染,所以上述中说到组件是不能直接修改state中的变量,并且state一定是通过mutations去修改的

Devtools是浏览器扩展程序插件,专门用来调试vue的,可以追踪vuex中state状态的改变,如果组件跳过mutations直接去修改state中的状态,那么就追踪不到:

actions是用于分发mutations函数,mutations只能进行同步操作,当想要执行异步操作时,请使用actions

文件夹目录:

推荐写法:

1.state.js:保存所有的数据,以对象的形式导出

//state.js
export default {
  username: "", //用户名
  token: "", //用户令牌
  role: "", //用户角色
  count: 10,
  info: {
    username: "kebi",
    age: 40,
    height: 1.95
  },
  students: [
    { id: 1, name: "zhangsan", age: 18 },
    { id: 2, name: "lisi", age: 20 },
    { id: 3, name: "xiaohua", age: 15 },
    { id: 4, name: "jinjin", age: 22 }
  ]
};
//mutations.js
export default {
  //第一个参数是store的state对象,第二个参数是传递过来的参数
  //名字使用全部大写,是为了和actions里面的方法名区分开
  SAVENAME(state, name) {
    state.username = name;
  }, //保存用户名

  SAVETOKEN(state, token) {
    state.token = token;
  }, //保存用户token

  SAVEROLE(state, role) {
    state.role = role;
  }, //保存用户角色

  UPDATEINFO(state, name) {
    state.info.username = name;
  }//异步修改用户信息
};
//actions.js
export default {
  //payload是传递过来的参数
  saveName(context, payload) {
    context.commit("SAVENAME", payload);
  }, //触发保存用户名方法
  //也可以这样写
  // {commit}是对象的解构,本来这个参数是context上下文,也就是store对象,打印这个对象,你就会知道里面有很多东西,其中就有commit这个东西
  // saveName({commit}, payload) {
  //   commit("SAVENAME", payload);
  // } //触发保存用户名方法

  saveToken(context, payload) {
    context.commit("SAVETOKEN", payload);
  }, //触发保存用户token方法

  saveRole(context, payload) {
    context.commit("SAVEROLE", payload);
  }, //触发保存用户角色方法
  
  //action里面可以进行异步操作
  aUpdateInfo(context, payload) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        context.commit("UPDATEINFO", payload);
        //这里告诉别人我已经做完了
        resolve("success");
      }, 1000);
    });
  }
};

actions.js里面进行异步操作,然后触发mutations里面的方法。

//main.js
import Vue from 'vue'
import App from './App'
import store from './store'

Vue.config.productionTip = false
Vue.prototype.$store = store
/* eslint-disable no-new */
new Vue({
  el: '#app',
  store,
  render: h => h(App)
})
//store中的index.js
import Vue from 'vue'
import Vuex from 'vuex'

import state from './state'
import mutations from './mutations'
import actions from './actions'

Vue.use(Vuex)

const store = new Vuex.Store({
  state,
  mutations,
  actions
})

export default store;

这样分模块写,index.js里面就简洁多了。

vuex里面的几个核心还有getters,modules,都可以这样写,为了方便管理

在组件里面使用:

<template>
  <div class="hello">
      <button @click="saveName">保存名字</button>
      <h2>展示名字:{{$store.state.username}}</h2>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  data () {
    return {
      
    }
  },
  methods: {
    saveName() {
         this.$store.dispatch('saveName', 'zhangsan')
     }
  },
}
</script>

actions是使用dispatch来分发任务,而mutations是使用commit来提交任务。

还可以这样使用:(这里会用到mapActions, mapState,还有mapMutations)

map就是映射嘛,拓展,把actions映射拓展到当前组件当中,这样就省去了$store....

<template>
  <div class="hello">
      <h2>展示名字:{{username}}</h2>
      <button @click="saveName('zhangsan')">保存名字</button>
  </div>
</template>

<script>
import {  mapActions, mapState, mapMutations } from 'vuex'
export default {
  name: 'HelloWorld',
  data () {
    return {
      
    }
  },
  computed: {
    ...mapState(['username'])//使用哪个就引入哪个,要映射到计算属性,以便响应式
  },
  methods: {
    ...mapActions(['saveName']),//使用哪个就引入哪个
  },
}
</script>

使用哪个就映射哪个,注意一点的就是使用mapActions映射的时候,传参是在调用的时候传参

效果:

点击保存名字:

总结:

vuex几个核心参数:

  1. state是一个对象,用于保存共享数据,只能供mutations去修改它,组件中可以使用$store.state.参数名来访问,也可以使用mapState映射到组件的计算属性中访问
  2. mutations是一个只能进行同步操作的对象,主要是去更改state,里面的方法第一个参数是state,第二个参数是传进来的参数,使用方法this.$store.commit('方法名',参数|按需传参),也可以使用mapMutations映射到组件方法中进行使用
  3. actions是一个可以进行异步操作的对象,可以触发mutations里面的方法,里面的方法第一个参数是context,第二个参数是payload传进来的参数,使用方法this.$store.dispatch('方法名',参数|按需传参),也可以使用mapActions映射到组件方法中进行使用
  4. getters是vuex里面的计算属性,是对state进行过滤处理进行使用,里面的方法第一个参数是state,第二个参数是getters,是它本身,使用方法$store.getters.方法名,也可以使用mapGetters映射到组件的计算属性里面进行使用
  5. modules是在当应用变得非常复杂时,store变得相当臃肿,modules是来把store分割成模块,而每个模块都拥有自己的state,mutations,actions,getters等

看过文章:

https://blog.csdn.net/qq_43363884/article/details/95948884###

https://blog.csdn.net/dkr380205984/article/details/82185740

https://github.com/vuejs/vuex/tree/1.0/docs/zh-cn

如以上有问题请留言,欢迎探讨

 

Logo

前往低代码交流专区

更多推荐