>  기사  >  웹 프론트엔드  >  이해하기 쉽다! VUEX 상태 창고 관리에 대한 자세한 설명

이해하기 쉽다! VUEX 상태 창고 관리에 대한 자세한 설명

藏色散人
藏色散人앞으로
2022-08-10 14:25:311676검색

Vuex는 Vue.js 애플리케이션용으로 특별히 개발된 상태 관리 패턴입니다. 중앙 집중식 저장소를 사용하여 애플리케이션의 모든 구성 요소 상태를 관리하고 해당 규칙을 사용하여 상태가 예측 가능한 방식으로 변경되도록 합니다. 간단히 말해서: 애플리케이션이 여러 구성요소 공유 상태를 발견하면 vuex를 사용하십시오.

Vue 핵심 개념:

State: 공유 상태, vuex의 기본 데이터로 변수를 저장하는 데 사용됩니다. 이는 구성 요소 데이터의 데이터와 동일하지만 이제는 전역 변수가 됩니다.

Getter: 상태를 기반으로 파생된 상태이며 구성 요소의 계산된 속성과 동일합니다.
  • Mutation: vuex에서 저장소의 공유 상태를 변경하는 방법입니다. 돌연변이를 제출하여 상태를 수정하고 데이터를 동기적으로 작동하는 방법은 일반적으로 비동기 데이터를 가져오는 작업, 커밋을 통해 돌연변이에 제출된 데이터를 가져오는 작업에 사용됩니다. 그리고 돌연변이에서 그 상태의 데이터를 동기적으로 작동시킵니다.
  • action: 요청에서 데이터를 비동기식으로 가져오는 데 사용할 수 있는 비동기 작업을 지원하고, 가져온 데이터를 동기식으로 mutation에 제출하여 데이터에 대한 ajax 비동기 요청을 구현하며, mutation은 해당 데이터를 상태에 동기화합니다.
  • 모듈: 모듈식 vuex는 나중에 프로젝트 관리를 용이하게 하기 위해 각 모듈에 고유한 상태, 돌연변이, 동작, 게터가 있어 구조가 매우 명확하고 관리하기 쉽습니다.
  • 장점과 단점은 무엇인가요?
  • 가장 큰 장점은 데이터와 방법을 전 세계적으로 공유할 수 있다는 것입니다. 통합 관리가 편리함
  • 단점: 상태 변수는 페이지 새로 고침 후 복원되고 지워지며, 쿠키처럼 영구적으로 저장되지 않습니다.

페이지 새로 고침 후 vuex 상태 데이터 손실 문제를 해결하는 방법은 무엇입니까?
먼저 왜 분실됐는지부터 이야기해볼까요?
스토어의 데이터는 실행 중인 메모리에 저장되기 때문에 페이지가 새로 고쳐지면 페이지가 vue 인스턴스를 다시 로드하고 스토어의 데이터가 다시 할당됩니다

이를 방지하는 방법은 무엇인가요?
실제로는 주로 사용 시나리오에 따라 다릅니다. 특정 데이터를 지속적으로 유지하려면 쿠키나 localStorage를 사용할 수도 있습니다. 예를 들어 일부 로그인 정보 등이 있습니다.
예를 들어 로그인 정보 획득을 요청한 후 먼저 localStorage에 저장하고, state에 있는 변수 값을 sessionStorage에 바인딩하고, mutation 수정 시 state와 localStorage를 동시에 수정할 수 있습니다. 마지막 페이지에서는 vuex의 변수를 직접 사용합니다. [관련 권장사항:

vue.js 비디오 튜토리얼

]

공식적으로

vuex
설치 입력 터미널을 열고 npm install vuex --save 명령줄을 입력하여 vuex

vuex 애플리케이션 코어 관리 웨어하우스 빌드 스토어 다운로드


여기에 새 저장소 폴더를 만들고 index.js라는 js를 만듭니다.

인덱스에서 상태, 변형, 작업 및 getter를 저장소에 도입하고 저장소 개체를 노출합니다.

다음은 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,})

스토어를 vue 인스턴스에 마운트합니다

main.js

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

상태 상태 관리 데이터


우리는 보통 관리해야 할 공유 데이터를 상태에 넣어서 상태를 만듭니다. 그것은 전역 변수처럼 보이며 필수 구성 요소에 상태 데이터를 도입합니다.

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

돌연변이는 동기적으로 데이터를 제출합니다

돌연변이는 상태의 상태 논리를 변경하고 상태의 상태 데이터를 동기적으로 변경하는 데 사용됩니다.

알아두셔야 할 점은 vuex의 mutation을 통해서만 상태 객체를 수정할 수 있다는 것입니다.

액션에서 얻은 데이터를 가져와서 상태를 수정할 수도 있고, 상태 데이터를 변경하기 위해 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 모듈을 호출하는 것을 볼 수 있습니다.
구성 요소에서 변이 모듈을 호출하는 코드는 다음과 같습니다.

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

액션의 비동기 작업


actions는 변이와 유사하지만 비동기 작업을 수행할 수 있고

비동기 작업으로 얻은 데이터를 변이에 제출합니다. 상태 데이터는 Ajax 요청에서 데이터를 얻는 데 자주 사용되며(비동기적이기 때문에), 얻은 데이터를 상태 데이터 상태를 업데이트하기 위해 돌연변이에 커밋합니다.

과 돌연변이의 차이점은 다음과 같습니다.

Action은 상태를 직접 변경하는 대신 돌연변이를 제출합니다.

Action에는 모든 비동기 작업이 포함될 수 있습니다.
  1. 예를 들어
  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);
            });
        });
      },}
구성 요소에서 이 작업의 호출 방법은 다음과 같습니다.
 this.$store.dispatch('user/login', postUser)
            .then(res => {
               // .............
              })// 我这里的login方法写在了user.js这个module里 所以这里调用是 user/login// 下面会讲到module

Getters 프로세스 상태

Getter는 계산된 속성과 동일하며 상태 데이터를 처리하는 데 사용되며 두 개의 기본 매개 변수가 있습니다. 첫 번째 기본값 매개변수는 상태이고 두 번째 기본 매개변수는 getter입니다.

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

구성 요소에서 이 메서드를 호출하기 위한 코드 조각은 다음과 같습니다. Vue 구성 요소에서

this.$store.getters.totalCount()

Get the Vuex status

에서 변경되면 반응형 업데이트를 위해 계산된 속성이 다시 검색됩니다.

 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

文件目录如图

이해하기 쉽다! 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

위 내용은 이해하기 쉽다! VUEX 상태 창고 관리에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 jianshu.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제