Maison  >  Article  >  interface Web  >  Facile à comprendre! Explication détaillée de la gestion des entrepôts d'état VUEX

Facile à comprendre! Explication détaillée de la gestion des entrepôts d'état VUEX

藏色散人
藏色散人avant
2022-08-10 14:25:311772parcourir

Vuex est un modèle de gestion d'état développé spécifiquement pour les applications Vue.js. Il utilise un stockage centralisé pour gérer l'état de tous les composants de l'application et utilise les règles correspondantes pour garantir que l'état change de manière prévisible. Pour faire simple : lorsque l'application rencontre plusieurs composants partageant l'état, utilisez vuex.

Concept Vue Core :

State : état partagé, les données de base de vuex, utilisées pour stocker les variables, ce qui est équivalent aux données des données du composant, mais maintenant elles deviennent une variable globale.

Getter : État dérivé basé sur l'état, équivalent aux propriétés calculées dans le composant.
  • Mutation : Une méthode pour changer l'état partagé du magasin dans vuex Modifier l'état en soumettant une mutation et exploiter les données de manière synchrone. Elle est généralement utilisée pour les actions visant à obtenir des données asynchrones, à obtenir des données soumises à la mutation via une validation, et exploitez les données dans l'état de manière synchrone dans la mutation.
  • action : prend en charge les opérations asynchrones, qui peuvent être utilisées pour obtenir de manière asynchrone les données dans la demande, et soumettre les données obtenues à la mutation de manière synchrone pour implémenter la demande de données asynchrone ajax, et la mutation synchronisera ses données avec l'état.
  • modules : Vuex modulaire, afin de faciliter la gestion de projet ultérieure, chaque module peut avoir son propre état, mutation, action, getters, rendant la structure très claire et facile à gérer.
  • Quels sont les avantages et les inconvénients ?
  • Le principal avantage est que les données et les méthodes peuvent être partagées à l'échelle mondiale. Pratique pour une gestion unifiée
  • Inconvénient : les variables d'état seront restaurées et effacées après l'actualisation de la page, et ne seront pas stockées de manière persistante comme les cookies

Comment résoudre le problème de perte de données d'état vuex après l'actualisation de la page ?
Tout d’abord, parlons de la raison pour laquelle il a été perdu ?
Étant donné que les données du magasin sont stockées dans la mémoire courante, lorsque la page est actualisée, la page rechargera l'instance de vue et les données du magasin seront réaffectées

Comment l'éviter ?
En fait, cela dépend principalement du scénario d'utilisation. Si vous souhaitez conserver certaines données de manière persistante, vous pouvez également utiliser des cookies ou localStorage. Par exemple, certaines informations de connexion, etc.
Par exemple, après avoir demandé les informations de connexion, vous pouvez d'abord les stocker dans localStorage, lier la valeur de la variable dans l'état à celle de sessionStorage et modifier l'état et localStorage en même temps lors de la modification des mutations. La dernière page utilise directement les variables dans vuex. [Recommandations associées :

tutoriel vidéo vue.js

]

Entrez officiellement dans l'installation de

vuex
Ouvrez le terminal, entrez la ligne de commande npm install vuex --save pour télécharger vuex

vuex application core management Warehouse build store


Créez un nouveau dossier de magasin ici, créez un js nommé index.js,

Dans l'index, introduisez l'état, les mutations, les actions et les getters dans le magasin et exposez l'objet du magasin.

Ce qui suit est le code d'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,})

Montez le magasin sur l'instance de vue

main.js

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

données de gestion de l'état de l'état


Nous mettons généralement les données partagées qui doivent être gérées dans l'état pour faire il Cela ressemble à une variable globale et introduit les données d'état aux composants requis.

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

mutations soumettent des données de manière synchrone

les mutations sont utilisées pour modifier la logique d'état dans l'état et modifier les données d'état dans l'état de manière synchrone.

Ce que vous devez savoir, c'est que l'objet d'état ne peut être modifié que par des mutations dans vuex.

Vous pouvez modifier l'état en obtenant les données obtenues à partir des actions, ou vous pouvez définir directement des méthodes dans le module mutations pour modifier les données d'état.

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;
  }};

A travers les modules mutations et actions ci-dessous, vous pouvez également voir que le commit est utilisé pour appeler le module mutation.
Le code pour appeler son module de mutation dans le composant est :

this.$store.commit('SET_TOKEN', token_data)

Le fonctionnement asynchrone des actions


les actions sont similaires à ses mutations, mais il peut effectuer des opérations asynchrones,

et soumettre les données obtenues par l'opération asynchrone aux mutations, pour que les mutations changent l'état. Les données d'état sont souvent utilisées pour obtenir les données dans la requête ajax (car elles sont asynchrones) et valider les données obtenues dans les mutations pour mettre à jour l'état des données d'état. La différence entre

et les mutations est la suivante :

L'action soumet une mutation au lieu de changer directement l'état.

Action peut contenir n’importe quelle opération asynchrone.
  1. Par exemple
  2. /* 下面就是通过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);
            });
        });
      },}
La méthode d'appel de cette action dans le composant est :
 this.$store.dispatch('user/login', postUser)
            .then(res => {
               // .............
              })// 我这里的login方法写在了user.js这个module里 所以这里调用是 user/login// 下面会讲到module

Getters Process state

Les getters sont équivalents aux propriétés calculées, utilisés pour traiter les données d'état, et ont deux paramètres par défaut, le premier par défaut Le paramètre est l'état et le deuxième paramètre par défaut est les getters.

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

L'extrait de code pour appeler cette méthode dans le composant est :

this.$store.getters.totalCount()

Obtenir le statut Vuex

dans le composant Vue Lorsqu'il change de

, les propriétés calculées seront à nouveau récupérées pour des mises à jour réactives.

 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

文件目录如图

Facile à comprendre! Explication détaillée de la gestion des entrepôts détat VUEX

举例 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

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer