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

vuex的使用及持久化state的方式詳解

 更新時(shí)間:2018年01月23日 09:09:37   作者:baby格魯特  
這篇文章主要介紹了vuex的使用及持久化state的方式詳解,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧

Vuex 是一個(gè)專為 Vue.js 應(yīng)用程序開發(fā)的狀態(tài)管理模式。它采用集中式存儲(chǔ)管理應(yīng)用的所有組件的狀態(tài),并以相應(yīng)的規(guī)則保證狀態(tài)以一種可預(yù)測(cè)的方式發(fā)生變化。

當(dāng)我們接觸vuex的時(shí)候,這是我們最先看到的一句官方引導(dǎo)。

從這句話中,我們可以得到如下幾個(gè)信息:

1、vuex是一個(gè)為vue而存在的特化的Flux,如同數(shù)據(jù)庫中的弱實(shí)體一樣,離開了vue,vuex就用不了。反之可以看到redux就不存在,無論是vue還是react,redux都可以使用。所以這里體現(xiàn)的vuex的“特性”,redux則具備“普適性”

2、集中式的管理說明vue中所有的組件的狀態(tài)都是存在于vuex中

3、使用vuex你就要遵循我的規(guī)則,這樣組件中狀態(tài)的變化我才能跟蹤的到。

1.項(xiàng)目中vuex目錄的搭建

上圖是我在這篇文章中,vue整體項(xiàng)目骨架的局部。

vuex使用的是單一的狀態(tài)樹,我們的vue應(yīng)用將僅僅包含一個(gè) store 的實(shí)例。所以當(dāng)我們將store掛載到vue的實(shí)例上以后,我們可以通過this.$store取到vuex里面的各個(gè)部分。

2.index.js

import vue from 'vue'
import vuex from 'vuex'
import mutations from './mutation'
import getters from './getter'

vue.use(vuex)

const state = {
 isLoading:false
}

export default new vuex.Store({
 state,
 getters,
 mutations
})

在index這個(gè)文件中,我們會(huì)去定義我們需要在vuex中存儲(chǔ)的狀態(tài)初始值。

比如說,我在上面的state對(duì)象中去存儲(chǔ)了一個(gè)isLoading屬性,該屬性我準(zhǔn)備用它來標(biāo)識(shí)我請(qǐng)求backend API的時(shí)候顯示,在請(qǐng)求完成后消失的這樣一個(gè)loading的效果,來緩解一下用戶的等待心理。

3.Mutation(mutation.js)

一般來說,我們?cè)陧?xiàng)目中最常用的就是mutation.js里面的方法了。因?yàn)楦膙uex中的store里的state的唯一的方式就是提交mutation。

在vuex中,每個(gè)mutation都有一個(gè)字符串的事件類型(mutation-type)和一個(gè)回調(diào)函數(shù)(handler)。

這個(gè)回調(diào)函數(shù)可接受兩個(gè)參數(shù),第一個(gè)參數(shù)為state,第二參數(shù)是mutation的載荷(payload)。

//...
mutations: {
 /**
 * @method:只傳入state,修改loading狀態(tài)
 * @param {bool} isLoading:loading狀態(tài)
 */ 
 changeLoading(state) {
 state.isLoading = !state.isLoading
 }
}
store.commit('changeLoading')

mutations: {
 /**
 * @method:傳入state和payload,修改loading狀態(tài)
 * @param {bool} isLoading:loading狀態(tài)
 */ 
 changeLoading(state,payload) {
 state.isLoading = payload.isLoading
 }
}
store.commit('changeLoading',{isLoading: true})

還有一種提交mutation的方式是直接使用包含 type 屬性的對(duì)象,不過我不是很推薦這樣的方式,因?yàn)橛蒙厦娴姆绞絹硖幚淼脑?,代碼的易讀性會(huì)更高。

store.commit({
 type: 'changeLoading',
 isLoading: true
})

4.mutation-types.js

