目錄
1.專案中vuex目錄的搭建
2.index.js
3.Mutation(mutation.js)
4.mutation-types.js
5.Getter(getter.js)
6 .Action(action.js)
7.module
8.持久化state的工具:vuex-persistedstate
首頁 web前端 js教程 使用vuex以及持久化

使用vuex以及持久化

Jun 09, 2018 pm 06:04 PM
state vuex

這篇文章主要介紹了vuex的使用及持久化state的方式詳解,現在分享給大家,也給大家做個參考。

Vuex 是一個專為 Vue.js 應用程式開發的狀態管理模式。它採用集中式儲存管理應用的所有元件的狀態,並以相應的規則保證狀態以一種可預測的方式變更。

當我們接觸vuex的時候,這是我們最先看到的一句官方引導。

從這句話中,我們可以得到以下幾個資訊:

1、vuex是一個為vue而存在的特化的Flux,如資料庫中的弱實體一樣,離開了vue,vuex就用不了。反之可以看到redux就不存在,無論是vue或react,redux都可以使用。所以這裡體現的vuex的“特性”,redux則具備“普適性”

2、集中式的管理說明vue中所有的組件的狀態都是存在於vuex中

3.使用vuex你就要遵循我的規則,這樣組件中狀態的變化我才能追蹤的到。

1.專案中vuex目錄的搭建

上圖是我在這篇文章中,vue整體專案骨架的局部。

vuex使用的是單一的狀態樹,我們的vue應用程式將只包含一個 store 的實例。所以當我們將store掛載到vue的實例上以後,我們可以透過this.$store取到vuex裡面的各個部分。

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這個檔案中,我們會去定義我們需要在vuex中儲存的狀態初始值。

比如說,我在上面的state物件中去儲存了一個isLoading屬性,該屬性我準備用它來標識我請求backend API的時候顯示,在請求完成後消失的這樣一個loading的效果,來緩解一下用戶的等待心理。

3.Mutation(mutation.js)

一般來說,我們在專案中最常用的就是mutation.js裡面的方法了。因為更改vuex中的store裡的state的唯一的方式就是提交mutation。

在vuex中,每個mutation都有一個字串的事件類型(mutation-type)和一個回呼函數(handler)。

這個回呼函數可接受兩個參數,第一個參數為state,第二參數是mutation的載重(payload)。

//...
mutations: {
 /**
 * @method:只传入state,修改loading状态
 * @param {bool} isLoading:loading状态
 */ 
 changeLoading(state) {
 state.isLoading = !state.isLoading
 }
}
store.commit('changeLoading')

mutations: {
 /**
 * @method:传入state和payload,修改loading状态
 * @param {bool} isLoading:loading状态
 */ 
 changeLoading(state,payload) {
 state.isLoading = payload.isLoading
 }
}
store.commit('changeLoading',{isLoading: true})
登入後複製

還有一種提交mutation的方式是直接使用包含 type 屬性的對象,不過我不是很推薦這樣的方式,因為用上面的方式來處理的話,程式碼的易讀性會更高。

store.commit({
 type: 'changeLoading',
 isLoading: true
})
登入後複製

4.mutation-types.js

在需要多人協作的專案中,我們可以使用常數來取代mutation 事件類型。這在各種 Flux 實作中是很常見的模式。同時把這些常數放在單獨的文件中可以讓協作開發變得清晰。

// 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
 },
}
登入後複製

對於定義mutation-type裡面的事件類型,我大致遵循我自己定義的如下規範:

1、因為mutation類似事件,所以以動詞開頭

2、單字間以下劃線進行連接

3、儲存到vuex裡面的狀態用RECORD標識

4、快取到本地的狀態用SAVE標識

 當然,這個規範的話大家可以自己定義,只要能透過mutation-type就能知道mutation的意圖就是極好的。

5.Getter(getter.js)

有時候我們需要從store 中的state 衍生出一些狀態,例如我上面提到的需要在非同步請求的時候去顯示一個有遮罩層的loading,然後我loading的下面需要依照state去展示loading的狀態。在不使用getter的情況下,我們會選擇使用計算屬性去處理。

computed: {
 loadingTxt () {
 return this.$store.state.isLoading ? '加载中' : '已完成';
 }
}
登入後複製

但是,我們這個loading需要在很多的元件中去使用它。那麼,我們要么複製這個函數,要么抽取到一個共享函數然後在多個地方導入它——無論哪種方式都不是很理想。

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

//getter.js
export default {
 loadingTxt:(state) =>{
  return state.isLoading ? '加载中' : '已完成';
 } 
};
登入後複製

