欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Vuex模塊化與持久化深入講解

 更新時(shí)間:2023年01月06日 08:32:44   作者:路易斯·李  
在實(shí)際項(xiàng)目開發(fā)過程中,如果公共數(shù)據(jù)比較多我們會(huì)使用vuex做公共狀態(tài)管理,但是在對(duì)瀏覽器進(jìn)行刷新操作的時(shí)候,會(huì)導(dǎo)致vuex內(nèi)的數(shù)據(jù)丟失,這種情況有些時(shí)候是沒問題的,但是有的時(shí)候我們需要某些數(shù)據(jù)可以持久化的保存,這樣就需要做對(duì)應(yīng)的處理

概述

Vuex作為VUE狀態(tài)管理組件,能夠?qū)㈨?xiàng)目公共數(shù)據(jù)進(jìn)行統(tǒng)一管理。而且可以按照不同的業(yè)務(wù)功能將數(shù)據(jù)狀態(tài)分模塊管理。另外,對(duì)于網(wǎng)頁刷新導(dǎo)致Vuex狀態(tài)丟失的問題可以使用vuex-persistedstate插件配置將數(shù)據(jù)保存在localStorage或者sessionStorage中。

本文測(cè)試環(huán)境如下:

“vue”: “^2.2.37”,
“vue-router”: “^3.0.1”,
“vuex”: “^3.0”,
“vuex-persistedstate”: “^4.1.0”
“secure-ls”: “^1.2.6”,

Vuex的模塊化

首先是main.js文件中引用Vuex組件,引入./store/index.js作為store參數(shù),用于實(shí)例化VUE對(duì)象。

// main.js
import Vue from 'vue'
import store from "./store";
/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  store,
  components: { App },
  template: '<App/>'
})

其中./store/index.js文件是Vuex狀態(tài)實(shí)例,使用new Vuex.Store()進(jìn)行狀態(tài)實(shí)例化,并將根狀態(tài)的state,getters,mutations,actions添加到參數(shù),以及各個(gè)模塊添加到modules對(duì)象參數(shù)中。

import Vue from 'vue'
import Vuex from 'vuex'
import user from "./modules/user";
import room from "./modules/room"
// 使用Vuex組件
Vue.use(Vuex)
const state = () => ({})
const getters = {}
const mutations = {}
const actions = {}
// 實(shí)例化狀態(tài)對(duì)象
export default new Vuex.Store({
  state,  getters,  mutations,  actions,
  modules: {  // 將各個(gè)模塊放入modules屬性中
    user, room, chat
  }
})

以上./store/index.js文件中,有user,room,chat三個(gè)模塊,模塊之間大同小異,下面僅以user模塊進(jìn)行講解。其中

state數(shù)據(jù)狀態(tài)對(duì)象

state,作為數(shù)據(jù)狀態(tài)的存儲(chǔ),是一個(gè)匿名函數(shù)返回的對(duì)象,該對(duì)象中有一個(gè)curTheme主題字符串和一個(gè) curUser用戶對(duì)象。

// state: 用戶相關(guān)狀態(tài)
const state = () => ({
  curTheme: 'light',
  curUser: {
    id: '123456',
    name: '張三'
  },
})

getters計(jì)算屬性對(duì)象

getters,作為計(jì)算屬性,類似vue組件中的computed屬性。該對(duì)象中是一個(gè)個(gè)的方法函數(shù),該函數(shù)按照順序有(state, getters, rootState, rootGetters)四個(gè)參數(shù)。前兩個(gè)參數(shù)stategetters是本模塊中的數(shù)據(jù)狀態(tài)對(duì)象和計(jì)算屬性對(duì)象,可在方法中按照如下格式進(jìn)行引用。

curUserId中可以使用state.curUser來訪問當(dāng)前模塊中數(shù)據(jù)狀態(tài)對(duì)象中的curUser對(duì)象。

使用方法:state.curUserId

isCurUserId中返回的是一個(gè)函數(shù),該函數(shù)接收一個(gè)userId參數(shù),通過getters.curUserId可以訪問當(dāng)前計(jì)算屬性對(duì)象中的curUserId屬性。

使用方法:state.isCurUserId(userId)

getCurThemeByUserId中返回的是一個(gè)函數(shù),該函數(shù)接收一個(gè)userId參數(shù),通過getters.isCurUserId(userId)函數(shù)確認(rèn)是否是當(dāng)前用戶,并返回對(duì)應(yīng)主題。