在需要多人協(xié)作的項(xiàng)目中,我們可以使用常量代替mutation 事件類型。這在各種 Flux 實(shí)現(xiàn)中是很常見的模式。同時(shí)把這些常量放在單獨(dú)的文件中可以讓協(xié)作開發(fā)變得清晰。

// mutation-types.js
export const CHANGE_LOADING= 'CHANGE_LOADING'

// mutation.js
import { CHANGE_LOADING} from './mutation-types'

export default{
 [CHANGE_LOADING](state,payload){
  state.isLoading = payload.isLoading
 },
}

對(duì)于定義mutation-type里面的事件類型,我大致遵循我自己定義的如下規(guī)范:

1、因?yàn)閙utation類似于事件,所以以動(dòng)詞開頭

2、單詞間以下劃線進(jìn)行連接

3、保存到vuex里面的狀態(tài)用RECORD標(biāo)識(shí)

4、緩存到本地的狀態(tài)用SAVE標(biāo)識(shí)

 當(dāng)然,這個(gè)規(guī)范的話大家可以自己定義,只要能通過mutation-type就能知道m(xù)utation的意圖就是極好的。

5.Getter(getter.js)

有時(shí)候我們需要從 store 中的 state 中派生出一些狀態(tài),例如我上面提到的需要在異步請(qǐng)求的時(shí)候去顯示一個(gè)帶有遮罩層的loading,然后我loading的下面需要根據(jù)state去展示loading的狀態(tài)。在不使用getter的情況下,我們會(huì)選擇使用計(jì)算屬性去處理。

computed: {
 loadingTxt () {
 return this.$store.state.isLoading ? '加載中' : '已完成';
 }
}

但是,我們這個(gè)loading需要在很多的組件中去使用它。那么,我們要么復(fù)制這個(gè)函數(shù),要么抽取到一個(gè)共享函數(shù)然后在多處導(dǎo)入它——無論哪種方式都不是很理想。

如果使用Getter,那么一切都變得美好了。

//getter.js
export default {
 loadingTxt:(state) =>{
  return state.isLoading ? '加載中' : '已完成';
 } 
};

就像計(jì)算屬性一樣,getter 的返回值會(huì)根據(jù)它的依賴被緩存起來,且只有當(dāng)它的依賴值發(fā)生了改變才會(huì)被重新計(jì)算。

并且,Getter 也可以接受其他 getter 作為第二個(gè)參數(shù):

export default {
 loadingTxt:(state) =>{
  return state.isLoading ? '加載中' : '已完成';
 },
  isLoading:(state,getters) => {
  return 'string' === typeof getters.loadingTxt ? true : false;
 } 
};

通過mapGetters輔助函數(shù)可以將 store 中的 getter 映射到局部計(jì)算屬性

//組件中
import { mapGetters } from 'vuex'

export default {
 data(){
 return {
  //...
 }
 },
 computed: {
 // 使用對(duì)象展開運(yùn)算符將 getter 混入 computed 對(duì)象中
 ...mapGetters([
  'loadingTxt',
  'isLoading',
  // ...
 ])
 }
}

6.Action(action.js)

action的功能和mutation是類似的,都是去變更store里的state,不過action和mutation有兩點(diǎn)不同:

1、action主要處理的是異步的操作,mutation必須同步執(zhí)行,而action就不受這樣的限制,也就是說action中我們既可以處理同步,也可以處理異步的操作

2、action改變狀態(tài),最后是通過提交mutation

就拿購物車來說,當(dāng)我們?nèi)ヌ砑右粋€(gè)商品的時(shí)候,我們需要先和后臺(tái)去通訊一次,這里涉及到sku或者說是如果用戶只添加了但是沒有去下單。

如果后臺(tái)添加成功,前端再去展示新添加的商品,如果失敗,我們需要告訴用戶添加失敗了。

