Pinia的使用

Pinia

Pinia(发音为/piːnjʌ/,如英语中的“peenya”)是最接近piña(西班牙语中的菠萝)的词;

Pinia本质上依然是一个状态管理的库,用于跨组件、页面进行状态共享(这点和Vuex、Redux一样);

官网:Home | Pinia (vuejs.org)

一、基本认识

1.安装

npm install pinia

2.基本使用
  • 创建一个pinia
import { createPinia } from "pinia";

const pinia = createPinia()

export default pinia
  • 注册
import pinia from './store'

createApp(App).use(pinia).mount('#app')
3.认识Store

Store的三个核心:state、getters、actions

等同于组件的data、computed、methods;

一旦 store 被实例化,你就可以直接在 store 上访问 state、getters 和 actions 中定义的任何属性;

1.定义Store

在创建的pinia文件夹中新建一个js文件,如counter.js(一个js文件为一个Store);

Store使用**defineStore()**定义:它有两个参数,第一个参数为唯一名称,第二个参数为一个对象,包含state,getters等。

// 定义一个关于counter的store
import { defineStore } from 'pinia'

const useCounter = defineStore('counter', {
  state: () => ({
    count: 100
  }),
  getters: {},
  actions: {}
})

export default useCounter
2.使用定义的Store

通过调用use函数来使用Store:

<template>
  <div class="home">
    <h2>home view</h2>
    <h2>count: {{ counterStore.count }}</h2>
    <h2>count : {{ count }}</h2>
    <button @click="incrementCount">+1</button>
  </div>
</template>

<script setup>
import useCounter from "../stores/counter";
// import { toRefs } from "vue";
import { storeToRefs } from "pinia";

const counterStore = useCounter();

// 可以解构,但是解构之后没有响应式
// const { count } = counterStore;
// 1.可以使用vue提供的toRefs使解构也具有响应式
// const { count } = toRefs(counterStore);
// 2.可以使用pinia提供的storeToRefs
const { count } = storeToRefs(counterStore);

function incrementCount() {
  counterStore.count++;
}
</script>

<style lang="scss" scoped>
</style>

二、state

  • 读取和写入 state:默认情况下,您可以通过 store 实例访问状态来直接读取和写入状态;
  • 重置 State: 可以通过调用 store 上的 $reset() 方法将状态 重置 到其初始值;
  • 改变State:除了直接用 store.counter++ 修改 store,还可以调用 $patch 方法;它允许使用部分“state”对象同时应用多个更改;
  • 替换State:可以通过将其 $state 属性设置为新对象来替换 Store 的整个状态:

user.js

import { defineStore } from "pinia";

const useUser = defineStore("user", {
  state: () => ({
    name: 'tjx',
    age: 18,
    level: 100
  })
})

export default useUser

使用:

<template>
  <div class="home">
    <h2>home view</h2>
    <h2>name: {{ name }}</h2>
    <h2>age : {{ age }}</h2>
    <h2>level : {{ level }}</h2>
    <button @click="changeState">修改state</button>
    <button @click="resetState">重置state</button>
  </div>
</template>

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

const userStore = useUser();

const { name, age, level } = storeToRefs(userStore);

function changeState() {
  // 1.一个一个修改状态
  // userStore.name = "yn";
  // userStore.age = 19;
  // userStore.level = 200;

  // 2.一次性修改多个状态: patch(),可以传入函数(该函数返回一个state)也可以传入对象
  userStore.$patch({
    name: "love",
    age: 20,
  });

  // 3.替换一个新的state
  userStore.$state = {
    name: "i love",
    level: 300,
    // 注:age属性还是存在
  };
}
function resetState() {
  // 重置state
  userStore.$reset();
}
</script>

<style lang="scss" scoped>
</style>

三、getters

Getters相当于Store的计算属性:它们可以用 defineStore() 中的 getters 属性定义; getters中可以定义接受一个state作为参数的函数;

counter.js:

// 定义一个关于counter的store
import { defineStore } from 'pinia'
import useUser from './user'

const useCounter = defineStore('counter', {
  state: () => ({
    count: 100,
    friends: [
      { id: 111, name: 'yn'},
      { id: 222, name: 'tjx'},
      { id: 333, name: 'lo'},
    ]
  }),
  getters: {
    // 1.基本使用
    doubleCount(state) {
      return state.count * 2
    },
    // 2.一个getter引入另一个getter
    doubleCountAddOne() {
      // this为store实例
      // return this.doubleCount + 1
    },
    // 3.getters也支持返回一个函数
    getFridenById(state) {
      return function(id) {
        for (let i = 0; i<state.friends.length;i++) {
          const friend = state.friends[i]
          if (friend.id === id) {
            return friend
          }
        }
      }
    },
    // 4.getter用到了别的store中的数据
    showMessage(state) {
      // 1.获取user信息
      const userStore = useUser()
      // 2.获取自己信息
      // 3.拼接信息
      return `name: ${userStore.name}-count:${state.count}`
    }
  },
  actions: {}
})

export default useCounter

使用:

<template>
  <div class="home">
    <h2>home view</h2>
    <h2>doubleCount: {{ counterStore.doubleCount }}</h2>
    <h2>doubleCountAddOne: {{ counterStore.doubleCountAddOne }}</h2>
    <h2>getFridenById-111: {{ counterStore.getFridenById(111) }}</h2>
    <h2>showMessage: {{ counterStore.showMessage }}</h2>
    <button @click="changeState">修改state</button>
    <button @click="resetState">重置state</button>
  </div>
</template>

<script setup>
import useCounter from "../stores/counter";

const counterStore = useCounter();
</script>

<style lang="scss" scoped>
</style>

四、actions

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

和getters一样,在action中可以通过this访问整个store实例的所有操作;

home.js:

import {defineStore} from 'pinia'

const useHome = defineStore('home', {
  state:() => ({
    banners: [],
    recommends: []
  }),
  actions: {
    async fetchHomeMultidata() {
      const res = await fetch('http://123.207.32.32:8000/home/multidata')
      const data = await res.json()
      this.banners = data.data.banner.list
      this.recommends = data.data.recommends.list
      return undefined
    }
  }
})

export default useHome

counter.js:

// 定义一个关于counter的store
import { defineStore } from 'pinia'

const useCounter = defineStore('counter', {
  state: () => ({
    count: 100
  }),
  getters: {},
  actions: {
    increment() {
      // 通过this访问,不会传入state
      this.count++
    },
    incrementNum(num) {
      this.count += num
    }
  }
})

export default useCounter

使用:

<template>
  <div class="home">
    <h2>home view</h2>
    <h2>count: {{ counterStore.count }}</h2>
    <button @click="changeState">修改state</button>
  </div>
</template>

<script setup>
import useCounter from "../stores/counter";
import useHome from "../stores/home";

const counterStore = useCounter();
function changeState() {
  // counterStore.increment();
  counterStore.incrementNum(100);
}
const homeStore = useHome();
homeStore.fetchHomeMultidata().then((res) => {
  console.log("成功:", res);
});
</script>

<style lang="scss" scoped>
</style>
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值