目录
- 前言
- 如何通过 provide/inject 实现 Vuex的功能
- 在应用中注册此插件
- 插件的入口文件
- 创建 store ,把对应的数据挂载到根组件上
- 实现 mapState、mapMutations 和 mapActions方法
- 组件中使用
- 总结
前言
在 Vue 生态中, Vuex 这个官方的状态管理库在 Vue 应用开发中,为我们带来了非常便捷的功能。但是 Vuex 20K+ 的大小,也带来了一些成本,对于项目规模较小的应用来说, 引入 Vuex 只是为了存储用户信息之类的一小撮数据,有点不值得。
Vue2.2.x 在后期就提供了 provide/inject API 来帮我们实现跨层级组件之间的通信。
Vue3.x 把 provide 也放到了应用 API 上,这就更方便让我们在此基础上,实现一个基础的状态管理。
如何通过 provide/inject 实现 Vuex的功能
首先我们想一下大概的逻辑,把它做成一个插件,通过 use 方法注册到应用实例中。
在 install 方法中,通过 app.provide 方法,把数据挂载到根组件上,该数据应该是一个响应式数据,并且为了数据安全,应该对数据的变更进行限制,遵循单向数据流的设计,不能让用户直接的进行修改,所以在暴露数据时,应该对数据进行 readonly(只读) 处理。
实现类似 Vuex 的 useStore 功能,让用户通过此方法访问数据。
实现类似 Vuex 的 mapState、mapMutations 和 mapActions方法,简化操作。
用法直接跟 Vuex 一样。
在应用中注册此插件
// 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')
插件的入口文件
在入口文件中,直接导出所有方法。
// sky-vuex/index.ts export * from './main/index'
创建 store ,把对应的数据挂载到根组件上
store 本身是一个对象,包含 state 属性和 commit、dispatch 等方法。 store 最主要的一些功能就是让所有组件,都能拿到 store 对象,来获取 state 中的数据,以及调用相关方法来修改 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 = {}) => { // 创建 store 对象 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 对象 return inject(mainStoreSky) }
实现 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)">修改数据</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>
总结
至此已经实现了基础的 Vuex 功能,可以自己动手实践一下,进行优化,有问题欢迎大家提出
到此这篇关于vue3如何使用provide实现状态管理的文章就介绍到这了,更多相关vue3 provide实现状态管理内容请搜索NICE源码以前的文章或继续浏览下面的相关文章希望大家以后多多支持NICE源码!