Pinia基础使用 (vite vue3)

pinia

Demo: https://github.com/ljx2/piniaDemo/blob/main/src/main.js

Pinia 概念

是 Vue 的存储库,它允许您跨组件/页面共享状态。 Vue官方推荐状态库

Pinia 的优点

pinia 符合直觉,易于学习。
pinia 是轻量级状态管理工具,大小只有1KB.
pinia 模块化设计,方便拆分。
pinia 没有 mutations,直接在 actions 中操作 state,通过 this.xxx 访问响应的状态,尽管可 以直接操作 state,但是还是推荐在 actions 中操作,保证状态不被意外的改变。
store 的 action 被调度为常规的函数调用,而不是使用 dispatch 方法或者是 MapAction 辅助函数,这是在 Vuex 中很常见的。
支持多个 store。
支持 Vue devtools、SSR、webpack 代码拆分。

什么时候使用Store

存储应该包含可以在整个应用程序中访问的数据。这包括在许多地方使用的数据
避免可以托管在组件的数据使用Store

创建项目(vite + vue3 + pinia):

pnpm create vite
cd project
pnpm i
pnpm i pinia
pnpm run dev

如果您的应用使用 Vue 2,您还需要安装组合 API:@vue/composition-api
创建一个pinia(根存储):

如果是 vue 3.2 + pinia 2.1.4版本,可能由以下报错:
import { hasInjectionContext,inject,toRaw,watch,…
在这里插入图片描述
是由于版本不兼容导致的

在package.json升级vue到3.3.4版本即可

基本使用

(1)创建一个 pinia(根存储)并将其传递给应用程序
修改main.js

import { createPinia } from 'pinia'
createApp(App).use(createPinia()).mount('#app')

(2) src下新建store文件夹,然后在store下创建counter.js文件

defineStore参数:
第一个参数是唯一的 id, 标志着一个命名空间
第二个参数是一个对象, 有三个模块: state, getters,actions

const useCounter = defineStore("counter", {
  state () {
    return {
      count: 66,
    }
  },
  getters: {
  },
  actions: {
  }
})
// 返回函数统一使用useXXX命名
export default useCounter;

(3) 在组件中使用:
修改,定义组件

<template>
  <div>展示pinia的counter的counter值: {{ counterStore.count }}</div>
  <div>解构出来的pinia的counter的count值: {{ count1 }}</div>
  <div>storeToRefs: {{ count2 }}</div>
  <button @click="addCount">count+1</button>
</template>

<script setup>
import useCounter from '../stores/counter'
import {storeToRefs} from 'pinia'
const counterStore = useCounter()
const {count1} = counterStore // 解构得到的失去响应式
const {count2} = storeToRefs(counterStore) // 不会失去响应式

function addCount() {
  counterStore.count++
}

修改App.vue,使用组件

<template>
  <Counter1/>
</template>

<script setup>
import Counter1 from './components/Counter1.vue'
</script>

(4) Store获取后不能解构, 否则失去响应式

const {count} = counterStore

解决方案:
提供了函数storeToRefs解决,作用就是把结构的数据使用ref做代理

import {storeToRefs} from 'pinia'
const counterStore = useCounter()
const {count} = storeToRefs(counterStore)

(5)修改state的数据

重新新建一个user模块store/user.js

import {defineStore} from 'pinia'

const useUser = defineStore("user", {
  state:() => ({
    name: "cq",
    age: 17
  })
})

export default useUser

新建组件 ChangeVaule.vue:
有几种修改state的方法

<template>
<div>
  <h2>名字是:{{ name }}</h2>
  <h2>年龄是: {{ age }}</h2>
  <button @click="updateStore">修改Store数据</button>
  <button @click="resetStore">重置Store数据</button>
</div>
</template>

<script setup>
import useUser from '../stores/user'
import { storeToRefs } from 'pinia';

const userStore = useUser()
const {name, age} = storeToRefs(userStore)

function updateStore() {
  // 1. 一个个修改状态
  // userStore.name = "川崎"
  // userStore.age = 19

  // 2. $patch一次改变多个状态
  userStore.$patch({
    name: "川川",
    age: 18
  })

  // 3. $state(替换, 基本不用)
}

function resetStore() {
  // 4. $reset()是重置state数据的
  userStore.$reset()
}
</script>

getters的使用:

getters类似于vue的计算属性,可以对已有的数据进行修饰。不管调用多少次,getters中的函数只会执行一次,而且会缓存

(1) 最基本使用
在store/counter.js添加getters:

const useCounter = defineStore("counter", {
  state:() => ({
    count:66,
  })
  getters: {
    doubleCount(state) {
      doubleCount(state) {
          return state.count * 2
      }
    }
  }
})

export default useCounter

在组件中使用:

<div>
  <h1>getters使用: </h1>
  <h2>doubleCount:{{counterStore.doubleCount}}</h2>
</div>

(2)一个getter引入另一个getter
counter模块:

getters: {
  doubleCount(state) {
    return state.count * 2
  },
  doubleCountAddTwo() {
    console.log(this)
    return this.doubleCount + 2
  }
}

组件中使用:

<div>
  <h2>doubleCount: {{counterStore.doubleCount}}</h2>
  <h2>doubleCountAddTwo: {{counterStore.doubleCountAddTwo}}</h2>
</div>

运行且看看getters的this打印:

在这里插入图片描述
this中有两个getters

(3) getters中使用别的store数据
在counter模块中拿user模块store数据

count模块的getters添加:

import useUser from "./user"
...
 showMessage(state){
     console.log(state);
     console.log(this)
     //获取user信息,拿到useUser模块
     const userStore = useUser()
     //拼接信息
     return `name:${userStore.name}--count:${state.count}`
 }

在组件中使用:

<div>
  <h2>showMessage:{{counterStore.showMessage}}</h2>
</div>

结果:
在这里插入图片描述
实现了counter模块中拿到了user模块的数据

actions的使用:

actions可以处理同步,也可以处理异步,类似于methods

(1) 同步使用:
counter模块使用:
在actions定义两个函数一个加1函数,一个加Num函数

  actions: {
    increment(state) {
      console.log(state)
      console.log(this)
      this.count++
    },

    incrementNum(num) {
      this.count += num
    },

组件中使用:

    <h2>展示pinia的counter的counter值: {{ counterStore.count }}</h2>
    <h2>doubleCountAddTwo:{{ counterStore.doubleCountAddTwo }}</h2>

    <button @click="incrementOne">count+1</button>
    <button @click="incrementNum">count+20</button>

在这里插入图片描述

点击count+1 ⇒ 加一
点击count+20 ⇒ 加二十

(2) 异步操作使用
在actions处理异步的时候,异步是与async和await连用

在actions中添加:

    // 异步操作
    async getData() {
      const res =await new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve([11,22,33,44])
        }, 2000)
      })

      this.list = res
      return "ok"
    }

新建组件AsyncChangeData.vue:

<template>
  <!-- 遍历store的数据 -->
  <div v-for="item in counterStore.list">{{ item }}</div>
</template>

<script setup>
import useCounter from '../stores/counter'
const counterStore = useCounter()

counterStore.getData().then(res =>{
console.log("成功",res);
})
</script>

可以看到异步数据延迟显示

数据持久化:

(1) 添加库:

npm i pinia-plugin-persist

(2) 在store中添加:

  persist: {
    enabled: true, // 开启缓存  默认会存储在本地localstorage
    storage: sessionStorage, // 缓存使用方式
    paths:[] // 需要缓存键 
  },

在这里插入图片描述
可以看到session中存储的信息

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值