如何使用pinia
首先进行安装:npm install pinia
创建一个pinia并注册
src
├─ App.vue
├─ main.js
├─ stores
│ ├─ counter.js
│ ├─ home.js
│ ├─ index.js
│ └─ user.js
└─ views
├─ 01_pinia的基本使用.vue
├─ 02_Pinia的核心State.vue
├─ 03_Pinia的核心Getters.vue
└─ Home.vue
import { createPinia } from 'pinia'
const pinia = createPinia()
export default pinia
import { createApp } from 'vue'
import App from './App.vue'
import pinia from './stores'
createApp(App).use(pinia).mount('#app')
定义一个Store:我们需要知道 Store 是使用 defineStore() 定义的,并且它需要一个唯一名称,作为第一个参数传递,这个name,也称为id,是必要的,Pinia 使用它来将 store 连接到 devtools,返回的函数统一使用useX作为命名方案,这是约定的规范
// 定义关于counter的store
import { defineStore } from 'pinia'
import useUser from './user'
const useCounter = defineStore("counter", {
state: () => ({
count: 99,
}),
})
export default useCounter
Store在它被使用之前是不会创建的,我们可以通过调用use函数来使用Store 注意Store获取到后不能被解构,那么会失去响应式,为了从 Store 中提取属性同时保持其响应式,您需要使用storeToRefs()
<template>
<div class="home">
<h2>Home View</h2>
<h2>count: {{ counterStore.count }}</h2>
<h2>count: {{ count }}</h2>
<button @click="incrementCount">count+1</button>
</div>
</template>
<script setup>
import { toRefs } from 'vue'
import { storeToRefs } from 'pinia'
import useCounter from '@/stores/counter';
const counterStore = useCounter()
// const { count } = toRefs(counterStore)
const { count } = storeToRefs(counterStore)
function incrementCount() {
counterStore.count++
}
</script>
<style scoped>
</style>
认识和定义State
state 是 store 的核心部分,因为store是用来帮助我们管理状态的,在 Pinia 中,状态被定义为返回初始状态的函数
import { defineStore } from 'pinia'
const useUser = defineStore("user", {
state: () => ({
name: "why",
age: 18,
level: 100
})
})
export default useUser
读取和写入State:
- 默认情况下,您可以通过 store 实例访问状态来直接读取和写入状态
- 你可以通过调用 store 上的 $reset() 方法将状态重置到其初始值
- 除了直接用 store.counter++ 修改 store,你还可以调用 $patch 方法
- 您可以通过将其 $state 属性设置为新对象来替换 Store 的整个状态
<template>
<div class="home">
<h2>Home View</h2>
<h2>count: {{ counterStore.count }}</h2>
<h2>count: {{ count }}</h2>
<button @click="incrementCount">count+1</button>
</div>
</template>
<script setup>
import { toRefs } from 'vue'
import { storeToRefs } from 'pinia'
import useCounter from '@/stores/counter';
const counterStore = useCounter()
// const { count } = toRefs(counterStore)
const { count } = storeToRefs(counterStore)
function incrementCount() {
counterStore.count++
}
</script>
<style scoped>
</style>
认识和定义Getters
Getters相当于Store的计算属性:
- 它们可以用 defineStore() 中的 getters 属性定义
- getters中可以定义接受一个state作为参数的函数
- 访问其他store的Getters
- Getters也可以返回一个函数,这样就可以接受参数
// 定义关于counter的store
import { defineStore } from 'pinia'
import useUser from './user'
const useCounter = defineStore("counter", {
state: () => ({
count: 99,
friends: [
{ id: 111, name: "why" },
{ id: 112, name: "kobe" },
{ id: 113, name: "james" },
]
}),
getters: {
// 1.基本使用
doubleCount(state) {
return state.count * 2
},
// 2.一个getter引入另外一个getter
doubleCountAddOne() {
// this是store实例
return this.doubleCount + 1
},
// 3.getters也支持返回一个函数
getFriendById(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.getters中用到别的store中的数据
showMessage(state) {
// 1.获取user信息
const userStore = useUser()
// 2.获取自己的信息
// 3.拼接信息
return `name:${userStore.name}-count:${state.count}`
}
}
})
export default useCounter
<template>
<div class="home">
<h2>Home View</h2>
<h2>doubleCount: {{ counterStore.doubleCount }}</h2>
<h2>doubleCountAddOne: {{ counterStore.doubleCountAddOne }}</h2>
<h2>friend-111: {{ counterStore.getFriendById(111) }}</h2>
<h2>friend-112: {{ counterStore.getFriendById(112) }}</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 scoped>
</style>
认识和定义Action
Actions 相当于组件中的 methods, 可以使用 defineStore() 中的 actions 属性定义,并且它们非常适合定义业务逻辑 和getters一样,在action中可以通过this访问整个store实例的所有操作
// 定义关于counter的store
import { defineStore } from 'pinia'
import useUser from './user'
const useCounter = defineStore("counter", {
state: () => ({
count: 99,
friends: [
{ id: 111, name: "why" },
{ id: 112, name: "kobe" },
{ id: 113, name: "james" },
]
}),
getters: {
// 1.基本使用
doubleCount(state) {
return state.count * 2
},
// 2.一个getter引入另外一个getter
doubleCountAddOne() {
// this是store实例
return this.doubleCount + 1
},
// 3.getters也支持返回一个函数
getFriendById(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.getters中用到别的store中的数据
showMessage(state) {
// 1.获取user信息
const userStore = useUser()
// 2.获取自己的信息
// 3.拼接信息
return `name:${userStore.name}-count:${state.count}`
}
},
actions: {
increment() {
this.count++
},
incrementNum(num) {
this.count += num
}
}
})
export default useCounter
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.recommend.list
// return new Promise(async (resolve, reject) => {
// 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.recommend.list
// resolve("bbb")
// })
}
}
})
export default useHome
<template>
<div class="home">
<h2>Home View</h2>
<h2>doubleCount: {{ counterStore.count }}</h2>
<button @click="changeState">修改state</button>
<!-- 展示数据 -->
<h2>轮播的数据</h2>
<ul>
<template v-for="item in homeStore.banners">
<li>{{ item.title }}</li>
</template>
</ul>
</div>
</template>
<script setup>
import useCounter from '@/stores/counter';
import useHome from '@/stores/home';
const counterStore = useCounter()
function changeState() {
// counterStore.increment()
counterStore.incrementNum(10)
}
const homeStore = useHome()
homeStore.fetchHomeMultidata().then(res => {
console.log("fetchHomeMultidata的action已经完成了:", res)
})
</script>
<style scoped>
</style>