目录
VueX 是一个专门为 Vue.js 应用设计的状态管理构架,统一管理和维护各个vue组件的可变化状态
vuex的五个核心概念:
正式进入使用
vuex应用核心管理仓库 构建store
state状态管理数据
mutations 同步提交数据
actions 的异步操作
Getters 对state进行加工
在Vue组件中获得Vuex状态
辅助函数 mapState 和 mapGetters
首页 web前端 Vue.js 通俗易懂!详解VUEX状态仓库管理

通俗易懂!详解VUEX状态仓库管理

Aug 10, 2022 pm 02:25 PM
vue vuex

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。简单来说就是:应用遇到多个组件共享状态时,使用vuex。

VueX 是一个专门为 Vue.js 应用设计的状态管理构架,统一管理和维护各个vue组件的可变化状态

场景:多个组件共享数据或者是跨组件传递数据时

vuex的五个核心概念:

  • State:共享状态,vuex的基本数据,用来存储变量,相当于组件data里的数据,只不过此时变成了全局变量。
  • Getter:基于state的派生状态,相当于组件中的computed中的属性。
  • Mutation:更改vuex中store共享状态的方法,通过提交mutation来去修改状态,进行同步操作数据,通常用于action获取异步数据,获取通过commit提交数据给mutation,在mutation同步操作state中的数据。
  • action:支持异步操作,可用于异步获取请求中的数据,并将获取的数据同步commit提交给mutation,实现ajax异步请求数据,mutation将其数据同步到state中。
  • modules:模块化vuex,为了方便后期对于项目的管理,可以让每一个模块拥有自己的state、mutation、action、getters,使得结构非常清晰,方便管理。

优势和劣势有哪些?
优势主要就是可以全局共享数据,方法。方便统一管理
劣势的话,页面刷新后state的变量都会还原清空,不会像cookies一样持久性存储

页面刷新后vuex的state数据丢失怎么解决?
先说一下为什么会丢失呢?
因为store里的数据是保存在运行内存中的,当页面刷新时页面会重新加载vue实例,store里面的数据就会被重新赋值

如何避免?
其实主要还是看使用的场景是怎样的,如果想某些数据持久性保留也可以搭配使用cookies或者localStorage。比如一些登录的信息等。
比如请求拿到了登录信息后可以先存在localStorage,将state里的变量值和sessionStorage里面的绑定,mutations中修改的时候同时修改state和localStorage。最后页面直接使用vuex中的变量。【相关推荐:vue.js视频教程


正式进入使用

vuex的安装
打开终端,输入命令行npm install vuex --save进行下载vuex

vuex应用核心管理仓库 构建store

这里新建store文件夹,创建一个js取名为index.js,
在index里 ,通过将state,mutations,actions,getters引入到store中,并暴露出store对象。

下面为index.js的代码

/*
  vuex最核心的管理对象 store
*/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)//new 一个Vuex的对象,将state,mutation,action,getters配置到vuex的store中,方便管理数据export default new Vuex.Store({  
  state,
  mutations,
  actions,
  getters,})
登录后复制

挂载store到vue实例上
main.js中

import store from './store'// ..........new Vue({
  el: '#app',
  router,
  store,   // ***
  render: h => h(App)})
登录后复制

state状态管理数据

我们通常将需要进行管理的共享数据,放入state中,使其形似为全局变量,对于需要的组件进行引入该state状态数据。

const state = {
  userId: '',
  token: '',
  name: '',
  avatar: '',
  introduction: '',
  roles: [],
  tenantId: 1,
  userInfo: null};
登录后复制

mutations 同步提交数据

mutations用于更改state中的状态逻辑的,且为同步更改state中的状态数据。
需要知道的是在vuex中只能通过mutation来去修改state对象,
可以通过获取actions获取到的数据去修改state,也可以在mutations模块中直接定义方法来去更改状态数据。

const mutations = {
  SET_TOKEN: (state, token) => {
    state.token = token;
  },
  SET_USERID: (state, userId) => {
    state.userId = userId;
  },
  SET_NAME: (state, name) => {
    state.name = name;
  },
  SET_ROLES: (state, roles) => {
    state.roles = roles;
  },
  SET_TENANTID: (state, roles) => {
    state.tenantId = roles;
  },
  SET_USER_INFO: (state, userInfo) => {
    state.userInfo = userInfo;
  }};
