成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

DIY 一個(gè) Vuex 持久化插件

Half / 1345人閱讀

摘要:接下來我們會從上述兩個(gè)功能點(diǎn)出發(fā),完成一個(gè)持久化插件。在我們的持久化插件中,就是在這個(gè)函數(shù)內(nèi)部對數(shù)據(jù)進(jìn)行持久化操作。而則整個(gè)被監(jiān)聽,所以任何對于的改動都會被持久化并能夠被恢復(fù)。

在做 Vue 相關(guān)項(xiàng)目的時(shí)候,總會遇到因?yàn)轫撁嫠⑿聦?dǎo)致 Store 內(nèi)容丟失的情況。復(fù)雜的項(xiàng)目往往涉及大量的狀態(tài)需要管理,如果僅因?yàn)橐淮嗡⑿戮托枰恐匦芦@取,代價(jià)也未免太大了。

那么我們能不能對這些狀態(tài)進(jìn)行本地的持久化呢?答案是可以的,社區(qū)里也提供了不少的解決方案,如 vuex-persistedstatevuex-localstorage 等插件,這些插件都提供了相對完善的功能。當(dāng)然除了直接使用第三方插件以外,我們自己來 DIY 一個(gè)也是非常容易的。

這個(gè)持久化插件主要有2個(gè)功能:

能夠選擇需要被持久化的數(shù)據(jù)。

能夠從本地讀取持久化數(shù)據(jù)并更新至 Store。

接下來我們會從上述兩個(gè)功能點(diǎn)出發(fā),完成一個(gè) Vuex 持久化插件。

Gist地址:https://gist.github.com/jrain...
在線體驗(yàn)地址:https://codepen.io/jrainlau/p...
一、學(xué)習(xí)寫一個(gè) Vuex 插件

引用 Vuex 官網(wǎng) 的例子:

Vuex 的 store 接受 plugins 選項(xiàng),這個(gè)選項(xiàng)暴露出每次 mutation 的鉤子。Vuex 插件就是一個(gè)函數(shù),它接收 store 作為唯一參數(shù):

const myPlugin = store => {
  // 當(dāng) store 初始化后調(diào)用
  store.subscribe((mutation, state) => {
    // 每次 mutation 之后調(diào)用
    // mutation 的格式為 { type, payload }
  })
}

然后像這樣使用:

const store = new Vuex.Store({
  // ...
  plugins: [myPlugin]
})

一切如此簡單,關(guān)鍵的一點(diǎn)就是在插件內(nèi)部通過 store.subscribe() 來監(jiān)聽 mutation。在我們的持久化插件中,就是在這個(gè)函數(shù)內(nèi)部對數(shù)據(jù)進(jìn)行持久化操作。

二、允許用戶選擇需要被持久化的數(shù)據(jù)

首選初始化一個(gè)插件的主體函數(shù):

const VuexLastingPlugin = function ({
  watch: "*",
  storageKey: "VuexLastingData"
}) {
  return store => {}
}

插件當(dāng)中的 watch 默認(rèn)為全選符號 *,允許傳入一個(gè)數(shù)組,數(shù)組的內(nèi)容為需要被持久化的數(shù)據(jù)的 key 值,如 ["key1", "key2"] 等。接著便可以去 store.subscribe() 里面對數(shù)據(jù)進(jìn)行持久化操作了。

const VuexLastingPlugin = function ({
  watch: "*"
}) {
  return store => {
    store.subscribe((mutation, state) => {
      let watchedDatas = {}
      // 如果為全選,則持久化整個(gè) state 
      // 否則將只持久化被列出的 state
      if (watch === "*") {
        watchedDatas = state
      } else {
        watch.forEach(key => {
          watchedDatas[key] = state[key]
        })
      }
      // 通過 localStorage 持久化
      localStorage && localStorage.setItem(storageKey, JSON.stringify(watchedDatas))
    })
  }
}

按照 Vuex 的規(guī)范,有且只有通過 mutation 才能夠修改 state,于是按照上面的步驟,我們便完成了對數(shù)據(jù)進(jìn)行實(shí)時(shí)持久化的工作。

這里也有一個(gè)小問題,就是寫入 watch 參數(shù)的數(shù)組元素必須是 state 當(dāng)中的最外層 key ,不支持形如 a.b.c 這樣的嵌套 key。這樣的功能顯然不夠完善,所以我們希望可以增加對嵌套 key 的支持。

新建一個(gè)工具函數(shù) getObjDeepValue()

