vue3如何使用provide實(shí)現(xiàn)狀態(tài)管理詳解
前言
在 Vue 生態(tài)中, Vuex 這個(gè)官方的狀態(tài)管理庫在 Vue 應(yīng)用開發(fā)中,為我們帶來了非常便捷的功能。但是 Vuex 20K+ 的大小,也帶來了一些成本,對(duì)于項(xiàng)目規(guī)模較小的應(yīng)用來說, 引入 Vuex 只是為了存儲(chǔ)用戶信息之類的一小撮數(shù)據(jù),有點(diǎn)不值得。
Vue2.2.x 在后期就提供了 provide/inject API 來幫我們實(shí)現(xiàn)跨層級(jí)組件之間的通信。
Vue3.x 把 provide 也放到了應(yīng)用 API 上,這就更方便讓我們?cè)诖嘶A(chǔ)上,實(shí)現(xiàn)一個(gè)基礎(chǔ)的狀態(tài)管理。
如何通過 provide/inject 實(shí)現(xiàn) Vuex的功能
首先我們想一下大概的邏輯,把它做成一個(gè)插件,通過 use 方法注冊(cè)到應(yīng)用實(shí)例中。
在 install 方法中,通過 app.provide 方法,把數(shù)據(jù)掛載到根組件上,該數(shù)據(jù)應(yīng)該是一個(gè)響應(yīng)式數(shù)據(jù),并且為了數(shù)據(jù)安全,應(yīng)該對(duì)數(shù)據(jù)的變更進(jìn)行限制,遵循單向數(shù)據(jù)流的設(shè)計(jì),不能讓用戶直接的進(jìn)行修改,所以在暴露數(shù)據(jù)時(shí),應(yīng)該對(duì)數(shù)據(jù)進(jìn)行 readonly(只讀) 處理。
實(shí)現(xiàn)類似 Vuex 的 useStore 功能,讓用戶通過此方法訪問數(shù)據(jù)。
實(shí)現(xiàn)類似 Vuex 的 mapState、mapMutations 和 mapActions方法,簡化操作。
用法直接跟 Vuex 一樣。
在應(yīng)用中注冊(cè)此插件
// main.ts import { createApp } from 'vue' import App from './App.vue' import router from './router' import store from './store' const app = createApp(App) app.use(router).use(store).mount('#app')
插件的入口文件
在入口文件中,直接導(dǎo)出所有方法。
// sky-vuex/index.ts export * from './main/index'
創(chuàng)建 store ,把對(duì)應(yīng)的數(shù)據(jù)掛載到根組件上
store 本身是一個(gè)對(duì)象,包含 state 屬性和 commit、dispatch 等方法。 store 最主要的一些功能就是讓所有組件,都能拿到 store 對(duì)象,來獲取 state 中的數(shù)據(jù),以及調(diào)用相關(guān)方法來修改 state。
// sky-vuex/main/index.ts import {inject, reactive, readonly} from 'vue' const mainStoreSky = Symbol('main store key') interface storeOptions { state?: any actions?: any mutations?: any } export const createStore = (options: storeOptions = {}) => { // 創(chuàng)建 store 對(duì)象 const initOptions = { state: {}, actions: {}, mutations: {}, } const mergeOptions: storeOptions = Object.assign(initOptions, options) const state = reactive(mergeOptions.state) const store = { state: readonly(state), dispatch(eventName: string, ...args: any[]) { mergeOptions.actions[eventName](store, ...args) }, commit(eventName: string, ...args: any[]) { ... }, } return { install(app: any) { app.provide(mainStoreSky, store) }, } } export const useStore = (): any => { // 其他組件通過此方法,獲取 store 對(duì)象 return inject(mainStoreSky) }
實(shí)現(xiàn) mapState、mapMutations 和 mapActions方法
export const mapState = () => { const store = useStore() return store.state } export const mapActions = (eventName: string) => { const store = useStore() return (...args: any[]) => store.dispatch(eventName, ...args) } export const mapMutations = (eventName: string) => { const store = useStore() return (...args: any[]) => store.commit(eventName, ...args) }
組件中使用
// store/index.ts import { createStore } from '../sky-vuex/index' export default createStore({ state: { age: 18 }, mutations: { setAge(state: any, data: number) { state.age = data } }, })
// Home.vue <template> <div class="home"> <button @click="handleAge(23)">修改數(shù)據(jù)</button> <h1>{{ state.age }}</h1> </div> </template> <script lang="ts"> import { defineComponent } from 'vue' import { useStore, mapActions, mapMutations } from '@/sky-vuex/index' export default defineComponent({ name: 'Home', setup() { const store = useStore() const handleAge = mapMutations('setAge') // const handleAge = mapActions('setAge') // const handleAge = () => { // store.dispatch('setAge', 5) // } return { state: store.state, handleAge, } }, }) </script>
總結(jié)
至此已經(jīng)實(shí)現(xiàn)了基礎(chǔ)的 Vuex 功能,可以自己動(dòng)手實(shí)踐一下,進(jìn)行優(yōu)化,有問題歡迎大家提出
到此這篇關(guān)于vue3如何使用provide實(shí)現(xiàn)狀態(tài)管理的文章就介紹到這了,更多相關(guān)vue3 provide實(shí)現(xiàn)狀態(tài)管理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
el-select自定義指令實(shí)現(xiàn)觸底加載分頁請(qǐng)求options數(shù)據(jù)(完整代碼和接口可直接用)
某些情況下,下拉框需要做觸底加載,發(fā)請(qǐng)求,獲取option的數(shù)據(jù),下面給大家分享el-select自定義指令實(shí)現(xiàn)觸底加載分頁請(qǐng)求options數(shù)據(jù)(附上完整代碼和接口可直接用),感興趣的朋友參考下吧2024-02-02vue使用cesium創(chuàng)建數(shù)據(jù)白模方式
這篇文章主要介紹了vue使用cesium創(chuàng)建數(shù)據(jù)白模方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-10-10vue動(dòng)態(tài)生成新表單并且添加驗(yàn)證校驗(yàn)規(guī)則方式
這篇文章主要介紹了vue動(dòng)態(tài)生成新表單并且添加驗(yàn)證校驗(yàn)規(guī)則方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-10-10el-table點(diǎn)擊某一行高亮并顯示小圓點(diǎn)的實(shí)現(xiàn)代碼
這篇文章主要介紹了el-table點(diǎn)擊某一行高亮并顯示小圓點(diǎn),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-08-08Vue filter 過濾當(dāng)前時(shí)間 實(shí)現(xiàn)實(shí)時(shí)更新效果
這篇文章主要介紹了Vue filter 過濾當(dāng)前時(shí)間 實(shí)現(xiàn)實(shí)時(shí)更新效果,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-12-12vue使用vue-video-player插件播放視頻的步驟講解
在最近的項(xiàng)目中有一個(gè)視頻播放的功能,在之前的項(xiàng)目中沒有接觸過類似的功能,第一次接觸,把具體操作步驟一下,這篇文章主要給大家介紹了關(guān)于vue使用vue-video-player插件播放視頻的相關(guān)資料,需要的朋友可以參考下2022-12-12