就像計算屬性一樣,getter 的回傳值會根據它的依賴被快取起來,並且只有當它的依賴值發生了改變才會被重新計算。

並且,Getter 也可以接受其他getter 作為第二個參數:

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

透過mapGetters輔助函數可以將store 中的getter 對應到局部計算屬性

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

export default {
 data(){
 return {
  //...
 }
 },
 computed: {
 // 使用对象展开运算符将 getter 混入 computed 对象中
 ...mapGetters([
  'loadingTxt',
  'isLoading',
  // ...
 ])
 }
}
登入後複製

6 .Action(action.js)

action的功能和mutation是類似的,都是去變更store裡的state,不過action和mutation有兩點不同:

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

2、action改變狀態,最後是透過提交mutation

就拿購物車來說,當我們去添加一個商品的時候,我們需要先和後台去通訊一次,這裡涉及到sku或者說是如果用戶只添加了但是沒有去下單。

如果後台加入成功,前端再去展示新加入的商品,如果失敗,我們需要告訴使用者新增失敗了。

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

当我们的项目足够大的时候,单一的状态树这个时候就会显得很臃肿了。因为需要用vuex进行状态管理的状态全部集中在一个state对象里面。

所以,当一个东西大了以后,我们就要想办法进行分割,同样的道理,我们熟知的分冶法和分布式其实也是基于这样的一个思想在里面。而vuex提供了module,我们就可以去横向的分割我们的store。

比如说,我在项目中需要去做一个购物车这样的东西,这在电商的项目中也是常见的需求。

//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,会暴露到全局
 * @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,会暴露到全局
 * @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中,后三个都会暴露到全局的store中去,这样使得多个模块能够对同一 mutation 或 action 作出响应。就不需要在其他的模块中去定义相同的mutation或action了。

而这里的state是局部的。这也导致后来的持久化无法去处理用module分割后的state。

如同上面的module =》shopCart,

当我们无论是在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里面的定义的全部都是独享的。我们可以使用module的命名空间,通过设置namespaced: true。

//test.js
const getters = {
 // 在这个模块的 getter 中,`getters` 被局部化了
 // 你可以使用 getter 的第四个参数来调用 `rootGetters`
 someGetter (state, getters, rootState, rootGetters) {
 getters.someOtherGetter // 'test/someOtherGetter'
 rootGetters.someOtherGetter // 'someOtherGetter'
 },
 someOtherGetter: state => { ... }
};

const actions = {
 // 在这个模块中, 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的肯定会有这样一个痛点,就是刷新以后vuex里面存储的state就会被浏览器释放掉,因为我们的state都是存储在内存中的。

而像登录状态这样的东西,你不可能一刷新就让用户重新去登录吧!所以,我们会去选择把状态存储到本地。

这样一来问题貌似是解决了,但是当我们需要使用的时候,我们就需要不断的从本地,通过getStore这样的方法去取得我们state。如果需要更新的话,我们又要在mutation里面通过setStore这样的方法去处理它。

虽然,我们的setStore都是在操作了state以后再去调用的,也就是说无论是通过vuex的logger或者vue的dev tool我们都是可以对local里面的状态进行跟踪的,但是,我们无法保证我们每次都记着去写setStore。

这样一来,在共享state的组件中,我们的代码可能就会是这样的。

import { getStore } from '@/util'
//组件中
mounted(){
 this.foo = getStore('foo');
 this.bar = getStore('bar');
 //.... 
}
登入後複製

那么,如何去改进呢?

我们能想到的就是,能不能让state不是保存在内存中,而是存储在本地。

而vuex-persistedstate做了这样的事情,它帮我们将store里面的state映射到了本地环境中。这样一来,我通过提交mutation改变的state,会动态的去更新local里面对应的值。

上面是我整理给大家的,希望今后会对大家有帮助。

相关文章:

在bootstrap中如何实现table支持高度百分比

在vue 2.x 中使用axios如何封装的get 和post方法

使用node应用中timing-attack存在哪些安全漏洞

在vue组件传递对象中实现单向绑定,该怎么做?

以上是使用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脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

<🎜>:泡泡膠模擬器無窮大 - 如何獲取和使用皇家鑰匙
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系統,解釋
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
Mandragora:巫婆樹的耳語 - 如何解鎖抓鉤
3 週前 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)

熱門話題

Java教學
1665
14
CakePHP 教程
1424
52
Laravel 教程
1322
25
PHP教程
1270
29
C# 教程
1249
24
在Vue應用程式中使用vuex時出現「Error: [vuex] unknown action type: xxx」怎麼解決? 在Vue應用程式中使用vuex時出現「Error: [vuex] unknown action type: xxx」怎麼解決? Jun 25, 2023 pm 12:09 PM

