目錄
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
登入後複製

文件目录如图

簡單易懂!詳解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中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡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 無盡。

熱門文章

倉庫:如何復興隊友
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
2 週前 By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island冒險:如何獲得巨型種子
1 個月前 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中echarts怎麼用 vue中echarts怎麼用 May 09, 2024 pm 04:24 PM

在 Vue 中使用 ECharts 可讓應用程式輕鬆新增資料視覺化功能。具體步驟包括:安裝 ECharts 和 Vue ECharts 套件、引入 ECharts、建立圖表組件、配置選項、使用圖表組件、實現圖表與 Vue 資料的響應式、新增互動式功能,以及使用進階用法。

vue中的export default的作用 vue中的export default的作用 May 09, 2024 pm 06:48 PM

問題:Vue 中 export default 的作用是什麼?詳細描述:export default 定義元件的預設匯出。導入時,將自動導入組件。簡化導入流程,提高清晰度和防止衝突。常用於匯出單一元件、同時使用命名匯出和預設匯出以及註冊全域元件。

vue中map函數的用法 vue中map函數的用法 May 09, 2024 pm 06:54 PM

Vue.js map 函數是一個內建的高階函數,用於建立一個新數組,其中每個元素都是原始數組中的每個元素轉換後的結果。其語法為 map(callbackFn),其中 callbackFn 接收數組中的每個元素作為第一個參數,可選地接收索引作為第二個參數,並傳回一個值。 map 函數不會改變原始陣列。

vue中onmounted作用 vue中onmounted作用 May 09, 2024 pm 02:51 PM

onMounted 是 Vue 中的元件掛載生命週期鉤子,其作用是在元件掛載到 DOM 後執行初始化操作,例如取得 DOM 元素的參考、設定資料、傳送 HTTP 請求、註冊事件監聽器等。它在元件掛載時僅呼叫一次,如果需要在元件更新後或銷毀前執行操作,可以使用其他生命週期鉤子。

vue中export與export default區別 vue中export與export default區別 May 08, 2024 pm 05:27 PM

Vue.js 中導出模組的方式有兩種:export 和 export default。 export用於匯出命名實體,需要使用花括號;export default用於匯出預設實體,不需要花括號。匯入時,export匯出的實體需要使用其名稱,而export default匯出的實體可以隱含使用。建議對於需要多次匯入的模組使用export default,對於只匯出一次的模組使用export。

vue中的鉤子是什麼 vue中的鉤子是什麼 May 09, 2024 pm 06:33 PM

Vue 鉤子是可在特定事件或生命週期階段執行操作的回呼函數。它們包括生命週期鉤子(如 beforeCreate、mounted、beforeDestroy)、事件處理鉤子(如 click、input、keydown)和自訂鉤子。鉤子增強元件控制,回應元件生命週期,處理使用者互動並提高元件重複使用性。使用鉤子,定義鉤子函數、執行邏輯並傳回可選值即可。

vue中的事件修飾符可以用於哪些場景 vue中的事件修飾符可以用於哪些場景 May 09, 2024 pm 02:33 PM

Vue.js 事件修飾符用於新增特定行為,包括:阻止預設行為(.prevent)停止事件冒泡(.stop)一次性事件(.once)擷取事件(.capture)被動的事件監聽(.passive)自適應修飾符(.self)關鍵修飾符(.key)

vue中的onmounted對應react哪個生命週期 vue中的onmounted對應react哪個生命週期 May 09, 2024 pm 01:42 PM

Vue 中的 onMounted 對應於 React 中的 useEffect 生命週期方法,帶有空依賴項數組 [],在元件掛載到 DOM 後立即執行。

See all articles