Pinia存储库入门到精通教程

2022-05-22 02:21:17
2024-10-11 12:36:09

为什么要使用Pina?

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

安装

shell 复制代码
npm i -S pinia

新建 src/store/index.ts

js 复制代码
import { createPinia } from 'pinia'
const store = createPinia()
export default store

在main.ts 全局中使用

js 复制代码
import { createApp } from 'vue'
import App from './App.vue'
import store from './store/index';
 
const app = createApp(App);
app.use(store).mount('#app')

核心概念与基本使用

Store

Store 是一个保存状态和业务逻辑的实体,可以自由读取和写入,并通过导入后在 setup 中使用创建一个 store

javascript 复制代码
//新建src/store/user.ts
import { defineStore } from 'pinia';

export const useUserStore = defineStore({
  id: 'user',
  state: () => {
    return {
      name: '小白龙',
    };
  },
});

使用 Store

vue 复制代码
<template>
  <div>{{ userStore.name }}</div>
</template>

<script lang="ts" setup>
import { useUserStore } from '@/store/user'

const userStore = useUserStore()
</script>

storeToRefs

state 也可以使用解构,但使用解构会使其失去响应式,使用 storeToRefs可以不失去响应式

vue 复制代码
<template>
  <div>{{ name }}</div>
</template>

<script lang="ts" setup>
import { storeToRefs } from 'pinia'
import { useUserStore } from '@/store/user'

const userStore = useUserStore()
const { name } = storeToRefs(userStore)
</script>

computed

state 直接赋值给变量,会使其失去响应式,使用vue3的computed()可以不失去响应式

vue 复制代码
<template>
  <div>{{ name }}</div>
</template>

<script lang="ts" setup>
import { storeToRefs } from 'pinia'
import { useUserStore } from '@/store/user'

const userStore = useUserStore()
const name = computed(() => useUserStore.name)
</script>

修改 state

1、直接修改(不推荐)

js 复制代码
userStore.name = '小龙龙'

2、通过 actions去修改 state,actions 里可以直接通过 this 访问。

js 复制代码
export const useUserStore = defineStore({
  id: 'user',
  state: () => {
    return {
      name: '小白龙',
      age:18,
      friendList: [
         { name: '浪里小白龙', age: 18 },
         { name: '浪里个浪小白龙', age: 20 },
      ]
    }
  },
  actions() {
    updateName(name: string) {
      this.name = name
    }
  }
})
vue 复制代码
<script lang="ts" setup>
import { useUserStore } from '@/store/user'
const userStore = useUserStore()
userStore.updateName('小龙龙')
</script>

3、使用 $patch 修改多条数据

$patch的方式是经过优化的,多条数据同时更新状态数据会加快修改速度,性能有很大的好处。

ts 复制代码
<script lang="ts" setup>
import { useUserStore } from '@/store/user'
const userStore = useUserStore()
//方式一(浅层修改)
userStore.$patch({
    name: '浪里' + userStore.name,
    age: userStore.age + 2
  });
//方式二(深层修改)
userStore.$patch(state => {
   state.name = '浪里' + userStore.name;
   state.age = userStore.age + 2;
   state.friendList[0].name = '小萝莉' 
});
</script>

4、重置状态

可以通过调用store 上的方法将状态重置为初始状态

vue 复制代码
<script lang="ts" setup>
import { useUserStore } from '@/store/user'
const userStore = useUserStore()
userStore.$reset()
</script>

5、监听订阅state

通过 store.$subscribe() 的方法,该方法的第一个参数接受一个回调函数,该函数可以在 state 变化时触发

js 复制代码
const subscribe = mainStore.$subscribe((mutation, state) => {
    console.log(mutation)
    console.log(state)
})

其中 state 是 mainStore 实例,而 mutation 打印如下

可以发现,打印结果的mutation对象主要包含三个属性

  • events : 是这次state改变的具体数据,包括改变前的值和改变后的值等等数据

  • storeId :是当前store的id

  • type:type表示这次变化是通过什么产生的,主要有三个分别是

    • “direct” :通过 action 变化的
    • ”patch object“ :通过 $patch 传递对象的方式改变的
    • “patch function” :通过 $patch 传递函数的方式改变的

