首頁 > web前端 > Vue.js > 簡單易懂!詳解VUEX狀態倉庫管理

簡單易懂!詳解VUEX狀態倉庫管理

藏色散人
發布: 2022-08-10 14:25:31
轉載
1931 人瀏覽過

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的程式碼

1

2

3

4

5

6

7

8

9

/*

  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中

1

2

3

4

5

import store from './store'// ..........new Vue({

  el: '#app',

  router,

  store,   // ***

  render: h => h(App)})

登入後複製

state狀態管理資料

我們通常將需要進行管理的共享數據,放入state中,使其形似為全域變量,對於需要的元件進行引入該state狀態數據。

1

2

3

4

5

6

7

8

9

const state = {

  userId: '',

  token: '',

  name: '',

  avatar: '',

  introduction: '',

  roles: [],

  tenantId: 1,

  userInfo: null};

登入後複製

mutations 同步提交資料

mutations用於更改state中的狀態邏輯的,並且為同步更改state中的狀態資料。
要知道的是在vuex中只能透過mutation來去修改state對象,
可以透過取得actions取得的資料去修改state,也可以在mutations模組中直接定義方法來去更改狀態資料。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

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模組的程式碼為:

1

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

登入後複製

actions 的非同步操作

actions與其mutations類似,但其可以進行非同步操作,
且將非同步操作獲取的資料提交給mutations,使得mutations更改state中的狀態資料, 這裡常常用於獲取ajax請求中的資料(因為是異步),並將其獲取的資料commit提交給mutations 使得state資料狀態的更新。

和mutations 的不同之處在於:

  1. Action 提交的是 mutation,而不是直接變更狀態。
  2. Action 可以包含任意非同步操作。

範例

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

/* 下面就是通过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在元件中的呼叫方法就是:

1

2

3

4

this.$store.dispatch('user/login', postUser)

           .then(res => {

              // .............

             })// 我这里的login方法写在了user.js这个module里 所以这里调用是 user/login// 下面会讲到module

登入後複製

Getters 對state進行加工

Getters相當於computed計算屬性,用於加工處理state狀態數據,有其兩個預設參數,第一個預設參數為state,第二個預設參數為getters。

1

2

3

4

5

6

7

const getters={

  plusCount(state){

    return state.count + 1

  },

 //获取state中状态数据对象,和获取getters模块中plusCount数据

  totalCount(state,getters){

    return getters.plusCount + state.count  }}

登入後複製

在元件中呼叫方法的程式碼片段為:

1

this.$store.getters.totalCount()

登入後複製

在Vue元件中取得Vuex狀態

store實例中讀取狀態最簡單的方法就是在計算屬性中傳回某個狀態,由於Vuex的狀態儲存是響應式的,所以在這裡每當store.state.count變化的時候,都會重新求取計算屬性,進行響應式更新。

1

2

3

4

computed: {

       count: function(){

           return this.$store.state.count        }

   },

登入後複製

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

辅助函数 mapState 和 mapGetters

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

//首先我们需要先将辅助函数引入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代码如下

1

2

3

4

5

6

7

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

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使用

页面中调用就是

1

// 使用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
最新問題
javascript - vuex store.watch()是什麼意思
來自於 1970-01-01 08:00:00
0
0
0
javascript - 使用vuex提示讀不到state屬性?
來自於 1970-01-01 08:00:00
0
0
0
javascript - vuex 使用dispatch 提示not found?
來自於 1970-01-01 08:00:00
0
0
0
javascript - vuex 無法取得modules中的getters
來自於 1970-01-01 08:00:00
0
0
0
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板