Pinia大菠萝🍍

1.为什么需要pinia
-
Pinia最初只是为了初探Vuex的下一次迭代是什么样子,结合了Vuex5 核心团队讨论中的许多想法
-
最终,团队意识到Pinia已经实现了Vuex5中大部分内容,所以最终决定用Pinia来替代Vuex;
-
与 Vuex 相比,Pinia 提供了一个更简单的 API,具有更少的仪式,提供了 Composition-API 风格的 API;
-
最重要的是,在与 TypeScript 一起使用时具有可靠的类型推断支持;
-
和Vuex相比,Pinia有许多优势:
-
mutations不再存在,因为mutations通常被认为是非常冗长
-
更友好的Typescript支持,Vuex对TS支持并不友好
-
不再有modules的嵌套结构:
- 可以灵活使用每一个store,它们是通过扁平化的方式来相互使用
-
2.如何使用Pinia
以下步骤都是以脚手架形式开发的,所以学习pinia之前请下载个脚手架生成项目
- 2.1:第一步当然是下载Pinia辣
- 2.2:创建stores/index.js作为入口文件
- 2.3:去到main.js中导入
- 2.4:创建counter.js
yarn add pinia
#or with npm
npm install pinia
//stores/index.js
import {createPinia} from "pinia";
const pinia = createPinia();
export default pinia
//main.js
import pinia from './stores'
//counter.js
//定义关于counter的store
import {defineStore} from "pinia"
//defineStore返回的是一个函数
const useCounterStore = defineStore("counter",{
state:() => ({
count:99
})
})
export default useCounterStore
创建Home组件
<template>
<div class="home">
<h2>
Home View
</h2>
<h2>count:{{CounterStore.count}}</h2>
<h2>count:{{count}}</h2>
<button @click="increment">
点击更新count
</button>
</div>
</template>
<script setup>
import useCounterStore from "@/stores/counter"
import {storeToRefs} from "pinia" //pinia提供的响应式
const CounterStore = useCounterStore()
//也可以进行结构
const {count} = storeToRefs(CounterStore)
const increment = () => {
CounterStore.count++
}
</script>
在App.vue中导入Home组件
<template>
<Home />
</template>
<script setup>
import Home from "./views/Home.vue"
</script>
3.State的使用与认识
3.1.创建user.js文件
import {defineStore} from "pinia"
const useUserStores = defineStore("user",{
state:()=> ({
name:"tim",
age:21,
level:20
})
})
export default useUserStores
<template>
<div class="home">
<h2>
Home View
</h2>
<h2>name:{{name}}</h2>
<h2>age:{{age}}</h2>
<h2>level:{{level}}</h2>
</div>
</template>
<script setup>
import useUserStore from "pinia"
const useUserStore = useUserStores()
const {name,age,level} = storeToRefs(useUserStore)
</script>
3.2.操作State
- 1.认识不同方式的操作State数据
- 2.使用$reset()进行数据重置(数据一开始pinia会进行缓存)
<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 useUserStore from "pinia"
const useUserStore = useUserStores()
const {name,age,level} = storeToRefs(useUserStore)
//修改State
const changeState = () => {
//1. 一次只修改一个状态
//useUserStore.name = "kobe",
//useUserStore.age = "18",
//useUserStore.level = 100
//2. 一次修改所有状态
//useUserStore.$patch({
//name:"james",
//age:35
//})
//3. 替换state为新的对象 (很少使用)
useUserstore.$state = {
name:"姚明",
level:80
}
}
//重置State
const resetState = () => {
useUserStore.$reset() //可以重置到初始化状态,因为一开始就缓存了初始化状态
}
</script>
4.认识Getters
- 它们可以用 defineStore() 中的 getters 属性定义;
- getters中可以定义接受一个state作为参数的函数;
- getter相当于Store的计算属性
4.1定义Getters
- 1.使用getters:{定义函数(state)} 函数里面提供了state数据可以直接获取 || getters里面可以直接是用this获取
- 2.getters引入另外一个getters的使用
- 3.getters支持返回函数
- 4.getters中使用别的store中数据
//counter.js
//定义关于counter的store
import {defineStore} from "pinia"
import {useUserStores} from "./user"
//defineStore返回的是一个函数
const useCounterStore = defineStore("counter",{
state:() => ({
count:99,
person: [
{id:1,name:"周冬雨"},
{id:2,name:"周杰伦"},
{id:3,name:"周笔畅"}
]
}),
getters: {
//1.基本使用
doubleCount(state) {
return state.count * 2
}
doubleCountChange() {
return this.doubleCount + '🫐'
}
getPersonId(state) {
return function(id) {
return state.person.filter(item => item.id === id)
}
}
showMessage() {
//1.获取user信息
const useUserStore = useUserStores()
//2.获取本文件信息
//3.拼接信息
return `name:${useUserStore.name}-count:${state.count}`
}
}
})
export default useCounterStore
<template>
<div class="home">
<h2>
Home View
</h2>
<h2>doubleCount: {{CounterStore.doubleCount}}</h2>
<h2>
doubleCountChange: {{CounterStore.doubleCountChange}}
</h2>
<h2>
getPersonId: {{CounterStore.getPersonId(2)}}
</h2>
<h2>
showMessage: {{CounterStore.showMessage}}
</h2>
</div>
</template>
<script setup>
import useCounterStore from "@/stores/counter"
import {storeToRefs} from "pinia" //pinia提供的响应式
const CounterStore = useCounterStore()
</script>
5.认识和定义Actions
Actions相当于组件中的methods
- 可以使用defineStore()中的actions属性定义,并且它们非常适合定义业务逻辑
- Actions和Getters一样可以使用this访问整个store实例的所有操作
5.1定义actions
//counter.js
//定义关于counter的store
import {defineStore} from "pinia"
import {useUserStores} from "./user"
//defineStore返回的是一个函数
const useCounterStore = defineStore("counter",{
state:() => ({
count:99,
person: [
{id:1,name:"周冬雨"},
{id:2,name:"周杰伦"},
{id:3,name:"周笔畅"}
]
}),
getters: {
//1.基本使用
doubleCount(state) {
return state.count * 2
}
doubleCountChange() {
return this.doubleCount + '🫐'
}
getPersonId(state) {
return function(id) {
return state.person.filter(item => item.id === id)
}
}
showMessage() {
//1.获取user信息
const useUserStore = useUserStores()
//2.获取本文件信息
//3.拼接信息
return `name:${useUserStore.name}-count:${state.count}`
}
},
actions: {
increment(state) {
console.log(state) //actions没有state,参数是传递的参数
this.count++
}
}
})
export default useCounterStore
<template>
<div class="home">
<h2>
Home View
</h2
<h2>
doubleCount: {{count}}
</h2>
<button @click="changeState">修改state</button>
</div>
</template>
<script setup>
import useCounterStore from "@/stores/counter"
import {storeToRefs} from "pinia" //pinia提供的响应式
const CounterStore = useCounterStore()
const {count} = storeToRefs(CounterStore)
function changeState() {
CounterStore.increment()
}
</script>
5.2.actions异步操作
- 1.定义home.js,并且提前给state给数据类型(随便提一嘴,pinia和ts会了之后,简直无敌)
- 2.定义actions获取数据并且赋值给state
- 3.在home.vue中使用
//home.js
import {defineStore} from "pinia"
const useHomeStores = defineStore("home",{
state: ()=> ({
banners:[],
recommends:[]
})
actions: {
async fetchHome() {
const response = await fetch("http://localhost:8000/home")
const data = await response.json()
this.banners = data.data.banner
}
}
})
export default useHomeStores
<template>
<div class="home">
<h2>
Home View
</h2>
<ul>
<li v-for="item in banners">
<img :src="item">
</li>
</ul>
</div>
</template>
<script setup>
import useHomeStores from "@/stores/home"
import {storeToRefs} from "pinia"
const useHomeStore = useHomeStores()
const {banners} = storeToRefs(useHomeStore)
useHomeStore.fetchHomeMultidata().then(res=> {
console.log("请求完成",res)
})
</script>