const actions = {
 checkout ({ 
   state,
      commit,
   //rootState 
      }, products) {
 const savedCartItems = [...state.added]
 commit(SET_CHECKOUT_STATUS, null)
 // 置空購物車
 commit(SET_CART_ITEMS, { items: [] })
 shop.buyProducts(
  products,
   //成功
  () => commit(SET_CHECKOUT_STATUS, 'successful'),
  //失敗
  () => {
  commit(SET_CHECKOUT_STATUS, 'failed')
  commit(SET_CART_ITEMS, { items: savedCartItems })
  }
 )
 }
}

7.module

當(dāng)我們的項(xiàng)目足夠大的時(shí)候,單一的狀態(tài)樹這個(gè)時(shí)候就會(huì)顯得很臃腫了。因?yàn)樾枰胿uex進(jìn)行狀態(tài)管理的狀態(tài)全部集中在一個(gè)state對(duì)象里面。

所以,當(dāng)一個(gè)東西大了以后,我們就要想辦法進(jìn)行分割,同樣的道理,我們熟知的分冶法和分布式其實(shí)也是基于這樣的一個(gè)思想在里面。而vuex提供了module,我們就可以去橫向的分割我們的store。

比如說,我在項(xiàng)目中需要去做一個(gè)購物車這樣的東西,這在電商的項(xiàng)目中也是常見的需求。

//shopCart.js
import shop from '../../api/shop'
import {
 ADD_TO_CART,
 SET_CART_ITEMS,
 SET_CHECKOUT_STATUS
} from '../mutation-types'

const state = {
 added: [],
 checkoutStatus: null
}

/**
 * module getters
 * @param {Object} state:模塊局部state
 * @param {Object} getters:模塊局部getters,會(huì)暴露到全局
 * @param {Object} rootState:全局(根)state
 */
const getters = {
 checkoutStatus: state => state.checkoutStatus,
 cartProducts: (state, getters, rootState) => {
 return state.added.map(({ id, quantity }) => {
  const product = rootState.products.all.find(product => product.id === id)
  return {
  title: product.title,
  price: product.price,
  quantity
  }
 })
 },
 cartTotalPrice: (state, getters) => {
 return getters.cartProducts.reduce((total, product) => {
  return total + product.price * product.quantity
 }, 0)
 }
}

/**
 * module actions
 * @param {Object} state:模塊局部state
 * @param {Object} getters:模塊局部getters,會(huì)暴露到全局
 * @param {Object} rootState:全局(根)state
 */
const actions = {
 checkout ({ 
   state,
      commit,
   //rootState 
      }, products) {
 const savedCartItems = [...state.added]
 commit(SET_CHECKOUT_STATUS, null)
 // 置空購物車
 commit(SET_CART_ITEMS, { items: [] })
 shop.buyProducts(
  products,
   //成功
  () => commit(SET_CHECKOUT_STATUS, 'successful'),
  //失敗
  () => {
  commit(SET_CHECKOUT_STATUS, 'failed')
  commit(SET_CART_ITEMS, { items: savedCartItems })
  }
 )
 }
}

/**
 * module mutations
 * @param {Object} state:模塊局部state
 * @param payload:mutation的載荷
 */
const mutations = {
 //用id去查找商品是否已存在,
 [ADD_TO_CART] (state, { id }) {
 state.checkoutStatus = null
 const record = state.added.find(product => product.id === id)
 if (!record) {
  state.added.push({
  id,
  quantity: 1
  })
 } else {
  record.quantity++
 }
 },
 [SET_CART_ITEMS] (state, { items }) {
 state.added = items
 },
 [SET_CHECKOUT_STATUS] (state, status) {
 state.checkoutStatus = status
 }
}

export default {
 state,
 getters,
 actions,
 mutations
}

在module的定義的局部state,getters,mutation,action中,后三個(gè)都會(huì)暴露到全局的store中去,這樣使得多個(gè)模塊能夠?qū)ν?mutation 或 action 作出響應(yīng)。就不需要在其他的模塊中去定義相同的mutation或action了。

而這里的state是局部的。這也導(dǎo)致后來的持久化無法去處理用module分割后的state。