function getObjDeepValue (obj, keysArr) {
  let val = obj
  keysArr.forEach(key => {
    val = val[key]
  })
  return val
}

該函數(shù)接收一個(gè)對象和一個(gè) key 值數(shù)組, 返回對應(yīng)的值,我們來驗(yàn)證一下:

var obj = {
  a: {
    name: "aaa",
    b: {
      name: "bbb",
      c: {
        name: "ccc"
      }
    }
  }
}

getObjDeepValue(obj, "a.b.c".split("."))

// => { name: "ccc" }

驗(yàn)證成功以后,便可以把這個(gè)工具函數(shù)也放進(jìn) store.subscribe() 里使用了:

    store.subscribe((mutation, state) => {
      let watchedDatas = {}
      if (watch === "*") {
        watchedDatas = state
      } else {
        watch.forEach(key => {
          // 形如 a.b.c 這樣的 key 會被保存為 deep_a.b.c 的形式
          if (data.split(".").length > 1) {
            watchedDatas[`deep_${key}`] = getObjDeepValue(state, key.split("."))
          } else {
            watchedDatas[key] = state[key]
          }
        })
      }
      
      localStorage && localStorage.setItem(storageKey, JSON.stringify(watchedDatas))
    })

經(jīng)過這一改造,通過 watch 寫入的 key 值將支持嵌套的形式,整個(gè)插件將會更加靈活。

三、從本地讀取持久化數(shù)據(jù)并更新至 Store

從上面的步驟我們已經(jīng)能夠靈活監(jiān)聽 store 里的數(shù)據(jù)并持久化它們了,接下來的工作就是完成如何在瀏覽器刷新之后去讀取本地持久化數(shù)據(jù),并把它們更新到 store。

為插件添加一個(gè)默認(rèn)為 true 的選項(xiàng) autoInit,作為是否自動讀取并更新 store 的開關(guān)。從功能上來說,刷新瀏覽器之后插件應(yīng)該自動讀取 localStorage 里面所保存的數(shù)據(jù),然后把它們更新到當(dāng)前的 store。關(guān)鍵的點(diǎn)就是如何把 deep_${key} 的值正確賦值到對應(yīng)的地方,所以我們需要再新建一個(gè)工具函數(shù) setObjDeepValue()

function setObjDeepValue (obj, keysArr, value) {
  let key = keysArr.shift()
  if (keysArr.length) {
    setObjDeepValue(obj[key], keysArr, value)
  } else {
    obj[key] = value
  }
}

該函數(shù)接收一個(gè)對象,一個(gè) key 值數(shù)組,和一個(gè) value ,設(shè)置對象對應(yīng) key 的值,我們來驗(yàn)證一下:

var obj = {
  a: {
    name: "aaa",
    b: {
      name: "bbb",
      c: {
        name: "ccc"
      }
    }
  }
}

setObjDeepValue(obj, ["a", "b", "c"], 12345)

/**
obj = {
  a: {
    name: "aaa",
    b: {
      name: "bbb",
      c: 12345
    }
  }
}
*/

有了這個(gè)工具方法,就可以正式操作 store 了。

    if (autoInit) {
      const localState = JSON.parse(storage && storage.getItem(storageKey))
      const storeState = store.state
      if (localState) {
        Object.keys(localState).forEach(key => {
          // 形如 deep_a.b.c 形式的值會被賦值到 state.a.b.c 中
          if (key.includes("deep_")) {
            let keysArr = key.replace("deep_", "").split(".")
            setObjDeepValue(storeState, keysArr, localState[key])
            delete localState[key]
          }
        })
        // 通過 Vuex 內(nèi)置的 store.replaceState 方法修改 store.state
        store.replaceState({ ...storeState, ...localState })
      }
    }

上面這段代碼會在頁面初始化的時(shí)候讀取 storage 的值,然后把形如 deep_a.b.c 的值提取并賦值到 store.state.a.b.c 當(dāng)中,最后通過 store.replaceState() 方法更新整個(gè) store.state 的值。這樣便完成了從本地讀取持久化數(shù)據(jù)并更新至 Store 的功能。

四、案例測試

我們可以寫一個(gè)案例,來測試下這個(gè)插件的運(yùn)行情況。

在線體驗(yàn):https://codepen.io/jrainlau/p...

App.vue



store.js
import Vue from "vue"
import Vuex from "vuex"
import VuexPlugin from "./vuexPlugin"

