之前做vue3项目遇到,现有时间记录一下。
概述
Pinia本质上依然是一个状态管理的库,用于跨组件、页面进行状态共享(这点和Vuex、Redux一样)。
和vuex对比
- mutations不再存在
- 更友好的TypeScript支持
- 不再有modules的嵌套结构,可以灵活使用每一个store,它们是通过扁平化的方式来相互使用的
- 不再有命名空间的概念,不需要记住它们的复杂关系
基本配置
- 安装
npm i pinia
或者
yarn add pinia
- 创建一个pinia
- 新建store文件,并新建一个index.js文件
import { createPinia } from 'pinia' //创建一个pinia实例 const pinia = createPinia() export default pinia
- 在main.js中use
这样就配置完成了import { createApp } from 'vue' import App from './App.vue' import pinia from './stores' createApp(App).use(pinia).mount('#app')
基本使用
-
如何定义一个store
- store是使用defineStore()定义的
- 唯一名称,作为参数传递,作用是将store连接到devtools。
- 返回函数统一使用usex作为命名方案。
具体案例
//定义一个counter.js,在里面定义一个store
// 定义关于counter的store import { defineStore } from 'pinia' const useCounter = defineStore("counter", { // 在 Pinia 中,状态被定义为返回初始状态的函数 state: () => ({ count: 99 }) }) export default useCounter //命名规范
//使用store读取和写入state
<template> <div class="home"> <h2>Home View</h2> <h2>count: {{ counterStore.count }}</h2> <h2>count: {{ count }}</h2> </div> </template> <script setup> import useCounter from '@/stores/counter'; import { storeToRefs } from 'pinia' // 1.直接使用useCounter获取counter这个Store的实例 // 这个函数名称取决于defineStore的返回值 const counterStore = useCounter() // 使用storeToRefs对数据进行结构,让count保持响应式的效果 const { count } = storeToRefs(counterStore) // 3.修改(写入)store counterStore.count++ </script>
- getters的使用
- Getters相当于Store的计算属性
- 它可以用defineStore()中的getters属性定义;
- getters中可以定义接受一个state作为参数的函数;
- 基本使用
- 定义
// 定义关于counter的store import { defineStore } from 'pinia' const useCounter = defineStore("counter", { state: () => ({ count: 99 }), getters: { // 基本使用 doubleCount(state) { return state.count * 2 }, // 2.一个getter引入另外一个getter doubleCountAddOne() { // this是store实例,可以直接使用另一个getter 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 } } } }, }, }) export default useCounter
- 访问
<template> <div class="home"> <!-- 在模板中使用 --> <h2>doubleCount: {{ counterStore.doubleCount }}</h2> <h2>doubleCountAddOne: {{ counterStore.doubleCountAddOne }}</h2> <h2>friend-111: {{ counterStore.getFriendById(111) }}</h2> </div> </template> <script setup> import useCounter from '@/stores/counter'; const counterStore = useCounter() // 在js文件中使用 const doubleCount = counterStore.doubleCount; const doubleCountAddOne = counterStore.doubleCountAddOne; const frend = counterStore.getFriendById(111) </script>
- actions的使用
- actions 相当于组件中的 methods
- 在action中可以通过this访问整个store实例的所有操作
- 基本定义方式
// 定义关于counter的store import { defineStore } from 'pinia' const useCounter = defineStore("counter", { state: () => ({ count: 99, }), // 定义actions actions: { increment() { this.count++ }, incrementNum(num) { this.count += num } } }) export default useCounter
- 基本使用方式
<template> <div class="home"> <h2>doubleCount: {{ counterStore.count }}</h2> <button @click="changeState">修改state</button> </div> </template> <script setup> import useCounter from '@/stores/counter'; const counterStore = useCounter() function changeState() { // 可以通过counterStore对象直接使用 // counterStore.increment() counterStore.incrementNum(10) } </script>
- 基本使用方式
<template> <div class="home"> <h2>doubleCount: {{ counterStore.count }}</h2> <button @click="changeState">修改state</button> </div> </template> <script setup> import useCounter from '@/stores/counter'; const counterStore = useCounter() function changeState() { // 可以通过counterStore对象直接使用 // counterStore.increment() counterStore.incrementNum(10) } </script>
- 异步操作
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() //得到数据后直接复制给state this.banners = data.data.banner.list this.recommends = data.data.recommend.list return 'success' } } }) export default useHome