• Pinia简单上手


    1. 概念

    Pinia是Vue的储存库,允许跨组件/页面共享状态
    
    • 1

    2. 特性

    • 直观,像定义components一样定义 store
    • 完整的TypeScript支持
    • 去除了mutations,只有 state,getters,actions
    • actions支持同步和异步
    • Vue Devtools支持Pinia,提供更好的开发体验
    • 能够构建多个stores,并实现自动地代码拆分
    • 极其轻量(1kb),甚至感觉不到它的存在

    3. 与Vuex比较

    • mutations不在存在
    • 无需创建自定义复杂包装器来支持TypeScript,所有内容都是类型化的,并且API的设计方式尽可能利用TS类型判断
    • 不再需要注入、导入函数、调用函数、享受自动完成功能
    • 无需动态添加Store,默认情况下它们都是动态的
    • 不再有mutations的嵌套结构
    • 没有命名空间模块

    4. 基本使用

    (1)安装
    yarn add pinia
    # 或者使用 npm
    npm install pinia
    
    • 1
    • 2
    • 3
    (2)在main.js 中挂载pinia
    import { createApp } from 'vue';
    import App from './App.vue';
    // 创建pinia
    import { createPinia } from 'pinia';
    const pinia = createPinia();
    const app = createApp(App);
    app.use(pinia).mount('#app')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    (3)新建文件 store/index.js,定义一个Store
    import { defineStore } from 'pinia'
    // useStore 也可以是 useUser useXxxxStore 之类的任何东西
    // 第一个参数是应用程序中 store的唯一id
    // 第二个参数为一个对象,提供 state getters actions
    const useStore = defineStore('main', {
    	state:() => {
    		return {
    			count: 1
    		}
    	},
    	getters: {},
    	actions: {}
    })
    
    export default useStore
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    这个name,也称为id,是必要的,Pinia使用它来将store连接到 devtools。将返回的函数命名为 use… 是跨可组合项的约定,以使其符合你的使用习惯

    (4)在组件中使用
    <template>
    	<h1>{{ store.count }}</h1>
    </template>
    
    <script>
    import { defineComponent } from "vue";
    import { useStore } from '@/stores/index'
    export default defineComponent({
    	setup() {
    		const store = useStore()
    		return {
    			store 
    		}
    	}
    })
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    注意:如果想要解构store赋值是不可行的,因为它会破坏响应式

    setup() {
        const store = useStore()
        // ❌ 这不起作用,因为它会破坏响应式
        const { count } = store
        
        return {
          count, // 一直会是 1
          // 这将是响应式的
          count: computed(() => store.count),
          }
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    为了从 store中提取属性的同时保持其想应收,需要用到 storeToRefs()。它将为任何响应式属性创建refs。

    import { storeToRefs } from "pinia";
    setup(){
    	const store = useStore()
    	const { count } = storeToRefs(store)
    	return {
    		count
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    5. getters

    getters 完全等同于 store 状态的计算值

    export const useStore = defineStore('main', {
      state: () => {
          return {
              count: 1,
          }
      },
      getters: {
        // 自动将返回类型推断为数字
        doubleCount(state) {
          return state.count* 2
        },
        // 设置了返回类型
        doublePlusOne(): number {
          return this.count* 2 + 1
        },
      },
    })
    
    // 在组件中使用
    <template>
      <p>Double count is {{ store.count }}</p>
      <p>DoublePlusOne count is {{ store.count }}</p>
    </template>
    
    <script>
      setup() {
        const store = useStore()
    
        return { 
        	store 
        }
      }
    </script>
    
    • 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

    getters 只是幕后的 computed 属性,因此无法向它们传递任何参数。但是,你可以从 getters 返回一个函数接收任何参数

    export const useStore = defineStore('main', {
      getters: {
        getUserById: (state) => {
          return (userId) => state.users.find((user) => user.id === userId)
        },
      },
    })
    
    // 在组件中使用
    <script>
    export default {
      setup() {
        const store = useStore()
    
        return { 
        	getUserById: store.getUserById 
        }
      },
    }
    </script>
    
    <template>
      <p>User 2: {{ getUserById(2) }}</p>
    </template>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    访问其他 store 的 getter

    import { useOtherStore } from './other-store'
    
    export const useStore = defineStore('main', {
      state: () => {
        return {
            localData: ...
        }
      },
      getters: {
        otherGetter(state) {
          const otherStore = useOtherStore()
          return state.localData + otherStore.data
        },
      },
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    6. actions

    不管是同步还是异步的代码,都可以在 actions 中完成。actions 相当于组件中的 methods

    export const useStore = defineStore('main', {
      state: () => ({
        count: 0,
      }),
      actions: {
        increment() {
          this.count++
        },
        randomizeCount() {
          this.count = Math.round(100 * Math.random())
        },
        incrementAsync() {
    		setTimeout(() => {
            	this.count++
          	}, 1000)
    	}
      },
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    在组件中使用

    <h1>数量---{{ store.count }}</h1>
    <button @click="store.increment">1</button>
    <button @click="store.randomizeCount">随机</button>
    <button @click="store.incrementAsync">异步加1</button>
    
    setup() {
        const store = useStore()
    
        return { 
        	store
        }
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    7. pinia模块化

    在项目中,不可能把多个模块的数据放在一个store中,一般都是一个模块对应一个store,再通过一个跟store进行整合

    // 新建store/user.js
    import { defineStore } from 'pinia'
     
    const useUserStore = defineStore('user', {
      state: () => {
        return {
          name: 'zs',
          age: 18,
        }
      },
    })
    export default useUserStore
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    //新建store/app.js
    import { defineStore } from 'pinia'
     
    const useAppStore = defineStore('app', {
      state: () => {
        return {
    		roles: []
        }
      },
    })
    export default useAppStore
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    // 在store/index.js 中
    import useUserStore from './user'
    import useAppStorefrom './app'
    
    // 统一导出useStore方法
    export default function useStore() {
      return {
        user: useUserStore(),
        counter: useAppStorefrom (),
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    // 在组件中使用
    <script>
    import useStore from "@/store/index";
    
    setup() {
    	const { app, user } = useStore();
    	
    	const { name, age } = storeToRefs(user)
    }
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    8. pinia 数据持久化

    (1)安装
    yarn add pinia-plugin-persistedstate
    or
    npm i  pinia-plugin-persistedstate
    
    • 1
    • 2
    • 3
    (2)在main.js中注册
    import { createApp } from 'vue';
    import App from './App.vue';
    // 创建pinia
    import { createPinia } from 'pinia';
    // 引入 pinia插件-数据持久化
    import PiniaPluginPersistedstate from 'pinia-plugin-persistedstate';
    
    const pinia = createPinia();
    pinia.use(PiniaPluginPersistedstate)
    const app = createApp(App);
    app.use(pinia).mount('#app');
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    (3)使用
    import { defineStore } from 'pinia'
    
    export const useStore = defineStore('store', {
      state: () => {
        return {
          someState: 'hello pinia',
        }
      },
      persist: true,
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    (4)配置储存持久化的方式,为presist属性指定选项
    import { defineStore } from 'pinia'
    
    export const useStore = defineStore('store', {
      state: () => {
        return {
          someState: 'hello pinia',
        }
      },
      persist: {
      	key: 'someState', // 作为存储的默认秘钥,存储中的键名称
        storage: sessionStorage, // 默认为localStorage
        paths: ['someState'], // 部分保持状态的点符号路径数组。[]意味着没有状态被持久化,undefined或者null意味着整个状态被持久化
      },
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
  • 相关阅读:
    初识href超链接
    仿游戏热血江湖游戏类22(物品方法)
    Notion 程序猿必备笔记软件
    React+TS学习和使用(三):React Redux和项目的路由配置
    java毕业设计Steam游戏平台系统mybatis+源码+调试部署+系统+数据库+lw
    【Vue官方教程】Vue官方教程之我的笔记--20221026
    【Android进阶】10、使用布局和部件创建 UI
    计算机网络篇之端口
    使用burp抓包时出现问题
    Mybatis中的动态SQL
  • 原文地址:https://blog.csdn.net/Fxhani/article/details/126099960