Vue.use(Vuex)

export default new Vuex.Store({
  plugins: [VuexPlugin({
    watch: ["a.b.c", "x"]
  })],
  state: {
    a: {
      name: "aaa",
      b: {
        name: "bbb",
        c: {
          name: "ccc"
        }
      }
    },
    x: {
      name: "xxx"
    }
  },
  mutations: {
    updateA (state, val) {
      state.a = val
    },
    updateX (state, val) {
      state.x = val
    }
  }
})

從案例可以看出,我們針對 state.a.b.c 和 state.x 進(jìn)行了數(shù)據(jù)持久化。在整個(gè) state.a 都被修改的情況下,僅僅只有 state.a.b.c 被存入了 localStorage ,數(shù)據(jù)恢復(fù)的時(shí)候也只修改了這個(gè)屬性。而 state.x 則整個(gè)被監(jiān)聽,所以任何對于 state.x 的改動都會被持久化并能夠被恢復(fù)。

尾聲

這個(gè) Vuex 插件僅在瀏覽器環(huán)境生效,未曾考慮到 SSR 的情況。有需要的同學(xué)可以在此基礎(chǔ)上進(jìn)行擴(kuò)展,就不再展開討論了。如果發(fā)現(xiàn)文章有任何錯(cuò)誤或不完善的地方,歡迎留言和我一同探討。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/109347.html

相關(guān)文章

  • Vuex久化插件-解決刷新數(shù)據(jù)消失的問題

    摘要:可以進(jìn)行全局的狀態(tài)管理,但刷新后刷新后數(shù)據(jù)會消失,這是我們不愿意看到的。怎么解決呢,我們可以結(jié)合本地存儲做到數(shù)據(jù)持久化,也可以通過插件。 vuex可以進(jìn)行全局的狀態(tài)管理,但刷新后刷新后數(shù)據(jù)會消失,這是我們不愿意看到的。怎么解決呢,我們可以結(jié)合本地存儲做到數(shù)據(jù)持久化,也可以通過插件-vuex-persistedstate。 歡迎來點(diǎn)點(diǎn)我的個(gè)人博客showImg(https://user-...

    adie 評論0 收藏0
  • vuex久化插件-解決瀏覽器刷新數(shù)據(jù)消失問題

    摘要:眾所周知,的一個(gè)全局狀態(tài)管理的插件,但是在瀏覽器刷新的時(shí)候,內(nèi)存中的會釋放,通常的解決辦法就是用本地存儲的方式保存數(shù)據(jù),然后再初始化的時(shí)候再賦值給,手動存再手動取會覺得很麻煩,這個(gè)時(shí)候就可以使用的插件插件地址歡迎插件原理有一個(gè)方法每次在 眾所周知,vuex的一個(gè)全局狀態(tài)管理的插件,但是在瀏覽器刷新的時(shí)候,內(nèi)存中的state會釋放,通常的解決辦法就是用本地存儲的方式保存數(shù)據(jù),然后再vue...

    walterrwu 評論0 收藏0
  • vue.js+socket.io打造一個(gè)好玩的新聞社區(qū)

    摘要:云新聞云新聞收藏的使用需要注意的地方提交的是,而不是直接的狀態(tài)變更可以包含任意異步操作。的使用利用實(shí)現(xiàn)了簡單的聊天功能,在同一個(gè)服務(wù)器下。 title: Socket.io+vue打造新聞社區(qū)date: 2017-06-12 20:19:05 tags: [vue.js,javascript,socket.io] vue2.0 + socket.io打造一個(gè)DIY新聞社區(qū)(web第一...

    xiguadada 評論0 收藏0
  • 深入學(xué)習(xí)Vuex

    摘要:深入學(xué)習(xí)作為配合使用的數(shù)據(jù)狀態(tài)管理庫,針對解決兄弟組件或多層級組件共享數(shù)據(jù)狀態(tài)的痛點(diǎn)問題來說,非常好用。至此,構(gòu)造函數(shù)部分已經(jīng)過了一遍了。 深入學(xué)習(xí)Vuex vuex作為配合vue使用的數(shù)據(jù)狀態(tài)管理庫,針對解決兄弟組件或多層級組件共享數(shù)據(jù)狀態(tài)的痛點(diǎn)問題來說,非常好用。本文以使用者的角度,結(jié)合源碼來學(xué)習(xí)vuex。其中也參考了許多前輩的文章,參見最后的Reference Vue加載Vuex...

    codercao 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<