Pinia 学习笔记(版本2.1.6)

Pinia 学习笔记(版本2.1.6)

一.介绍

冷知识:为什么是 Pinia

Pinia(发音为 /piːnjʌ/,类似于英语中的“peenya”)是最接近有效包名 piña(西班牙语中的_pineapple_)的词。 菠萝实际上是一组单独的花朵,它们结合在一起形成多个水果。 与 Store 类似,每一家都是独立诞生的,但最终都是相互联系的。 它也是一种美味的热带水果,原产于南美洲。

他是一个全局状态管理工具,有如下特点:

  1. 完整的 ts 的支持;
  2. 足够轻量,压缩后的体积只有1kb左右;
  3. 去除 mutations,只有 state,getters,actions;
  4. actions 支持同步和异步;
  5. 代码扁平化没有模块嵌套,只有 store 的概念,store 之间可以自由使用,每一个store都是独立的
  6. 无需手动添加 store,store 一旦创建便会自动添加;
  7. 支持Vue3 和 Vue2

二.快速开始

安装依赖

npm install pinia

引入、注册插件

import { createApp } from 'vue'
import App from './App.vue'
import {createPinia} from 'pinia'
 
const store = createPinia()
let app = createApp(App)
 
app.use(store)
app.mount('#app')

新建一个文件夹Store,新建文件[name].ts,定义仓库Store

import {defineStore} from 'pinia'

export const UseTestStore = defineStore('t',{
    state: () => {
        return {
            current: 1,
            name: "aaa"
        }
    },
    getters: {
        
    },
    actions: {

    }
})

defineStore()第一个参数,也称为id,是必要的,Pania 使用它来将商店连接到 devtools。将返回的函数命名为use...是可组合项之间的约定,以使其使用习惯。

在组件中使用

<template>
  <div>
    <h1>
      Pina:{{ store.current }}--{{ store.name }}
    </h1>
  </div>
</template>
<script setup lang="ts">
import { UseTestStore } from './store';
const store =  UseTestStore()
</script>
<style></style>

三.基础

3.1 State

3.1.1 修改内容

大多数时候,state 是 store 的核心部分。 我们通常从定义应用程序的状态开始。 在 Pinia 中,状态被定义为返回初始状态的函数。 Pinia 在服务器端和客户端都可以工作。

默认情况下,您可以通过 store 实例访问状态来直接读取和写入状态:

<template>
  <div>
    <button @click="chage()">按钮</button>
    <h1>
      Pina:{{ store.number }}--{{ store.name }}
    </h1>
  </div>
</template>
<script setup lang="ts">
import { UseTestStore } from './store';
const store =  UseTestStore()
const chage = ()=>{
  //做下面的操作
}
</script>
<style></style>

在change函数中,我们有几种方式做修改或者替换:

  1. 直接修改,简单粗暴:

    	store.number ++
    
  2. $patch(对象)方法:

      store.$patch({
        number: 2,
        name: "测试修改"
      })
    
  3. $patch(函数)方法:

      store.$patch((patch)=>{
        patch.number = 777
        patch.name = "999"
      })
    

    Tips:和上面的对象方式相比,这种方式可以在函数中做一些逻辑。

  4. $state(对象)方法:

      store.$state = { 
        number: 888, 
        name: "999"
      }
    

    Tips:注意这种方式是替换patch的内容了,不是修改

  5. actions 方法:

    在定义Store的actions中创建函数,直接使用this就可以指到state里面的值,然后修改。

    import {defineStore} from 'pinia'
    
    export const UseTestStore = defineStore('t',{
        state: () => {
            return {
                number: 1,
                name: "aaa"
            }
        },
        getters: {
            
        },
        actions: {
            addNumber(num:number){
                this.number += num
            }
        }
    })
    

    组件中调用addnumber函数

    <script setup lang="ts">
    import { UseTestStore } from './store';
    const store =  UseTestStore()
    const chage = ()=>{
      store.addNumber(4)
    }
    </script>
    
  6. 补充:$reset()

    可以通过调用 store 上的 $reset() 方法将状态 重置 到其初始值:

    const store = useStore()
    
    store.$reset()
    

3.1.2 解构内容

直接解构State是不具有响应式的,Pinia提供了一个函数storeToRefs,解构的时候用它包裹一下就好了。

import { storeToRefs } from 'pinia';
import { UseTestStore } from './store';
const store =  UseTestStore()
const {number,name} = storeToRefs(store) 

Tips:原理和toRefs是一样的,所以在函数中要改变其中的值的之后,需要使用属性.value来进行修改

3.2 Getters

Getter 完全等同于 Store 状态的 计算值 并且有缓存。 它们可以用 defineStore() 中的 getters 属性定义。 他们接收“状态”作为第一个参数以鼓励箭头函数的使用:

getters:{
       newPrice:(state)=>  `$${state.user.price}`
    },

普通函数形式可以使用this

getters:{
       newCurrent ():number {
           return ++this.current
       }
    },

在组件中还用模板直接调用就可以

<template>
  <div>
    <button @click="chage()">改变</button>

    <button @click="back()">还原</button>
    <h1>
      Pina.属性获取:{{ store.number }}--{{ store.name }}
    <br>
      Pina解构获取:{{ number }}=== {{ store.showNumber}}--{{ name }}
    </h1>
  </div>
</template>

Tips:getters 可以互相调用

3.3 Actions

Actions 相当于组件中的 methods。 它们可以使用 defineStore() 中的 actions 属性定义,并且它们非常适合定义业务逻辑

export const UseTestStore = defineStore('t',{
    state: () => {
        return {
            number: 1,
            name: "aaa"
        }
    },
    getters: {
        
    },
    actions: {
        async changeName() {
            const result =  await change2()
            this.number = result.number 
            this.name = result.name
          	this.addNumber(5)
        }
      	addNumber(num:number){
            this.number += num
        },
    }

Tips:在actions中,方法是可以相互调用的

在组件中可以直接调用其中的方法

import { UseTestStore } from './store';
const store =  UseTestStore()
const chage = ()=>{
  store.addNumber(3)
  store.changeName()
}

四.其他API

4.1$subscribe()

订阅State订状态,只要state中的值的状态发生变化,这个函数就会触发

import { UseTestStore } from './store';
const store =  UseTestStore()
store.$subscribe((args,state)=>{
   console.log(args,state);
})

如果你的组件卸载之后还想继续调用请设置第二个参数detached:true

import { UseTestStore } from './store';
const store =  UseTestStore()
store.$subscribe((args,state)=>{
   console.log(args,state);
},{
  detached:true
})

4.2$onAction()

订阅Action及其结果。传递给它的回调在 action 之前执行。 after 处理 Promise 并允许您在 action 完成后执行函数。

import { UseTestStore } from './store';
const store =  UseTestStore()
store.$onAction((args)=>{
   console.log(args);
})

如果你的组件卸载之后还想继续调用请设置第二个参数为true

import { UseTestStore } from './store';
const store =  UseTestStore()
store.$onAction((args)=>{
   console.log(args);
},true)

Tips:和subscribe方式不同,onAction继续订阅直接设置为true就好了,第一个方法要给一个对象

posted @ 2023-08-10 11:28  抓哇攻城狮  阅读(68)  评论(0)    收藏  举报