Pinia
Pinia(发音为/piːnjʌ/,如英语中的“peenya”)是最接近piña(西班牙语中的菠萝)的词;
Pinia本质上依然是一个状态管理的库,用于跨组件、页面进行状态共享(这点和Vuex、Redux一样);
一、基本认识
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>