🎬 岸邊的風:個人主頁
?🔥?個人專欄?:《 VUE 》?《 javaScript 》
???生活的理想,就是為了理想的生活?!
目錄
?📚 前言
📘 創建 Pinia
📘 Option Store
📘?Pinia 提供多種選項配置 Store:
🍍?state
🍍?getters
🍍?actions
🍍?persist
📘 使用 Store
🍍 讀取狀態
🍍調用 Actions
🍍 多個 Store
📘 Setup Store
📘 數據持久化
📘 Pinia 插件
📘 購物車示例
📘?Pinia 插件
📘 實現一個持久化插件
📚? 寫在最后
?📚 前言
?
Pinia,讓狀態管理再無難題!
作為Vue.js官方推薦的新星級管理庫,Pinia為開發者帶來前所未有的順滑體驗。你還在為復雜難懂的狀態管理代碼頭疼嗎?別急,用Pinia你可以告別一切煩惱!
本指南將為您還原Pinia的奧秘,您將掌握它獨特的簡潔API使用技巧,迅速成為狀態管理的專家級大師!無論您是新手還是老鳥,這里的專業指導將助您在項目中如虎添翼,以最輕松的姿態管理復雜應用狀態。
快來 Reshape Your State Management Skills吧!我們一起領略 Pinia的魅力!
📘 創建 Pinia
在 main.js 中導入 createPinia 并使用:
import?{?createApp?}?from?'vue'
import?{?createPinia?}?from?'pinia'const?pinia?=?createPinia()
const?app?=?createApp(App)app.use(pinia)
可以通過?app.config.globalProperties.$pinia
?訪問 Pinia 實例。
📘 Option Store
與 Vue 的選項式 API 類似,我們也可以傳入一個帶有?
state
、actions
?與?getters
?屬性的 Option 對象(廢棄了Mutations)
使用?defineStore
?API 定義 Store:
import?{?defineStore?}?from?'pinia'export?const?useMainStore?=?defineStore('main',?{//?statestate:?()?=>?{return?{counter:?0}},//?gettersgetters:?{doubleCount(state)?{return?state.counter?*?2}},//?actionsactions:?{increment()?{this.counter++?}}
})
接收唯一 ID 作為第一個參數
state、getters、actions 定義方式與 Vue 組件類似
可以直接通過?
this
?訪問狀態
📘?Pinia 提供多種選項配置 Store:
🍍?state
📟 定義響應式狀態:
state:?()?=>?{return?{count:?0}
}?
必須是一個返回狀態對象的函數。
🍍?getters
📟 定義 getter 計算屬性:
getters:?{double(state)?{return?state.count?*?2}
}
📟?getter 可以接收參數:
getters:?{getMessage(state)?{return?(name?=?'Vue')?=>?`Hello?${name}`?}
}
🍍?actions
📟 定義方法修改狀態:
actions:?{increment(amount?=?1)?{this.count?+=?amount}
}
📟?actions 支持同步和異步操作。
🍍?persist
📟 配置數據持久化,需要使用插件:
persist:?{enabled:?true,strategies:?[{key:?'my_store',storage:?localStorage,},]
}?
📘 使用 Store
📟 通過?useXxxStore()
?獲取 Store 實例:
import?{?useMainStore?}?from?'@/stores/main'export?default?{setup()?{const?main?=?useMainStore()main.increment()}?
}
📟 讀取狀態、調用 actions 同 Vue 組件。
🍍 讀取狀態
//?直接讀取
const?count?=?main.count//?通過計算屬性
const?double?=?computed(()?=>?main.doubleCount)//?通過?storeToRefs
const?{?count?}?=?storeToRefs(main)
🍍調用 Actions
main.increment()const?message?=?main.getMessage('Vue')
🍍 多個 Store
📟 可以拆分多個 Store 管理不同模塊狀態:
stores
|- user.js
|- product.js
📟 單獨導出每個 Store 并在組件中使用:
import?{?useUserStore?}?from?'@/stores/user'
import?{?useProductStore?}?from?'@/stores/product'?export?default?{setup()?{//?...}
}
📟?Store 可以互相引用:
//?userStore.js
import?{?useProductStore?}?from?'./product'export?const?useUserStore?=?defineStore({//?可以直接使用?productStore
})
📘 Setup Store
🍍 個人比較傾向這種語法
也存在另一種定義 store 的可用語法。與 Vue 組合式 API 的?setup 函數?相似,我們可以傳入一個函數,該函數定義了一些響應式屬性和方法,并且返回一個帶有我們想暴露出去的屬性和方法的對象。
export?const?useCounterStore?=?defineStore('counter',?()?=>?{const?count?=?ref(0)function?increment()?{count.value++}return?{?count,?increment?}
})
🍍 在?Setup Store?中:
ref()
?就是?state
?屬性
computed()
?就是?getters
function()
?就是?actions
Setup store 比?Option Store?帶來了更多的靈活性,因為你可以在一個 store 內創建偵聽器,并自由地使用任何組合式函數。不過,請記住,使用組合式函數會讓?SSR?變得更加復雜。
📘 數據持久化
📟?Pinia 默認狀態不持久化,可以通過插件實現持久化:
npm?install?pinia-plugin-persistedstate
import?persistedState?from?'pinia-plugin-persistedstate'const?pinia?=?createPinia()
pinia.use(persistedState)?
📟 在 Store 中配置?persist
:
export?const?useUserStore?=?defineStore({persist:?{enabled:?true}?
})?
📟 配置?storage
?指定存儲位置:
persist:?{storage:?sessionStorage
}
📘 Pinia 插件
Pinia 生態已有許多插件,可以擴展更多功能:
pinia-plugin-persistedstate
:數據持久化
pinia-plugin-debounce
:防抖修改狀態
pinia-plugin-pinia-observable
:轉換成 Observable
📟?使用插件:
import?piniaPluginPersist?from?'pinia-plugin-persist'pinia.use(piniaPluginPersist)
📟?Devtools
Pinia支持Vue devtools
📘 購物車示例
📟 我們來通過一個購物車的例子看看 Pinia 的用法:
//?store.js
import?{?defineStore?}?from?'pinia'export?const?useCartStore?=?defineStore('cart',?{state:?()?=>?{return?{items:?[]??}},getters:?{total(state)?{return?state.items.reduce((total,?item)?=>?{return?total?+?item.price??},?0)}},actions:?{addItem(item)?{this.items.push(item)},removeItem(id)?{this.items?=?this.items.filter(i?=>?i.id?!==?id)}}
})
📟 在組件中使用:
//?Cart.vueimport?{?useCartStore?}?from?'@/stores/cart'setup()?{const?cart?=?useCartStore()return?{items:?cart.items,total:?cart.total}
}
可以看出代碼非常簡潔直觀。
📘?Pinia 插件
Pinia 插件是一個函數,可以選擇性地返回要添加到 store 的屬性。它接收一個可選參數,即?context。
export?function?myPiniaPlugin(context)?{context.pinia?//?用?`createPinia()`?創建的?pinia。?context.app?//?用?`createApp()`?創建的當前應用(僅?Vue?3)。context.store?//?該插件想擴展的?storecontext.options?//?定義傳給?`defineStore()`?的?store?的可選對象。//?...
}
然后用?pinia.use()
?將這個函數傳給?pinia
:
pinia.use(myPiniaPlugin)
插件只會應用于「在?pinia
?傳遞給應用后」創建的 store,否則它們不會生效。
📘 實現一個持久化插件
getStorage
?函數:根據提供的?key
?從本地存儲中讀取數據。如果數據無法解析或不存在,則返回?null
。
setStorage
?函數:將提供的值轉換為 JSON 格式,并以指定的?key
?保存到本地存儲中。
DEFAULT_KEY
?常量:表示默認的本地存儲鍵名前綴。如果在選項中未提供自定義鍵名,將使用該默認鍵名。
Options
?類型:定義了插件選項對象的類型,包含?key
(本地存儲鍵名前綴)和?needKeepIds
(需要進行持久化的 Pinia 存儲的 ID 數組)兩個可選屬性。piniaPlugin` 函數:這是主要的插件函數,它接收一個選項對象,并返回一個用于處理 Pinia 存儲的函數。
import?{?PiniaPluginContext?}?from?"pinia";
import?{?toRaw?}?from?"vue";//?Get?data?from?local?storage?by?key
export?function?getStorage(key)?{const?data?=?localStorage.getItem(key);try?{return?JSON.parse(data);}?catch?(error)?{return?null;}
}//?Set?data?to?local?storage?with?a?key
export?function?setStorage(key,?value)?{const?data?=?JSON.stringify(value);localStorage.setItem(key,?data);
}const?DEFAULT_KEY?=?"pinia";type?Options?=?{key?:?string;needKeepIds?:?string[];
};const?piniaPlugin?=?({?key?=?DEFAULT_KEY,?needKeepIds?=?[]?}:?Options)?=>?{return?(context:?PiniaPluginContext)?=>?{const?{?store?}?=?context;const?data?=?getStorage(`${key}-${store.$id}`);const?subscribeToStore?=?()?=>?{if?(needKeepIds.length?===?0?||?needKeepIds.includes(store.$id))?{setStorage(`${key}-${store.$id}`,?toRaw(store.$state));}};store.$subscribe(subscribeToStore);return?{...data,};};
};export?default?piniaPlugin;
📚? 寫在最后
Pinia是Vue.js的新一代狀態管理解決方案,由Vue核心團隊開發,其設計理念簡潔直觀,易于上手使用。相較于Vuex,Pinia解決了其過于復雜的問題,提供了更符合Vue理念的狀態管理方式。
Pinia通過組合式Store結構,實現了狀態、獲取器、操作行為的邏輯分離。開發者可以輕松地創建Store模塊,在Vue組件內直接使用$store語法訪問狀態,無需導入映射函數,語法非常簡潔。同時Pinia還提供了完整的TypeScript支持,可以為State、Getters、Actions添加類型檢測。
除此之外,Pinia還有模塊熱更新,無需重載頁面即可看到狀態變更,開發調試體驗更佳。同時支持Vue DevTools進行調試,也提供插件機制等拓展功能。總的來說,Pinia是一個非常輕量、易于理解和使用的狀態管理方案,可以極大地提升Vue項目的開發效率。它是Vue生態中簡潔高效管理狀態的首選解決方案。
?