使用方法:state.getCurThemeByUserId(userId)

const getters = {
  // 獲取當(dāng)前用戶ID 
  curUserId: (state, getters, rootState, rootGetters) => {
    return state.curUser ? state.curUser.id : undefined
  },
  // 比對(duì)userId是否是當(dāng)前用戶id
  isCurUserId: (state, getters, rootState, rootGetters) => {
  	return (userId) => {
	  return userId == getters.curUserId;
	}
  },
  // 根據(jù)userId獲取當(dāng)前主題
  getCurThemeByUserId: (state, getters, rootState, rootGetters) => {
  	return (userId) => {
	  if(getters.isCurUserId(userId)) return state.curTheme;
	  else return '';
	}
  }
}

后兩個(gè)參數(shù)rootStaterootGetters可以用來訪問根和其他模塊的數(shù)據(jù)狀態(tài)和計(jì)算屬性。比如下面是room模塊的getters屬性。

// room.js
const getters = {
  // 測(cè)試
  testRoom: (state, getters, rootState, rootGetters) => {
	// 獲取userid
	let curUserId = rootGetters['user/curUserId']
	// 根據(jù)userId獲取當(dāng)前主題
	let curTheme = rootGetters['user/getCurThemeByUserId'](curUserId)
	return 'test';
  }
}

actions異步請(qǐng)求對(duì)象

actions,內(nèi)部是一個(gè)個(gè)函數(shù),所有異步操作需要放到這里,且如果需要更改數(shù)據(jù)狀態(tài),則必須通過commit調(diào)用相應(yīng)的mutation。且需要注意該函數(shù)有兩個(gè)參數(shù)(context, payload),其中context是一個(gè)對(duì)象,包括了state,‘rootState’,‘commit’,‘dispatch’,‘getters’,'rootGetters’等參數(shù)。

需要注意的是,actions中的(context, payload)參數(shù)中context是對(duì)象,所以里面的參數(shù)可以是無須的。但是getters中的(state, getters, rootState, rootGetters) 是四個(gè)參數(shù),并且是有序的,千萬注意順序!??!

// actions,異步操作,通過mutation進(jìn)行更新數(shù)據(jù)
const actions = {
  //context:{
  //         state,   等同于store.$state,若在模塊中則為局部狀態(tài)
  //         rootState,   等同于store.$state,只存在模塊中
  //         commit,   等同于store.$commit
  //         dispatch,   等同于store.$dispatch
  //         getters   等同于store.$getters,若在模塊中為局部狀態(tài)
  //		 rootGetters 等同于store.$getters
  // }
  // 用戶登錄
  async login ({state, rootState, commit, dispatch, getters, rootGetters}, {name, passwd})  {
    // getters使用
    getters.curUserId				// 獲取當(dāng)前模塊中的curUserId計(jì)算屬性 
    rootGetters['user/curUserId']	// 獲取user模塊中的curUserId計(jì)算屬性
	// dispatch使用
    dispatch('logout') 		// 調(diào)用本模塊中的logout異步請(qǐng)求
    dispatch('room/getRoomByUserId', null, { root: true }) // 調(diào)用rooom模塊的getRoomByUserId異步請(qǐng)求
	// commit使用
    commit('SET_CUR_USER', null) // 調(diào)用本模塊mutation方法
    commit('room/SET_ROOM_LIST', null, { root: true }) // 調(diào)用room模塊mutation方法
  },
  // 登出
  async logout({commit}) {
    let res = await $api.logout()
    localStorage.removeItem("token");
    commit("SET_CUR_USER", null);
    // 關(guān)閉socket鏈接
    websocket.close();
    await $router.push("/")
  },

mutations數(shù)據(jù)同步對(duì)象

mutations,數(shù)據(jù)同步對(duì)象,內(nèi)部是一個(gè)個(gè)同步函數(shù),該函數(shù)中主要是為了修改state屬性。注意千萬不要在actions或者其他地方直接設(shè)置state數(shù)據(jù)狀態(tài),若要修改state狀態(tài),必須使用commit。因?yàn)橹挥性?code>mutations方法中修改才能觸發(fā)Vuex數(shù)據(jù)和視圖同步更新。

其他地方更新數(shù)據(jù),需要使用commit方法

commit('room/SET_ROOM_LIST', null)

另外,對(duì)象和數(shù)組類型修改時(shí)不能使用state.curUser = curUser這種方式。需要使用Vue.set()方法進(jìn)行修改,否則也不會(huì)觸發(fā)數(shù)據(jù)視圖的更新。