如同上面的module =》shopCart,

當(dāng)我們無論是在index.js里面或者其他的module中,shopCart里面的getters或者action或者mutations,我們都可以去使用。

//test.js
const state = {
 isTest:false
};

const getters = {
 isTest :state => state.isTest,
 checkTestStatus:(state,getters) => {
 return getters.checkoutStatus;
 }
};

export default {
 state,
 getters,
}
//組件中
...mapGetters([
 'checkTestStatus'
])
//...
created(){
 this.checkTestStatus ;//null
}

如果說,我就想讓我的module里面的定義的全部都是獨(dú)享的。我們可以使用module的命名空間,通過設(shè)置namespaced: true。

//test.js
const getters = {
 // 在這個(gè)模塊的 getter 中,`getters` 被局部化了
 // 你可以使用 getter 的第四個(gè)參數(shù)來調(diào)用 `rootGetters`
 someGetter (state, getters, rootState, rootGetters) {
 getters.someOtherGetter // 'test/someOtherGetter'
 rootGetters.someOtherGetter // 'someOtherGetter'
 },
 someOtherGetter: state => { ... }
};

const actions = {
 // 在這個(gè)模塊中, dispatch 和 commit 也被局部化了
 // 他們可以接受 `root` 屬性以訪問根 dispatch 或 commit
 someAction ({ dispatch, commit, getters, rootGetters }) {
 getters.someGetter // 'test/someGetter'
 rootGetters.someGetter // 'someGetter'

 dispatch('someOtherAction') // 'test/someOtherAction'
 dispatch('someOtherAction', null, { root: true }) // 'someOtherAction'

 commit('someMutation') // 'test/someMutation'
 commit('someMutation', null, { root: true }) // 'someMutation'
 },
 someOtherAction ({ state,commit }, payload) { ... }
}

export default {
 namespaced: true,
 state,
 getters,
 actions,
 mutations
}

8.持久化state的工具:vuex-persistedstate

用過vuex的肯定會(huì)有這樣一個(gè)痛點(diǎn),就是刷新以后vuex里面存儲(chǔ)的state就會(huì)被瀏覽器釋放掉,因?yàn)槲覀兊膕tate都是存儲(chǔ)在內(nèi)存中的。

而像登錄狀態(tài)這樣的東西,你不可能一刷新就讓用戶重新去登錄吧!所以,我們會(huì)去選擇把狀態(tài)存儲(chǔ)到本地。

這樣一來問題貌似是解決了,但是當(dāng)我們需要使用的時(shí)候,我們就需要不斷的從本地,通過getStore這樣的方法去取得我們state。如果需要更新的話,我們又要在mutation里面通過setStore這樣的方法去處理它。

雖然,我們的setStore都是在操作了state以后再去調(diào)用的,也就是說無論是通過vuex的logger或者vue的dev tool我們都是可以對(duì)local里面的狀態(tài)進(jìn)行跟蹤的,但是,我們無法保證我們每次都記著去寫setStore。

這樣一來,在共享state的組件中,我們的代碼可能就會(huì)是這樣的。

import { getStore } from '@/util'
//組件中
mounted(){
 this.foo = getStore('foo');
 this.bar = getStore('bar');
 //.... 
}

那么,如何去改進(jìn)呢?

我們能想到的就是,能不能讓state不是保存在內(nèi)存中,而是存儲(chǔ)在本地。

而vuex-persistedstate做了這樣的事情,它幫我們將store里面的state映射到了本地環(huán)境中。這樣一來,我通過提交mutation改變的state,會(huì)動(dòng)態(tài)的去更新local里面對(duì)應(yīng)的值。

大家感興趣的話,可以戳這里,這里有個(gè)小dmeo

