• pinia原理


    pinia原理

    创建项目

    • 新建项目vite-pinia
    • 创建vite项目
    • 安装pinia
    mkdir vite-pinia
    cd vite-pinia
    yarn create vite
    yarn add pinia
    code .
    
    • 1
    • 2
    • 3
    • 4
    • 5

    使用pinia

    • main.js
    import { createApp } from 'vue'
    import './style.css'
    import App from './App.vue'
    import { createPinia } from 'pinia'
    const app = createApp(App)
    app.use(createPinia()).mount('#app')
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • scr/store/index.js
    import { defineStore } from "pinia";
    export const useStore = defineStore({
      id: "main",
      state: () => {
        return {
          a: 1,
        };
      },
      getters: {
        double: (store) => {
          return store.a * 2;
        },
      },
      actions: {
        add(num) {
          this.a += 1;
        },
      },
    });
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • app.vue
    
    
    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    使用自己的pinia

    • vite.config.js中添加@
    import { defineConfig } from 'vite'
    import vue from '@vitejs/plugin-vue'
    import path from 'path'
    // https://vitejs.dev/config/
    export default defineConfig({
      plugins: [vue()],
      resolve:{
        //设置路径别名
        alias: {
          '@': path.resolve(__dirname, './src'),
          }
      }
    })
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • mian.js修改为@/pinia
    import { createApp } from 'vue'
    // import './style.css'
    import App from './App.vue'
    import { createPinia } from '@/pinia'
    const app = createApp(App)
    app.use(createPinia()).mount('#app')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • store/index.js
    import { defineStore } from "@/pinia";
    export const useStore = defineStore({
      id: "main",
      state: () => {
        return {
          a: 1,
        };
      },
      getters: {
        double: (store) => {
          return store.a * 2;
        },
      },
      actions: {
        add(num) {
          this.a += 1;
        },
      },
    });
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • src下新增pinia文件夹,添加index.js

    实现pinia的store

    • pinia/index.js
    • 导出两个方法,defineStore定义store,createPinia创建一个pinia
    import { defineStore } from "./defineStore";
    
    import { createPinia } from "./createPinia";
    
    export {
        defineStore,
        createPinia
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • defineStore.js
    import { effectScope, getCurrentInstance, inject, reactive } from "vue";
    import { SymbolPinia } from "./rootStore";
    
    export function defineStore(idOrOptions, setup) {
        // 第一个参数可能是id,或者对象
      let id;
      let options;
    
      if (typeof idOrOptions === "string") {
        id = idOrOptions;
        options = setup;
      } else {
        options = idOrOptions;
        id = idOrOptions.id;
      }
    
      function useStore() {
        // 获取当前vue运行的实例
        const currentInstance = getCurrentInstance();
        const pinia = currentInstance && inject(SymbolPinia);
        // 如果实例存在,用inject注册到当前实例上
    
        if (!pinia._s.has(id)) {
            // 判断当前store上面有没有已经注册过的id
          createOptionsStore(id, options, pinia);
        }
        const store = pinia._s.get(id);
        return store;
      }
      return useStore;
    }
    
    function createOptionsStore(id, options, pinia) {
      let { state, getters, actions } = options;
    
      let scope;
    
      const store = reactive({});
    
      function setup() {
        // pinia.state是一个ref 要用value接受值
        pinia.state.value[id] = state ? state() : {};
        const localState = pinia.state.value[id];
    
        return localState;
      }
    
      const setupStore = pinia._e.run(() => {
        scope = effectScope();
        return scope.run(() => setup());
      });
      
    
    //   把当前的setupStore 合并到reactive里面,确保是一个响应式
      Object.assign(store, setupStore);
    
      pinia._s.set(id, store);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • createPinia.js
    import { effectScope, markRaw, ref } from "vue";
    import { SymbolPinia } from "./rootStore";
    
    export function createPinia() {
      const scope = effectScope(true);
      const state = scope.run(() => ref({}));
      const pinia = markRaw({
        install(app) {
          pinia._a = app;
          app.provide(SymbolPinia, pinia);
          app.config.globalProperties.$pinia = pinia;
        },
        _a: null,
        state,
        // 管理整个应用
        _e: scope,
        // 记录所有的store
        _s: new Map(),
      });
    
      return pinia
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 测试页面是否能展示出来 a 的值

    实现pinia的getters

    • setup方法
    function setup() {
        // pinia.state是一个ref 要用value接受值
        pinia.state.value[id] = state ? state() : {};
        //  localState 的值要转换响应式,否则getter不能响应
        const localState = toRefs(pinia.state.value[id]);
        return Object.assign(
          localState,
          actions,
          Object.keys(getters || {}).reduce((computedCetters, name) => {
            computedCetters[name] = computed(() => {
                // 获取当前的store
               return getters[name].call(store,store)
            });
            return computedCetters
          },{})
        );
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    实现pinia的actions

    • createOptionsStore方法
    function createOptionsStore(id, options, pinia) {
      let { state, getters, actions } = options;
    
      let scope;
    
      const store = reactive({});
    
      function setup() {
        // pinia.state是一个ref 要用value接受值
        pinia.state.value[id] = state ? state() : {};
        const localState = pinia.state.value[id];
    
        return Object.assign(localState, actions);
      }
    
      const setupStore = pinia._e.run(() => {
        scope = effectScope();
        return scope.run(() => setup());
      });
    
      function warpAction(name, action) {
        return function () {
          // 触发action
          let ret = action.apply(store, arguments);
          return ret;
        };
      }
    
      for (let key in setupStore) {
        const prop = setupStore[key];
        if (typeof prop === "function") {
          // 解决 action中this的问题  解构赋值时候,this会改变
          // const counter = useStore()
          // const {add} = counter
          // const counterAdd = (num)=>{
          //   add(num)
          // }
          setupStore[key] = warpAction(key, prop);
        }
      }
    
      //   把当前的setupStore 合并到reactive里面,确保是一个响应式
      Object.assign(store, setupStore);
    
      pinia._s.set(id, store);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    pinia的参数是函数的时候

    • 修改store/index.js
    import { defineStore } from "@/pinia";
    import { computed, reactive, toRefs } from "vue";
    export const useStore = defineStore('mian',()=>{
      const state = reactive({a:1})
      const double = computed(()=>{
        return state.a*2
      })
      const add = (num)=> state.a +=num
      return { ...toRefs(state),double,add }
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 修改defineStore.js
    import {
      computed,
      effectScope,
      getCurrentInstance,
      inject,
      reactive,
      toRefs,
    } from "vue";
    import { SymbolPinia } from "./rootStore";
    
    export function defineStore(idOrOptions, setup) {
      // 第一个参数可能是id,或者对象
      let id;
      let options;
    
      if (typeof idOrOptions === "string") {
        id = idOrOptions;
        options = setup;
      } else {
        options = idOrOptions;
        id = idOrOptions.id;
      }
    
      const isSetupStore = typeof setup === "function";
    
      function useStore() {
        // 获取当前vue运行的实例
        const currentInstance = getCurrentInstance();
        const pinia = currentInstance && inject(SymbolPinia);
        // 如果实例存在,用inject注册到当前实例上
    
        if (!pinia._s.has(id)) {
          // 判断当前store上面有没有已经注册过的id
          if (isSetupStore) {
            createSetupStore(id, setup, pinia);
          } else {
            createOptionsStore(id, options, pinia);
          }
        }
        const store = pinia._s.get(id);
        return store;
      }
      return useStore;
    }
    
    function createSetupStore(id,setup,pinia){
        const store = reactive({});
        let scope;
        const setupStore = pinia._e.run(() => {
            scope = effectScope();
            return scope.run(() => setup());
          });
          function warpAction(name, action) {
            return function () {
              // 触发action
              let ret = action.apply(store, arguments);
              return ret;
            };
          }
          for (let key in setupStore) {
            const prop = setupStore[key];
            if (typeof prop === "function") {
              // 解决 action中this的问题  解构赋值时候,this会改变
              // const counter = useStore()
              // const {add} = counter
              // const counterAdd = (num)=>{
              //   add(num)
              // }
              setupStore[key] = warpAction(key, prop);
            }
          }
          //   把当前的setupStore 合并到reactive里面,确保是一个响应式
          Object.assign(store, setupStore);
          pinia._s.set(id, store);
          return store
    }
    
    function createOptionsStore(id, options, pinia) {
      let { state, getters, actions } = options;
      function setup() {
        // pinia.state是一个ref 要用value接受值
        pinia.state.value[id] = state ? state() : {};
        const localState = toRefs(pinia.state.value[id]);
        return Object.assign(
          localState,
          actions,
          Object.keys(getters || {}).reduce((computedCetters, name) => {
            computedCetters[name] = computed(() => {
              // 获取当前的store
              return getters[name].call(store, store);
            });
            return computedCetters;
          }, {})
        );
      }
      const store = createSetupStore(id,setup,pinia)
      return store
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
  • 相关阅读:
    Unity6 向量的概念和计算、预制体变体
    【学习笔记】设计算法(Design Algorithm)
    某ERP系统存在RCE漏洞
    python 机器学习 常用函数
    APK与小程序渗透
    [译] MySQL-恢复被删除的Performance Schema 数据库
    C++语法篇(一)
    [架构之路-18]:目标系统 - 硬件平台 - 案例1 - 单片机MCU STM32 芯片的工作原理与启动流程
    初创公司即融资上亿,这个“人造超级大脑”赛道为什么不是噱头?
    全民拼购:重新定义电商营销的新模式
  • 原文地址:https://blog.csdn.net/xiaoshunshi/article/details/126761031