Vue Getters和mapGetters的原理及使用示例詳解
在Vue.js的狀態(tài)管理中,Vuex是一個非常重要的工具,它幫助開發(fā)者集中管理應用的狀態(tài)。Vuex的核心概念包括state、mutations、actions、getters和modules。今天,我們要深入探討其中一個關鍵部分:getters,以及它的相關輔助函數(shù)mapGetters。通過詳細介紹getters的原理和實現(xiàn)過程,希望能幫助你更好地理解和使用它們。
什么是Vue Getters?
Vuex中的getters可以被視為store的計算屬性。就像Vue組件中的計算屬性一樣,getters的返回值會基于其依賴被緩存起來,且只有當它的依賴值發(fā)生變化時才會重新計算。這使得getters非常適合用于從store中的state派生出一些狀態(tài)。
基本使用
首先,讓我們看一個簡單的例子:
const store = new Vuex.Store({
state: {
todos: [
{ id: 1, text: 'Learn Vue', done: true },
{ id: 2, text: 'Learn Vuex', done: false }
]
},
getters: {
doneTodos: state => {
return state.todos.filter(todo => todo.done)
},
doneTodosCount: (state, getters) => {
return getters.doneTodos.length
}
}
})在上面的代碼中,我們定義了一個doneTodos的getter,它會返回所有已完成的任務。同時,我們還定義了一個doneTodosCount的getter,它依賴于doneTodos,返回已完成任務的數(shù)量。
訪問Getters
你可以通過store.getters來訪問getters:
store.getters.doneTodos // -> [{ id: 1, text: 'Learn Vue', done: true }]
store.getters.doneTodosCount // -> 1在組件中使用Getters
在Vue組件中,你可以使用this.$store.getters來訪問getters:
computed: {
doneTodos () {
return this.$store.getters.doneTodos
}
}這雖然工作正常,但對于多個getters的訪問會顯得有些冗長。為了解決這個問題,我們可以使用mapGetters輔助函數(shù)。
使用mapGetters
mapGetters是一個輔助函數(shù),它可以幫助我們將store中的getter映射到局部計算屬性。它可以極大地簡化在組件中使用getters的代碼量。
基本使用
首先,我們需要在組件中導入mapGetters:
import { mapGetters } from 'vuex'
export default {
computed: {
...mapGetters([
'doneTodos',
'doneTodosCount'
])
}
}現(xiàn)在,我們可以直接在模板中使用這些計算屬性:
<template>
<div>
<p>Done Todos: {{ doneTodos }}</p>
<p>Done Todos Count: {{ doneTodosCount }}</p>
</div>
</template>別名
有時候,我們可能想要為映射的計算屬性指定別名。這時可以使用對象形式的參數(shù):
computed: {
...mapGetters({
completedTasks: 'doneTodos',
completedTasksCount: 'doneTodosCount'
})
}這樣,我們就可以在模板中使用別名:
<template>
<div>
<p>Completed Tasks: {{ completedTasks }}</p>
<p>Completed Tasks Count: {{ completedTasksCount }}</p>
</div>
</template>Getters的原理和實現(xiàn)
為了更深入地理解getters的工作原理,我們需要了解Vuex的內(nèi)部實現(xiàn)。Vuex是基于Vue的響應系統(tǒng)構建的,因此getters的實現(xiàn)與Vue的計算屬性有很多相似之處。
創(chuàng)建Getters
當我們創(chuàng)建一個store時,Vuex會遍歷我們定義的所有getters,并為每一個getter創(chuàng)建一個計算屬性。這些計算屬性的結果會被緩存,只有當它們的依賴(即state或者其他getters)發(fā)生變化時才會重新計算。
class Store {
constructor (options = {}) {
// ...
const store = this
const { getters } = options
this.getters = {}
Object.keys(getters).forEach(key => {
const fn = getters[key]
Object.defineProperty(store.getters, key, {
get: () => fn(store.state, store.getters)
})
})
// ...
}
}在上面的代碼中,我們可以看到Vuex通過Object.defineProperty為每一個getter定義了一個屬性,這個屬性的getter函數(shù)會返回計算后的結果。
響應式系統(tǒng)
Vuex的state是響應式的,這意味著當我們改變state中的數(shù)據(jù)時,所有依賴于這些數(shù)據(jù)的getters都會自動更新。Vuex通過Vue的Vue.observable方法將state變成響應式對象。
const state = Vue.observable({
todos: [
{ id: 1, text: 'Learn Vue', done: true },
{ id: 2, text: 'Learn Vuex', done: false }
]
})這樣,當我們改變state中的todos時,所有依賴于todos的getters(例如doneTodos和doneTodosCount)都會自動重新計算,并觸發(fā)相關的視圖更新。
深入理解mapGetters
mapGetters是Vuex提供的一個非常有用的輔助函數(shù),它的實現(xiàn)也相對簡單。mapGetters的主要作用是將store中的getters映射到組件的計算屬性。
mapGetters的實現(xiàn)
我們來看看mapGetters的實現(xiàn):
export function mapGetters (getters) {
const res = {}
normalizeMap(getters).forEach(({ key, val }) => {
res[key] = function mappedGetter () {
return this.$store.getters[val]
}
})
return res
}在上面的代碼中,mapGetters首先通過normalizeMap函數(shù)將傳入的參數(shù)規(guī)范化為一個數(shù)組,然后遍歷這個數(shù)組,為每一個getter創(chuàng)建一個計算屬性。這些計算屬性的getter函數(shù)會返回this.$store.getters中的對應值。
使用normalizeMap
normalizeMap函數(shù)的作用是將傳入的參數(shù)(可以是數(shù)組或對象)規(guī)范化為一個標準的對象數(shù)組:
function normalizeMap (map) {
if (!isValidMap(map)) {
return []
}
return Array.isArray(map)
? map.map(key => ({ key, val: key }))
: Object.keys(map).map(key => ({ key, val: map[key] }))
}如果傳入的是一個數(shù)組,normalizeMap會將每一個數(shù)組元素轉化為一個對象,鍵和值相同;如果傳入的是一個對象,normalizeMap會將每一個鍵值對轉化為一個對象,鍵和值分別對應原對象的鍵和值。
Getters和mapGetters的實際應用
在實際項目中,getters和mapGetters可以幫助我們更好地組織和管理應用狀態(tài)。讓我們通過一個稍微復雜的例子來進一步理解它們的實際應用。
例子:Todo應用
假設我們在開發(fā)一個Todo應用,這個應用需要展示所有任務、已完成任務、未完成任務以及任務的數(shù)量。我們可以通過getters來實現(xiàn)這些功能。
首先,我們定義store的state和getters:
const store = new Vuex.Store({
state: {
todos: [
{ id: 1, text: 'Learn Vue', done: true },
{ id: 2, text: 'Learn Vuex', done: false },
{ id: 3, text: 'Build something awesome', done: false }
]
},
getters: {
allTodos: state => state.todos,
doneTodos: state => state.todos.filter(todo => todo.done),
undoneTodos: state => state.todos.filter(todo => !todo.done),
totalTodosCount: state => state.todos.length,
doneTodosCount: (state, getters) => getters.doneTodos.length,
undoneTodosCount: (state, getters) => getters.undoneTodos.length
}
})然后,在組件中使用這些getters:
import { mapGetters } from 'vuex'
export default {
computed: {
...mapGetters([
'allTodos',
'doneTodos',
'undoneTodos',
'totalTodosCount',
'doneTodosCount',
'undoneTodosCount'
])
}
}在模板中展示任務和統(tǒng)計信息:
<template>
<div>
<h1>Todo List</h1>
<p>Total Todos: {{ totalTodosCount }}</p>
<p>Done Todos: {{ doneTodosCount }}</p>
<p>Undone Todos: {{ undoneTodosCount }}</p>
<h2>All Todos</h2>
<ul>
<li v-for="todo in allTodos" :key="todo.id">{{ todo.text }}</li>
</ul>
<h2>Done Todos</h2>
<ul>
<li v-for="todo in doneTodos" :key="todo.id">{{ todo.text }}</li>
</ul>
<h2>Undone Todos</h2>
<ul>
<li v-for="todo in undoneTodos" :key="todo.id">{{ todo.text }}</li>
</ul>
</div>
</template>通過這種方式,我們可以清晰地展示所有任務、已完成任務和未完成任務,以及相關的統(tǒng)計信息。而且,這些數(shù)據(jù)都是通過getters從state派生出來的,當state中的任務列表發(fā)生變化時,視圖會自動更新。
優(yōu)化和最佳實踐
在實際開發(fā)中,除了正確使用getters和mapGetters,我們還可以采取一些優(yōu)化和最佳實踐來提升代碼的可維護性和性能。
避免不必要的計算
雖然getters的結果會被緩存,但在設計getters時仍然要注意避免不必要的計算。例如,如果一個getter依賴于另一個getter,我們應該盡量減少重復計算。
模塊化
對于大型應用,我們可以將store拆分成多個模塊,每個模塊都有自己的state、mutations、actions和getters。這樣可以使代碼更清晰,更易于管理。
const moduleA = {
state: () => ({
todos: []
}),
getters: {
doneTodos: state => state.todos.filter(todo => todo.done)
},
mutations: {
// ...
},
actions: {
// ...
}
}
const store = new Vuex.Store({
modules: {
a: moduleA
}
})在組件中使用模塊的getters:
computed: {
...mapGetters('a', [
'doneTodos'
])
}異步操作
雖然getters不應該包含異步操作,但我們可以在actions中進行異步操作,然后通過mutations更新state,從而觸發(fā)getters的重新計算。
const store = new Vuex.Store({
state: {
todos: []
},
getters: {
doneTodos: state => state.todos.filter(todo => todo.done)
},
mutations: {
setTodos (state, todos) {
state.todos = todos
}
},
actions: {
fetchTodos ({ commit }) {
// 假設我們有一個API調(diào)用來獲取todos
fetchTodosFromAPI().then(todos => {
commit('setTodos', todos)
})
}
}
})性能優(yōu)化
在高性能需求的應用中,我們可以利用Vuex的插件系統(tǒng)來優(yōu)化getters的性能。例如,我們可以編寫一個插件來對getters的結果進行緩存,從而避免頻繁的計算。
function createGettersCachePlugin () {
return store => {
const cache = {}
store.subscribe((mutation, state) => {
// 在每次mutation后清除緩存
Object.keys(cache).forEach(key => delete cache[key])
})
store._wrappedGetters = Object.keys(store._wrappedGetters).reduce((wrappedGetters, key) => {
const getter = store._wrappedGetters[key]
wrappedGetters[key] = (state, getters) => {
if (!cache[key]) {
cache[key] = getter(state, getters)
}
return cache[key]
}
return wrappedGetters
}, {})
}
}
const store = new Vuex.Store({
// ...
plugins: [createGettersCachePlugin()]
})這個插件在每次mutation后清除緩存,并對getters的結果進行緩存,從而減少不必要的計算。
總結
Vuex的getters和mapGetters是非常強大的工具,它們可以幫助我們從store中的state派生出新的狀態(tài),并在組件中方便地使用這些狀態(tài)。在實際開發(fā)中,我們可以通過合理使用getters和mapGetters,提高代碼的可維護性和性能。同時,我們還可以采用一些優(yōu)化和最佳實踐,使我們的應用更加健壯和高效。
希望通過本文的詳細介紹,你能夠對Vuex的getters和mapGetters有更深入的理解,并在實際項目中更好地應用它們。祝你在Vue.js的世界中編程愉快!
到此這篇關于Vue Getters和mapGetters的原理及使用示例詳解的文章就介紹到這了,更多相關Vue Getters和mapGetters使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
- Vue3使用Vuex之mapState與mapGetters詳解
- 記一次vuex的mapGetters無效原因及解決
- vuex中...mapstate和...mapgetters的區(qū)別及說明
- vue3.0使用mapState,mapGetters和mapActions的方式
- vuex 中輔助函數(shù)mapGetters的基本用法詳解
- vuex2中使用mapGetters/mapActions報錯的解決方法
- vuex中的 mapState,mapGetters,mapActions,mapMutations 的使用
- 詳解vuex中mapState,mapGetters,mapMutations,mapActions的作用
相關文章
vuejs在解析時出現(xiàn)閃爍的原因及防止閃爍的方法
這篇文章主要介紹了vuejs在解析時出現(xiàn)閃爍的原因及防止閃爍的方法,本文介紹的非常詳細,具有參考借鑒價值,感興趣的朋友一起看看吧2016-09-09
解決Vue + Echarts 使用markLine標線(precision精度問題)
這篇文章主要介紹了解決Vue + Echarts 使用markLine標線(precision精度問題),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-07-07
vue?perfect-scrollbar(特定框架里使用非該框架定制庫/插件)
這篇文章主要為大家介紹了vue?perfect-scrollbar在特定框架里使用一款并非為該框架定制的庫/插件如何實現(xiàn),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪<BR>2023-05-05
vue3.x?的shallowReactive?與?shallowRef?使用場景分析
在Vue3.x中,`shallowReactive`和`shallowRef`是用于創(chuàng)建淺層響應式數(shù)據(jù)的API,它們與`reactive`和`ref`類似,本文介紹vue3.x??shallowReactive?與?shallowRef的使用場景,感興趣的朋友一起看看吧2025-02-02