Vue.set(state, 'curUser', curUser)
Vue.set(state.curUser, 'name', '張三')
Vue.set(state.list, 0, "2");
// mutations,定義更新數(shù)據(jù)方法,同步操作
const mutations = {
  SET_CUR_THEME (state, curTheme) {
    state.curTheme = curTheme
  },
  SET_CUR_USER (state, curUser) {
    Vue.set(state, 'curUser', curUser)
  },
}

Vuex的使用方式

在自定義組件中使用

// RoomGaming.vue
import {mapActions, mapGetters, mapState, mapMutations} from "vuex";
export default {
  computed: {
    ...mapState('user', ['curUser']),
    ...mapState('room', ['roomVO']),
    ...mapGetters('room', ['seatCount', 'playerList', 'curPlayer', 'curPlayerStatus',
      'curPlayerCanAddSeat', 'curPlayerCanDelSeat', 'curPlayerIsOwner']),
  },
  methods: {
    ...mapActions('room', ['leaveRoom', 'playerReady', 'playerAddSeat', 'startGame']),
    ...mapMutations('room', [])
  },
}

在自定義js文件中引用

// ReceiveService.js
import $store from '../store'
const testFunction = (data) => {
  // mutations
  $store.commit("gamexstx/SET_CLOCKWISE", data.clockwise);
  $store.commit("gamexstx/SET_BOTTOM", data.bottom);
  $store.commit("gamexstx/SET_DEGREE", data.degree);
  $store.commit("gamexstx/SET_PLAYER_STATE", data.playerState);
  // getters
  let index = $store.getters['gamexstx/curDrawIndex']
  let code = $store.getters['gamexstx/getCardInGroup1ByIndex'](index);
  // actions
  await $store.dispatch('cardxstx/playDrawCardAnim', {code, target});
  // state
  if($store.state.gamexstx.degree > 0) return;
}

Vuex持久化配置

在main.js中添加plugins屬性,并設(shè)置keystorage屬性,key是鍵名,storage是存儲(chǔ)位置,可以是window.localStorage也可以是window.sessionStorage

// main.js
import createPersistedState from 'vuex-persistedstate'
export default new Vuex.Store({
  state,
  getters,
  mutations,
  actions,
  modules: {
    user, room, chat, gamexstx, cardxstx
  },
  plugins: [
    createPersistedState({
      key: 'vuex',
      storage: window.localStorage,
    })
  ]
})

因?yàn)閘ocalStorage不會(huì)隨著網(wǎng)頁刷新而丟失數(shù)據(jù),所以將Vuex數(shù)據(jù)狀態(tài)存儲(chǔ)在此解決刷新丟失數(shù)據(jù)的問題。如下圖,可以看到相應(yīng)的數(shù)據(jù)存儲(chǔ)。

另外,由于是明文存儲(chǔ),可能存在安全問題,可以使用以下插件對(duì)數(shù)據(jù)進(jìn)行加密存儲(chǔ)。

var ls = new SecureLS({
  encodingType: "aes",    //加密類型
  isCompression: false,   //是否壓縮
  encryptionSecret: "encryption",   //PBKDF2值  加密秘密
});
export default new Vuex.Store({
  state,
  getters,
  mutations,
  actions,
  modules: {
    user, room, chat, gamexstx, cardxstx
  },
  plugins: [
    createPersistedState({
      // 以下使用ls加密
      key: 'vuex',
      storage: {
        getItem: (key) => ls.get(key),
        setItem: (key, value) => ls.set(key, value),
        removeItem: (key) => ls.remove(key),
      }
    })
  ]
})

加密之后,控制臺(tái)顯示如下,可以看到vuex中內(nèi)容已加密。

main.js代碼

import Vue from 'vue'
import Vuex from 'vuex'
import user from "./modules/user";
import room from "./modules/room"
import chat from "./modules/chat"
import cardxstx from "./modules/cardxstx"
import gamexstx from "./modules/gamexstx";
import createPersistedState from 'vuex-persistedstate'
import SecureLS from "secure-ls";
import SystemConfig from "../consts/SystemConfig";
Vue.use(Vuex)
const state = () => ({})
const getters = {}
const mutations = {}
const actions = {}
var ls = new SecureLS({
  encodingType: "aes",    //加密類型
  isCompression: false,   //是否壓縮
  encryptionSecret: "encryption",   //PBKDF2值  加密秘密
});
localStorage.removeItem(SystemConfig.storageKey);
export default new Vuex.Store({
  state,
  getters,
  mutations,
  actions,
  modules: {
    user, room, chat, gamexstx, cardxstx
  },
  plugins: [
    createPersistedState({
      key: SystemConfig.storageKey,
      storage: window.localStorage,
      // 以下使用ls加密
      // key: SystemConfig.storageKey,
      // storage: {
      //   getItem: (key) => ls.get(key),
      //   setItem: (key, value) => ls.set(key, value),
      //   removeItem: (key) => ls.remove(key),
      // }
    })
  ]
})

