【vue3】Pinia是什么?实现原理?手写Pinia!-CSDN博客

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

前言

本文只是说明pinia的核心功能及核心原理它本身的功能是很多很复杂的这里就不进行叙述我们只需要掌握这个工具的核心功能即可。

1.是什么

Pinia是基于Vue 3的Composition API构建的状态管理库。它让你能够创建和管理多个store通过调用createPinia激活一次你能获取全应用的store访问权限。

2.主要特性

  • Pinia拥有独立的store每个store都有自己的状态(state)和行为(action)等。
  • 你能调用store = useStore()直接使用和获取store。
  • Pinia全局只需要一次安装(通过app.use(createPinia())函数)。
  • 自动在DevTools中显示每次状态改变。

3.实现原理 

以下是对 Pinia 工作原理的总结

1. 创建 Pinia 实例   
   `createPinia()` 用于生成 Pinia 实例这个实例你可以将其看作为一个全局的 store 容器用来保存所有的 Vuex store。

2. 创建 Store  
   使用 `createStore` 可以创建一个新的 store这个 store 可看做是一个独立的状态管理空间其中包含了 state、getters 和 actions被创建的 store 实例会被自动添加到 Pinia 实例中。

3. 使用 Store  
   我们通过在组件中调用用 `createStore` 创建的 store 函数来获取对应的 Pinia store 的实例。然后我们就可以访问其中的 state、getters或者执行 actions 里定义的方法。

4. 监听 Store 变化  
   我们可以使用 Vue 的 `watch` 和 `watchEffect` 函数来监听 store 中 state 或 getters 的变化以便在这些内容改变时执行相应的操作。

5. 整合到 Vue App 中  
   创建的 Pinia 实例需要使用 `app.use()` 安装到 Vue App 中以便 Pinia 与 Vue App 一同工作提供全局的状态管理能力。

ps:

如果你已经熟悉 Vue 或 Vuex那么你在学习和使用 Pinia 时应该会觉得很自然因为其设计思想和使用方式与 Vue、Vuex 非常接近但同时也提供了更加灵活和便利的特性。

 


 

3.手写pinia

简易版 Pinia 的实现中包括以下关键部分

  1. 创建一个 Pinia 对象它包含一个响应式的 Map用于存储所有的 store。
  2. 设定在 Vue 类型系统 的安装方法它将 Pinia 实例提供给整个 Vue 应用。
  3. 设定一个 createStore 方法用于创建或获取一个 store。store 是通过处理选项参数如id, state, getters, actions生成的。
  4. 设定一个 useStore 方法通过 store id 来获取 store。使用 computed() 函数确保返回的 store 是响应式的。

具体代码实现 

// 引入所需的 Vue Composition API 相关函数
import { createStore as createVuexStore, reactive, computed } from 'vue'

// 创建 Pinia 对象
function createPinia() {
    // 用 reactive 创建响应式存储对象
    const stores = reactive(new Map());

    return {
        // 安装 Pinia 到 Vue 应用
        install(app) {
            // 在 Vue 应用中注册 Pinia 实例
            app.provide('pinia', this);
        },

        // 创建名为 "createStore" 的方法用于根据选项创建或获取 store
        createStore(options) {
            // 如果 stores 已经存在相应的 store则直接返回这个 store
            if (stores.has(options.id)) {
                return stores.get(options.id);
            }

            // 使用 Vue createVuexStore 函数创建响应式 store
            const store = createVuexStore({
                id: options.id,
                state: options.state,
                getters: options.getters,
                actions: options.actions
            });

            // 将新创建的 store 添加到 stores 中
            stores.set(options.id, store);

            // 返回创建的 store
            return store;
        },

        // 使用 store 的名字获取 store
        useStore(id) {
            // 返回一个计算属性其值为获取到的 store
            return computed(() => stores.get(id));
        }
    }
}

// 创建 Store
function createStore(options) {
    // 返回一个使用 store 的函数需要在 setup() 中调用
    return function useStore(pinia = inject('pinia')) {
      // 调用 pinia 的 createStore 方法创建或获取对应的 store
        return pinia.createStore(options);
    }
}

export {
    createPinia,
    createStore
}

然后是它的实际使用了
 

  1. 首先我们要在应用层面使用 createPinia 创建 Pinia 实例并安装到 Vue 应用中
    import { createApp } from 'vue';
    import App from './App.vue';
    import { createPinia } from './pinia';
    
    // 创建 Pinia 实例
    const pinia = createPinia();
    
    // 创建 Vue 应用
    const app = createApp(App);
    
    // 使用 Pinia
    app.use(pinia);
    
    // 挂载到 DOM
    app.mount('#app');

  2. 然后我们可以通过 createStore 方法创建一个名为 useCounterStore 的 store
    import { createStore } from './pinia';
    
    export const useCounterStore = createStore({
        id: 'counter',
        state: () => ({
            count: 0
        }),
        getters: {
            isZero: state => state.count === 0
        },
        actions: {
            increment() {
                this.state.count++;
            }
        }
    });

  3. 在 Vue 组件中可以使用 useCounterStore 来获取和使用这个 store
    import { computed } from 'vue';
    import { useCounterStore } from './store';
    
    export default {
      setup() {
        const store = useCounterStore();
        
        // 使用状态
        console.log(store.state.count); // 0
        
        // 使用 getter 计算属性
        const isZero = computed(() => store.getters.isZero);
        console.log(isZero.value); // true
        
        // 使用 actions
        store.actions.increment();
        console.log(store.state.count); // 1
      }

    上文中已经描述了 get、set 和使用 store 中的 actions 的基本用法下面我将说明如果你要监听store的变化应该如何操作。

    Vue 的 Composition API 提供了 `watch` 和 `watchEffect` 函数能让你监听 reactive object 响应式对象或者 ref 引用对象的值变化。当你需要监听 store 中的数据变化时可以使用这两个函数。

    以下示例展示了如何监听 state 和 getters 的变化

    
    import { watch, watchEffect } from 'vue';
    import { useCounterStore } from './store';
    
    export default {
      setup() {
        const store = useCounterStore();
    
        // 监听 state 变化
        watch(() => store.state.count, (newCount, oldCount) => {
          console.log(`Count changed from ${oldCount} to ${newCount}`);
        });
    
        // 监听 getter 变化
        watch(() => store.getters.isZero, newVal => {
          console.log(`isZero changed to ${newVal}`);
        });
    
        // 使用 watchEffect 监听 state 变化不需要提供一个函数作为源
        watchEffect(() => {
          console.log(`Count is now ${store.state.count}`);
        });
      }
    }
    

    在这个例子中我们使用 `watch` 监听 count 和 isZero 的变化当这两个值改变时对应的回调函数就会被执行。同时我们也用 `watchEffect` 监听了 count这样只要 count 变化即使值还是原值对应的回调函数也会执行。当你在组件 setup 函数中设置了监听当组件卸载后监听也会自动停止。


     

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: vue