在Vue.js專案中,vuex是一個非常有用的狀態管理工具。它可以幫助我們在多個元件之間共享狀態,並提供了一種可靠的方式來管理狀態的變化。但使用vuex時,有時會遇到「Error:[vuex]unknownact​​iontype:xxx」的錯誤。這篇文章將介紹該錯誤的原因及解決方法。 1.錯誤原因在使用vuex時,我們需要定義一些actions和mu

在Vue應用中使用vuex時出現「Error: [vuex] do not mutate vuex store state outside mutation handlers.」怎麼解決? 在Vue應用中使用vuex時出現「Error: [vuex] do not mutate vuex store state outside mutation handlers.」怎麼解決? Jun 24, 2023 pm 07:04 PM

在Vue應用程式中,使用vuex是常見的狀態管理方式。然而,在使用vuex時,我們有時可能會遇到這樣的錯誤提示:「Error:[vuex]donotmutatevuexstorestateoutsidemutationhandlers.」這個錯誤提示是什麼意思呢?為什麼會出現這個錯誤提示?如何解決這個錯誤?本文將詳細介紹這個問題。錯誤提示的含

Vue2.x中使用Vuex管理全域狀態的最佳實踐 Vue2.x中使用Vuex管理全域狀態的最佳實踐 Jun 09, 2023 pm 04:07 PM

Vue2.x是目前最受歡迎的前端框架之一,它提供了Vuex作為管理全域狀態的解決方案。使用Vuex能夠使得狀態管理更加清晰、易於維護,以下將介紹Vuex的最佳實踐,幫助開發者更好地使用Vuex以及提高程式碼品質。 1.使用模組化組織狀態Vuex使用單一狀態樹管理應用程式的全部狀態,將狀態從元件中抽離出來,使得狀態管理更加清晰易懂。在具有較多狀態的應用中,必須使用模組

在Vue應用程式中使用vuex時出現「TypeError: Cannot read property 'xxx' of undefined」怎麼解決? 在Vue應用程式中使用vuex時出現「TypeError: Cannot read property 'xxx' of undefined」怎麼解決? Aug 18, 2023 pm 09:24 PM

在Vue應用中使用Vuex是非常常見的操作。然而,偶爾在使用Vuex時會遇到錯誤訊息“TypeError:Cannotreadproperty'xxx'ofundefined”,這個錯誤訊息的意思是無法讀取undefined的屬性“xxx”,導致了程式的錯誤。這個問題其實產生的原因很明顯,就是因為在呼叫Vuex的某個屬性的時候,這個屬性沒有被正確

Vue3中Vuex怎麼使用 Vue3中Vuex怎麼使用 May 14, 2023 pm 08:28 PM

Vuex是做什麼的? Vue官方:狀態管理工具狀態管理是什麼?需要在多個元件中共享的狀態、且是響應式的、一個變,全都改變。例如一些全域要用的狀態資訊:使用者登入狀態、使用者名稱、地理位置資訊、購物車中商品、等等這時候我們就需要這麼一個工具來進行全域的狀態管理,Vuex就是這樣的一個工具。單一頁面的狀態管理View–>Actions—>State視圖層(view)觸發操作(action)變更狀態(state)回應回視圖層(view)vuex(Vue3.

深入了解vuex的實現原理 深入了解vuex的實現原理 Mar 20, 2023 pm 06:14 PM

當面試被問到vuex的實現原理,你要怎麼回答?以下這篇文章就來帶大家深入了解vuex的實作原理,希望對大家有幫助!

vue3+vite中如何使用vuex vue3+vite中如何使用vuex Jun 03, 2023 am 09:10 AM

具體步驟:1、安裝vuex(vue3建議4.0+)pnpmivuex-S2、main.js中設定importstorefrom'@/store'//hx-app的全域設定constapp=createApp(App)app.use(store)3、新建相關的資料夾與文件,這裡配置多個不同vuex內部的js,使用vuex的modules來放置不同的頁面,文件,然後統一使用一個getters.jsindex.js核心文件,這裡使用了import.meta.glob ,而不

聊聊兩個Vue狀態管理庫Pinia和Vuex,該用哪個? 聊聊兩個Vue狀態管理庫Pinia和Vuex,該用哪個? Feb 15, 2023 pm 03:08 PM

這篇文章帶大家聊聊Vue狀態管理,介紹一下兩個Vue狀態管理函式庫:Pinia和Vuex,希望對大家有幫助!

See all articles