登录后复制

通过mutations和下面的actions模块,大家也可以看出commit是用于调用mutation模块中的。
在组件中调用其mutation模块的代码为:

this.$store.commit('SET_TOKEN', token_data)
登录后复制

actions 的异步操作

actions与其mutations类似,但其可以进行异步操作,
且将异步操作获取的数据提交给mutations,使得mutations更改state中的状态数据, 这里常常用于获取ajax请求中的数据(因为是异步),并将其获取的数据commit提交给mutations 使得 state数据状态的更新。

和mutations 的不同之处在于:

  1. Action 提交的是 mutation,而不是直接变更状态。
  2. Action 可以包含任意异步操作。

举例

/* 下面就是通过actions执行异步Ajax请求,
得到数据后,
通过commit的方法调用mutations 从而更新数据
例如:  commit('SET_TOKEN', data.uuid);
*/const actions = {
  login({ commit }, userInfo) {  // 用户登录
    const params = userInfo;
    params.userName = userInfo.userName.trim()
    return new Promise((resolve, reject) => {
      getLogin(params)
        .then((response) => {
          const { status, message, data } = response || {};
          if (status === 200) {
            // 存入 参数: 1.调用的值 2.所要存入的数据
            commit('SET_USER_INFO', data);
            commit('SET_TOKEN', data.uuid);
            commit('SET_USERID', data.id);
            commit('SET_ROLES', data.roles);
            commit('SET_NAME', data.realName);
            commit('SET_TENANTID', data.tenantId || 1);
            setToken(data.uuid);
            db.save('userInfo', data);
            db.save('tenantId', data.tenantId || 1);
            localStorage.setItem('loginToken', data.uuid);
            resolve(data);
          } else {
            // ElementUI.Message.error(message);  // axios拦截统一提示了
          }
        })
        .catch((error) => {
          // ElementUI.Message.error(error.message); // axios拦截统一提示了
          reject(error);
        });
    });
  },}
登录后复制

这个actions在组件中的调用方法就是:

 this.$store.dispatch('user/login', postUser)
            .then(res => {
               // .............
              })// 我这里的login方法写在了user.js这个module里 所以这里调用是 user/login// 下面会讲到module
登录后复制

Getters 对state进行加工

Getters相当于computed计算属性,用于加工处理state状态数据,有其两个默认参数,第一个默认参数为state,第二个默认参数为getters。

const getters={
  plusCount(state){
    return state.count + 1
  },
 //获取state中状态数据对象,和获取getters模块中plusCount数据
  totalCount(state,getters){
    return getters.plusCount + state.count  }}
登录后复制

在组件中调用该方法的代码片段为:

this.$store.getters.totalCount()
登录后复制

在Vue组件中获得Vuex状态

store实例中读取状态最简单的方法就是在计算属性中返回某个状态,由于Vuex的状态存储是响应式的,所以在这里每当store.state.count变化的时候,都会重新求取计算属性,进行响应式更新。

 computed: {
        count: function(){
            return this.$store.state.count        }
    },
登录后复制

那么对于以上的store我们就简单介绍完了,相信大家看完后对于vuex会有一定的理解。那么这个时候我们要想,是不是使用this.$store.statethis.$store.getters.xxx感到麻烦呢?下面我们介绍另一种引入state和getters的方式

辅助函数 mapState 和 mapGetters

对于上述的在组件中引用state和getters的方法是不是感到麻烦呢?使用mapState你将会感受到便利。
组件中这样使用

//首先我们需要先将辅助函数引入import { mapGetters,mapState } from 'vuex'
 export default {
 computed: {

  // 使用对象展开运算符将 getter 混入 computed 对象中
  ...mapGetters( ['plusCount','totalCount'] )

 // 使用对象展开运算符将 state 混入 computed 对象中
    ...mapState( ['userInfo','count'] )

 },methods:{
    getData(){
        // 这里就能直接使用了  直接使用state 和getters里的数据
        //  this.userInfo 
        // this.plusCount
        
    }}}
登录后复制