modules/user.js代碼

// ./store/modules/user.js
import Vue from 'vue'
import $api from '../../api/inter'
import $router from "../../router";
import {Message} from "element-ui";
import websocket from "../../api/websocket";
import SystemConfig from "../../consts/SystemConfig";
// state: 用戶相關(guān)狀態(tài)
const state = () => ({
  curTheme: 'light',
  curUser: undefined,
})
// getters: 用戶相關(guān)計(jì)算屬性,類似vue組件中的computed
const getters = {
  // 
  curUserId: (state, getters, rootState, rootGetters) => {
    return state.curUser ? state.curUser.id : undefined
  },
  getUserNameById: (state, getters, rootState, rootGetters) => {
	return (userId) => {
	  if(state.curUser.id == userId) return state.curUser.name;
	  else return "無名氏" 
	}
  }
}
// actions,異步操作,通過mutation進(jìn)行更新數(shù)據(jù)
const actions = {
  //context:{
  //         state,   等同于store.$state,若在模塊中則為局部狀態(tài)
  //         rootState,   等同于store.$state,只存在模塊中
  //         commit,   等同于store.$commit
  //         dispatch,   等同于store.$dispatch
  //         getters   等同于store.$getters
  // }
  // 獲取用戶信息
  async getCurUser ({ state, commit }) {
    // dispatch('room/getRoomByUserId', value, { root: true })  // 調(diào)用另外模塊
    // 獲取登錄后存儲(chǔ)在localStorage中的token值
    let token = localStorage.getItem("token");
    // console.log("token=" + token)
    // 如果token為空則返回空
    if(token == undefined || token == null) {
      commit('SET_CUR_USER', null);
      // Message.warning("用戶token失效,將移除本地token");
      // 移除token
      localStorage.removeItem("token")
      // 關(guān)閉socket鏈接
      websocket.close();
      return;
    }
    try{
      // 將token傳到后臺(tái)獲取對(duì)應(yīng)用戶信息
      let res = await $api.getUserInfoByToken();
      if(200 != res.code) throw new Error(res.message);
      localStorage.removeItem(SystemConfig.storageKey); // 登陸成功后清空會(huì)話緩存
      // 獲取到用戶信息,設(shè)置到curUser狀態(tài)中
      commit('SET_CUR_USER', res.data);
      // 設(shè)置websocket
      websocket.connect(state.curUser.id)
    } catch(err) {
      // 會(huì)話失效后應(yīng)該清理本地緩存
      localStorage.removeItem("token");
      // 關(guān)閉socket鏈接
      websocket.close();
      return Promise.reject(err);
    }
  },
  // 游客登錄
  async loginAsNameless({ dispatch }) {
    try{
      let res = await $api.loginAsNameless()
      await dispatch('loginSuccess', res.data);
    } catch (err) {
      Message.error(err);
      return Promise.reject(err)
    }
  },
  // 用戶登錄
  async loginByUser({dispatch}, params) {
    try{
      let res = await $api.login(params)
      // console.log("用戶登錄返回:", res)
      await dispatch('loginSuccess', res.data);
    }catch (err) {
      Message.error(err)
      return Promise.reject(err)
    }
  },
  // 登錄之后的操作
  async loginSuccess({state, dispatch}, token) {
    // 設(shè)置本地緩存
    localStorage.token = token;
    // 獲取用戶信息
    await dispatch('getCurUser');
    // 如果獲取用戶信息成功,則打開websocket并進(jìn)入大廳
    if(state.curUser != null) {
      await $router.push({path: '/hall'})
    } else {
      $router.push({path: "/"})
    }
  },
  // 登出
  async logout({commit}) {
    let res = await $api.logout()
    localStorage.removeItem("token");
    commit("SET_CUR_USER", null);
    // 關(guān)閉socket鏈接
    websocket.close();
    await $router.push("/")
  },
  // 修改密碼
  async modifyPass({commit}, params) {
    try{
      await $api.modifyPass(params)
    } catch (err) {
      Message.error(err)
      return Promise.reject(err)
    }
  }
}
// mutations,定義更新數(shù)據(jù)方法,同步操作
//
const mutations = {
  SET_CUR_USER (state, curUser) {
    Vue.set(state, 'curUser', curUser)
  },
}
export default {
  namespaced: true,
  state,
  getters,
  mutations,
  actions
}