6、停止监听

store.$subscribe() 的方法的第二个参数options对象,是各种配置参数,包括

detached属性,其值是一个布尔值,默认是 false, 正常情况下,当 订阅所在的组件被卸载时,订阅将被停止删除,如果设置detached值为 true 时,即使所在组件被卸载,订阅依然可以生效。

其他属性主要还有 immediate、deep、flush 等等,和 vue3 watch的对应参数效果一样。

Getters

javascript 复制代码
export const useUserStore = defineStore({
  id: 'user',
  state: () => {
    return {
      name: '小白龙',
    }
  },
  getters: {
    formatName: (state) => {
      return state.name + '0418';
    },
  },
})
js 复制代码
userStore.formatName    //小白龙0418

pinia模块化

新建store/user.js文件

language 复制代码
import { defineStore } from 'pinia'

const useUserStore = defineStore('user', {
  state: () => {
    return {
      count: 0
    }
  },
  getters: {
    double() {
      return this.count * 2
    },
  }
})

export default useUserStore

新建store/counter.js文件

language 复制代码
import { defineStore } from 'pinia'

const useCounterStore = defineStore('counter', {
  state: () => {
    return {
      name: 'ls',
      age: 120,
    }
  },
})

export default useCounterStore

新建store/index.js

language 复制代码
import useUserStore from './user'
import useCounterStore from './counter'

// 统一导出useStore方法
export default function useStore() {
  return {
    user: useUserStore(),
    counter: useCounterStore(),
  }
}

在组件中使用

language 复制代码
<script setup>
import { storeToRefs } from 'pinia'
import useStore from './store'
const { counter } = useStore()

// 使用storeToRefs可以保证解构出来的数据也是响应式的
const { user, counter } = storeToRefs(counter)
</script>

Setup 语法

ref 与 state 对应、computed 与 getters 对应、function 与 actions 对应。

js 复制代码
export const useCounterStore = defineStore('counter', () => {
  const count = ref(0)
  const doubleCount = computed(() => count.value * 2)
  function increment() {
    count.value++
  }

  return { count, doubleCount, increment }
})

/** 在 setup 外使用 */
export function useCounterStoreHook() {
  return useCounterStore(store)
}

数据持久化

解决页面刷新,Pinia数据丢失

安装

shell 复制代码
npm i -S pinia-plugin-persistedstate

使用

javascript 复制代码
// src/store/index.ts

import { createPinia } from 'pinia'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'

const store = createPinia()
store.use(piniaPluginPersistedstate)

export default store
js 复制代码
//src/store/user.ts
import { defineStore } from 'pinia';

export const useUserStore = defineStore({
  id: 'user',
  state: () => {
    return {
      name: '小白龙',
    };
  },

  actions: {
    updateName(name: string) {
      this.name = name;
    },
  },

  getters: {
    formatName: (state) => {
      return state.name + '0418';
    },
  },

  // 开启数据缓存
 persist: true,
});

自定义 key

数据默认存在 sessionStorage 里,并且会以 store 的 id 作为 key你也可以在 strategies 里自定义 key 值,并将存放位置由 sessionStorage 改为 localStorage。

js 复制代码
// 开启数据缓存
  persist: {
    storage: sessionStorage,
    paths: ['someState'],
  },

持久化部分 state

默认所有 state 都会进行缓存,你可以通过 paths 指定要持久化的字段,其他的则不会进行持久化。

yaml 复制代码
state: () => {
  return {
    name: '小白龙',
    age: 18,
    gender: '男'
  }  
},

  persist: {
    storage: sessionStorage,
    paths: ['someState'],
  },

常见问题

目录

运营需要亿点资金维持,您的支持,是小白龙创作的动力!!!

昵称
留言
赞赏金额
暂无评论,欢迎留下你的评论