Module子模块化管理

store文件夹下的index.js代码如下

import Vue from 'vue'import Vuex from 'vuex'import getters from './getters'Vue.use(Vuex)const modulesFiles = require.context('./modules', true, /\.js$/)const modules = modulesFiles.keys().reduce((modules, modulePath) => {
  const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1')
  const value = modulesFiles(modulePath)
  modules[moduleName] = value.default
  return modules}, {})const store = new Vuex.Store({
  modules,
  getters})export default store
登录后复制

文件目录如图

0c6dfca7c3329646836381c630d4f6b.jpg

举例 api.js

import { getKey, getLogin, logout, getInfo } from '@/api/user';import { setToken, removeToken } from '@/utils/auth';import db from '@/utils/localstorage';import router, { resetRouter } from '@/router';import ElementUI from 'element-ui';const state = {
  userId: '',
  token: '',
  name: '',
  avatar: '',
  introduction: '',
  roles: [],
  tenantId: 1,
  userInfo: null
  // roles: ['9999']};const mutations = {
  SET_TOKEN: (state, token) => {
    state.token = token;
  },
  SET_USERID: (state, userId) => {
    state.userId = userId;
  },
  SET_NAME: (state, name) => {
    state.name = name;
  },
  SET_ROLES: (state, roles) => {
    state.roles = roles;
  },
  SET_TENANTID: (state, roles) => {
    state.tenantId = roles;
  },
  SET_USER_INFO: (state, userInfo) => {
    state.userInfo = userInfo;
  }};const actions = {
  // 获取密钥
  getKey({ commit }) {
    return new Promise((resolve, reject) => {
      getKey()
        .then((response) => {
          resolve(response);
        })
        .catch((error) => {
          reject(error);
        });
    });
  },

  // 用户登录
  login({ commit }, userInfo) {
    // const { username, password } = userInfo;
    const params = userInfo;
    params.userName = userInfo.userName.trim()
    return new Promise((resolve, reject) => {
      // console.log(username, password);
      // setToken(state.token)
      // localStorage.setItem('loginToken', state.token)
      getLogin(params)
      // getLogin({ userName: username.trim(), password: password })
        .then((response) => {
          const { status, message, data } = response || {};
          if (status === 200) {
            // 存入 参数: 1.调用的值 2.所要存入的数据
            commit('SET_USER_INFO', data);
            commit('SET_TOKEN', data.uuid);
            commit('SET_USERID', data.id);
            commit('SET_ROLES', data.roles);
            commit('SET_NAME', data.realName);
            commit('SET_TENANTID', data.tenantId || 1);
            setToken(data.uuid);
            db.save('userInfo', data);
            db.save('tenantId', data.tenantId || 1);
            localStorage.setItem('loginToken', data.uuid);
            resolve(data);
          } else {
            // ElementUI.Message.error(message);  // axios拦截统一提示了
          }
        })
        .catch((error) => {
          // ElementUI.Message.error(error.message); // axios拦截统一提示了
          reject(error);
        });
    });
  },

  // 获取用户信息
  getInfo({ commit, state }) {
    return new Promise((resolve, reject) => {
      getInfo(state.token)
        .then((response) => {
          const { data } = response;
          data.roles = response.data.rights.map(String);
          if (!data) {
            reject('验证失败,请重新登录。');
          }
          const loginMessage = {
            memberId: data.id,
            userName: data.name,
            userTel: data.mobile,
            realName: data.realName,
            incorCom: data.incorCom,
            virtualCor: data.virtualCor,
            deptId: data.deptId,
            deptpath: data.deptpath,
            deptName: data.deptName          };
          localStorage.setItem('loginMessage', JSON.stringify(loginMessage));
          const { id, roles, realName } = data;
          // 角色必须是非空数组!
          if (!roles || roles.length <= 0) {
            reject('getInfo: 角色必须是非空数组!');
          }
          commit('SET_USERID', id);
          commit('SET_ROLES', roles);
          commit('SET_NAME', realName);
          localStorage.setItem('userRights', roles);
          // commit('SET_AVATAR', avatar)
          // commit('SET_INTRODUCTION', introduction)
          resolve(data);
        })
        .catch((error) => {
          reject(error);
        });
    });
  },

  // 用户登出
  logout({ commit, state }) {
    return new Promise((resolve, reject) => {
      logout(state.token)
        .then(() => {
          commit('SET_TOKEN', '');
          commit('SET_ROLES', []);
          db.remove('router');
          removeToken();
          resetRouter();
          resolve();
        })
        .catch((error) => {
          reject(error);
        });
    });
  },

  // 删除token
  resetToken({ commit }) {
    return new Promise((resolve) => {
      commit('SET_TOKEN', '');
      commit('SET_ROLES', []);
      removeToken();
      resolve();
    });
  },

  // 动态修改权限
  changeRoles({ commit, dispatch }, role) {
    return new Promise(async(resolve) => {
      const token = role + '-token';

      commit('SET_TOKEN', token);
      setToken(token);

      const { roles } = await dispatch('getInfo');
      console.log(roles, 'rolesrolesroles');
      resetRouter();

      // 根据角色生成可访问路由映射
      const accessRoutes = await dispatch('permission/generateRoutes', roles, {
        root: true
      });

      // 动态添加可访问路由
      router.addRoutes(accessRoutes);

      // 重置已访问视图和缓存视图
      dispatch('tagsView/delAllViews', null, { root: true });

      resolve();
    });
  }};export default {
  namespaced: true,
  state,
  mutations,
  actions};