項(xiàng)目傳送門:https://github.com/louislee92/vue-module-persistedstate

到此這篇關(guān)于Vuex模塊化與持久化深入講解的文章就介紹到這了,更多相關(guān)Vuex模塊化與持久化內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • VUE中data配置項(xiàng)詳細(xì)解析

    VUE中data配置項(xiàng)詳細(xì)解析

    data屬性是Vue實(shí)例的數(shù)據(jù)對(duì)象,可以綁定的是對(duì)象或者是函數(shù),下面這篇文章主要給大家介紹了關(guān)于VUE中data配置項(xiàng)詳細(xì)解析的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-02-02
  • JS 實(shí)現(xiàn)獲取對(duì)象屬性個(gè)數(shù)的方法小結(jié)

    JS 實(shí)現(xiàn)獲取對(duì)象屬性個(gè)數(shù)的方法小結(jié)

    這篇文章主要介紹了JS 實(shí)現(xiàn)獲取對(duì)象屬性個(gè)數(shù)的方法,結(jié)合實(shí)例形式總結(jié)分析了JS 獲取對(duì)象屬性個(gè)數(shù)的三種常用方法,需要的朋友可以參考下
    2023-05-05
  • vue?element如何添加遮罩層

    vue?element如何添加遮罩層

    這篇文章主要介紹了vue?element如何添加遮罩層問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • VUE 配置vue-devtools調(diào)試工具及安裝方法

    VUE 配置vue-devtools調(diào)試工具及安裝方法

    vue-devtools是一款基于chrome瀏覽器的插件,用于vue應(yīng)用的調(diào)試,這款vue調(diào)試神器可以極大地提高我們的調(diào)試效率。幫助我們快速的調(diào)試開發(fā)vue應(yīng)用。這篇文章主要介紹了VUE 配置vue-devtools調(diào)試工具及安裝步驟 ,需要的朋友可以參考下
    2018-09-09
  • Vue props 單向數(shù)據(jù)流的實(shí)現(xiàn)

    Vue props 單向數(shù)據(jù)流的實(shí)現(xiàn)

    這篇文章主要介紹了Vue props 單向數(shù)據(jù)流的實(shí)現(xiàn),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-11-11
  • Vue中的插槽Slot技術(shù)詳解

    Vue中的插槽Slot技術(shù)詳解

    插槽(Slot)技術(shù)是一種用于組件化開發(fā)的重要技術(shù),允許我們?cè)诮M件中定義一些占位符,在Vue中,插槽的使用方式可以分為三種:默認(rèn)插槽、具名插槽和作用域插槽,下面我們就來看看這三種方式的具體使用吧
    2023-09-09
  • vue.js刪除列表中的一行

    vue.js刪除列表中的一行

    這篇文章給大家分享了vue.js刪除列表中的一行的實(shí)例操作以及代碼分享,有興趣的朋友參考下。
    2018-06-06
  • 詳細(xì)對(duì)比Ember.js和Vue.js

    詳細(xì)對(duì)比Ember.js和Vue.js

    這篇文章主要介紹了詳細(xì)對(duì)比Ember.js和Vue.js,對(duì)JS框架感興趣的同學(xué),可以參考下
    2021-05-05
  • vue3使用video.js播放m3u8格式視頻的操作指南

    vue3使用video.js播放m3u8格式視頻的操作指南

    有時(shí)候我們需要播放 m3u8 格式的視頻,或者實(shí)現(xiàn)視頻播放器更多定制化需求,HTML 的 video 元素?zé)o法實(shí)現(xiàn)這些需求,這時(shí)候可以考慮使用 Video.js,本文給大家介紹了vue3使用video.js播放m3u8格式視頻的操作指南,需要的朋友可以參考下
    2024-07-07
  • Vue 不定高展開動(dòng)效原理詳解

    Vue 不定高展開動(dòng)效原理詳解

    本文主要介紹了Vue不定高展開動(dòng)效原理詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-06-06

最新評(píng)論