以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • vue+tsc+noEmit導(dǎo)致打包報(bào)TS類型錯(cuò)誤問題及解決方法

    vue+tsc+noEmit導(dǎo)致打包報(bào)TS類型錯(cuò)誤問題及解決方法

    當(dāng)我們新建vue3項(xiàng)目,package.json文件會(huì)自動(dòng)給我添加一些配置選項(xiàng),這寫選項(xiàng)基本沒有問題,但是在實(shí)際操作過程中,當(dāng)項(xiàng)目越來越復(fù)雜就會(huì)出現(xiàn)問題,本文給大家分享vue+tsc+noEmit導(dǎo)致打包報(bào)TS類型錯(cuò)誤問題及解決方法,感興趣的朋友一起看看吧
    2023-10-10
  • vue源碼解析之事件機(jī)制原理

    vue源碼解析之事件機(jī)制原理

    這篇文章主要介紹了vue源碼解析之事件機(jī)制原理,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-04-04
  • SpringBoot+Vue開發(fā)之Login校驗(yàn)規(guī)則、實(shí)現(xiàn)登錄和重置事件

    SpringBoot+Vue開發(fā)之Login校驗(yàn)規(guī)則、實(shí)現(xiàn)登錄和重置事件

    這篇文章主要介紹了SpringBoot+Vue開發(fā)之Login校驗(yàn)規(guī)則、實(shí)現(xiàn)登錄和重置事件,本文通過圖文實(shí)例相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-10-10
  • 使用el-table做成樹形結(jié)構(gòu)并解決數(shù)據(jù)驅(qū)動(dòng)視圖問題

    使用el-table做成樹形結(jié)構(gòu)并解決數(shù)據(jù)驅(qū)動(dòng)視圖問題

    這篇文章主要介紹了使用el-table做成樹形結(jié)構(gòu)并解決數(shù)據(jù)驅(qū)動(dòng)視圖問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • 使用Vue.js和MJML創(chuàng)建響應(yīng)式電子郵件

    使用Vue.js和MJML創(chuàng)建響應(yīng)式電子郵件

    這篇文章主要介紹了使用Vue.js和MJML創(chuàng)建響應(yīng)式電子郵件,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • 關(guān)于Vue中的計(jì)算屬性和監(jiān)聽屬性詳解

    關(guān)于Vue中的計(jì)算屬性和監(jiān)聽屬性詳解

    這篇文章主要介紹了關(guān)于Vue中的計(jì)算屬性和監(jiān)聽屬性詳解,Vue.js模板內(nèi)的表達(dá)式非常便利,但是設(shè)計(jì)它們的初衷是用于簡單運(yùn)算的,在模板內(nèi)放入過長的或復(fù)雜的邏輯時(shí),會(huì)讓模板過重且難以維護(hù),需要的朋友可以參考下
    2023-05-05
  • 一個(gè)Vue視頻媒體多段裁剪組件的實(shí)現(xiàn)示例

    一個(gè)Vue視頻媒體多段裁剪組件的實(shí)現(xiàn)示例

    這篇文章主要介紹了一個(gè)Vue媒體多段裁剪組件的實(shí)現(xiàn)示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-08-08
  • vue項(xiàng)目中main.js的用法

    vue項(xiàng)目中main.js的用法

    src/main.js是入口文件,主要作用是初始化vue實(shí)例并使用需要的插件, Vue.use()的作用就是讓它里面被注冊(cè)的組件能夠被全局使用,本文通過實(shí)例代碼介紹vue項(xiàng)目中main.js的用法,感興趣的朋友一起看看吧
    2023-10-10
  • Vue3實(shí)現(xiàn)clipboard復(fù)制的使用示例

    Vue3實(shí)現(xiàn)clipboard復(fù)制的使用示例

    在日常開發(fā)中,為用戶提供復(fù)制文本功能的需求比較常見,下面介紹一款vue3可用的插件,可以快速實(shí)現(xiàn)這個(gè)功能,感興趣的可以了解一下
    2023-11-11
  • vue如何獲取配置代理文件中的api地址值

    vue如何獲取配置代理文件中的api地址值

    這篇文章主要介紹了vue如何獲取配置代理文件中的api地址值,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-04-04

最新評(píng)論