登录后复制

这样后可以按功能分module使用

页面中调用就是

// 使用mutationsthis.$store.commit(&#39;api/SET_T&#39;, keys);// 使用actionsthis.$store.dispatch(&#39;user/login&#39;, postUser).then(res => {})// 如果没有分module // 那就是 this.$store.commit(&#39;SET_T&#39;, keys);// 直接调用方法
登录后复制

写完自己也感觉好简单噢(⊙-⊙)

不明白的童鞋在评论区留言咯 ヾ(•ω•`)o

以上是通俗易懂!详解VUEX状态仓库管理的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
2 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
2 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

为什么vue-router跳转后控制台网络中没有页面请求信息? 为什么vue-router跳转后控制台网络中没有页面请求信息? Apr 04, 2025 pm 05:27 PM

为什么vue-router跳转后控制台网络中没有页面请求信息?在使用vue-router进行页面跳转时,你可能会注意到一个现�...

如何在前端实现不同品牌高拍仪的拍照上传功能? 如何在前端实现不同品牌高拍仪的拍照上传功能? Apr 04, 2025 pm 05:42 PM

在前端如何实现不同品牌高拍仪的拍照上传功能在开发前端项目时,常常会遇到需要集成硬件设备的需求。对于...

如何使用Vue实现单表头和多表身的电子化报价表单? 如何使用Vue实现单表头和多表身的电子化报价表单? Apr 04, 2025 pm 11:39 PM

如何在Vue中实现单表头和多表身的电子化报价表单在现代化的企业管理中,报价表单的电子化处理是提高效率和...

在Vue2中如何使用el-table实现表格分组拖拽排序? 在Vue2中如何使用el-table实现表格分组拖拽排序? Apr 04, 2025 pm 07:54 PM

Vue2中实现el-table表格分组拖拽排序在Vue2中使用el-table表格实现分组拖拽排序是一个常见的需求。假设我们有一个...

如何实现带有45度曲线边框的分段器效果? 如何实现带有45度曲线边框的分段器效果? Apr 04, 2025 pm 11:48 PM

实现分段器效果的技巧在用户界面设计中,分段器是一种常见的导航元素,尤其是在移动应用和响应式网页中。...

JavaScript命名规范在Android WebView中是否会引发兼容性问题? JavaScript命名规范在Android WebView中是否会引发兼容性问题? Apr 04, 2025 pm 07:15 PM

JavaScript命名规范与Android...

如何在Vue中使用Mapbox和Three.js确保三维物体的底部固定在地图上? 如何在Vue中使用Mapbox和Three.js确保三维物体的底部固定在地图上? Apr 04, 2025 pm 06:42 PM

如何在Vue中使用Mapbox和Three.js实现三维物体与地图视角的适配在使用Vue结合Mapbox和Three.js时,创建的三维物体需�...

See all articles