一、Pinia和Vuex的对比
什么是Pinia呢?
Pinia开始于2019年,最初作为一个实验为Vue重新设计状态管理,让它用起来像 组合式API(Composition API)
从那时到现在,最初的设计原则依然相同,并且同时兼容Vue2 Vue3 也不要求你使用 Composition API
Pinia本质上 依然是一个 状态管理的库 用于 跨组件 页面进行状态共享(和Vuex Redux一样)
Pina和Vuex的区别
pinia最初是为了探索Vuex的下一次迭代会是什么样的,结合了Vuex5核心团队讨论中的许多想法
最终,团队意识到Pinia已经实现了Vuex5中大部分内容,所以决定用Pinia来替代Vuex
与Vuex比,Pinia提供了一个 更简单的API 具有更少的仪式,提供了CompositionAPI风格的API
最重要的是,与TypeScript一起使用时具有可靠的类型推断支持;
和Vuex相比,Pinia有很多的优势:
如:mutation不再存在:
经常被认为是 非常冗长; 最初带来了devtools集成,但这不再是问题.
更友好的TypeScript支持,Vuex之前对TS的支持不是很友好
不再有modules的嵌套结构:
可以灵活使用每一个store,是通过扁平化的方式来相互使用的
不再有命名空间的概念,不需要记住它们的复杂关系
如何使用Pinia
安装Pinia
JavaScript yarn add pinia // or with npm npm i pinia
创建一个pinia并且将其传递给应用程序:
JavaScript import { createPinia } from 'pinia' const pinia = createPinia() export default pinia
JavaScript // main.js文件中定义 import pinia from './stores/index' createApp(App).use(pinia).mount('#app')
二、创建Pinia的Store
认识Store
什么是Store?
一个Store(如pinia)是一个实体,它会持有为绑定到你组件树的状态和业务逻辑,也就是保存了全局的状态;
有点像始终存在,并且 每个人都可以读取和写入的组件
可以在你的应用程序中 定义任意数量的Store来管理你的状态
Store有三个核心概念:
State getters actions
等同于组件的 data computed methods
一旦store被实例化,就可以直接在store上访问state getters 和 actions中定义的任何属性
定义一个Store
定义一个Store:
需要知道Store是使用defineStore()定义的
并且需要一个唯一名称,作为第一个参数传递
JavaScript import { defineStore } from 'pinia' // defineStore 本身的返回值是一个函数 // 习惯用useXXX来命名 => 规范 const useCounter = defineStore("counter",{ state:()=> ({ count:999 }) }) export default useCounter
这个name,也称为id 是必要的的,Pinia使用它来将store连接到devtools
返回的函数统一使用useXXX作为命名方案,这是约定的规范
使用定义的Store
Store在它被使用之前是不会创建的,可以通过调用use函数来使用Store
JavaScript <template> <div class="home"> <h2>Home view</h2> <h2>count: {{ counterStore.count }}</h2> </div> </template> <script setup> import useCounter from '@/stores/counter'; const counterStore = useCounter() </script> <style scoped> </style>
注意Store获取到后不能被解构,不然会失去响应式!
为了从Store中提取属性同时保持其响应式 需要使用storeToRefs()
三、Pinia核心概念 State
认识和定义State
state是store的核心部分,因为store是用来帮助我们管理状态的
在Pinia中,状态被定义为返回初始状态的函数
操作State(一)
读取和写入state:
默认情况下,可以通过store实例访问状态来直接读取和写入状态
JavaScript const counterStore = useCounter() counterStore.count++ counterStore.name = "xiong"
重置State:
可以通过调用store上的$reset()方法将状态 重置 到其初始值;
JavaScript const counterStore = useCounter() counterStore.$reset()
操作State(二)
改变State:
除了直接使用store.counter++修改store,还可以调用$patch方法
它允许你使用部分"state"对象 同时应用多个更改
JavaScript function changeStateClick(){ // 1 一个一个修改状态 // userStore.name = "xiaoxiong" // userStore.age = 18 // userStore.level = 9999 // 2 一次性修改多个状态 userStore.$patch({ name:"xx", age:20 }) }
替换State:
可以通过将其$state属性设置为新对象来替换Store的整个状态
JavaScript counterStore.$state = { counter:1, name:"xxiong" }
四、Pinia核心概念 Getters
认识和定义Getters
Getters相当于Store的计算属性:
可以用defineStore()中的getters属性定义
getters中可以定义接受一个state作为参数的函数
JavaScript const useCounter = defineStore("counter",{ state:()=> ({ count:999, friends:[ { id:1,name:"xiong" }, { id:2,name:"xx" }, { id:3,name:"xxiong" }, ] }), getters:{ // 1 基本使用 doubleCount(state){ return state.count * 2 }, // 2 一个getter引入另外一个getter doubleCountAddOne(){ // 通过this访问 this绑定store实例 return this.doubleCount + 1 }, // 3 getters也支持返回一个函数 getFriendById(state){ return function(id) { // 高阶js写法 return state.friends.find(item => item.id === id ) // 普通写法 // for(let i = 0;i<state.friends.length;i++){ // const friend = state.friends[i] // if(friend.id === id){ // return friend // } // } } }, // 4 getters中使用到别的store中的数据 showMsg(state){ // 展示 count 和 user内的信息 // 在上面 导入 user包 // 1 获取user信息 const useStore = useUser() // 2 获取自己信息 state // 3 拼接信息 return `name:${useStore.name}-count:${state.count}` } } })
访问Getters(一)
访问当前Store的Getters:
JavaScript <h2>doubleCount: {{ countStore.doubleCount }}</h2> <h2>doubleCountAddOne: {{ countStore.doubleCountAddOne }}</h2> <h2>friend-2: {{ countStore.getFriendById(2) }}</h2> <h2>拼接counter里面的count和user里面的名字: showMsg:{{ countStore.showMsg }}</h2>
Getters中访问自己的其他Getters:
可以通过 this来访问到当前store实例的所有其他属性:
JavaScript doubleCountAddOne(){ // 通过this访问 this绑定store实例 return this.doubleCount + 1 },
访问其他store的Getters:
JavaScript // 4 getters中使用到别的store中的数据 showMsg(state){ // 展示 count 和 user内的信息 // 在上面 导入 user包 // 1 获取user信息 const useStore = useUser() // 2 获取自己信息 state // 3 拼接信息 return `name:${useStore.name}-count:${state.count}` }
访问Getters(二)
Getters也可以返回一个函数
JavaScript // 3 getters也支持返回一个函数 getFriendById(state){ return function(id) { // 高阶js写法 return state.friends.find(item => item.id === id ) // 普通写法 // for(let i = 0;i<state.friends.length;i++){ // const friend = state.friends[i] // if(friend.id === id){ // return friend // } // } } },
五、Pinia核心概念 Actions
认识和定义Actions
Actions相当于组件中的methods
使用defineStore()中的actions属性定义,且它们非常适合业务逻辑
和getters一样,在actions中可以通过this访问整个store实例的所有操作;
JavaScript actions:{ // 用来定义方法,这里不会给我们传进来一个state, // 他用来传递参数 increment() { this.count++ }, // 如:下示例 incrementAdd(num){ this.count += num } }
Actions执行异步操作
Actions中是支持异步操作的,我们可以编写异步函数,在函数中使用await
JavaScript actions:{ async fetchHomeMultidata(){ const res = await fetch("http://xxxx:8000/home/") const data = await res.json() // console.log(data) // 拿到数据 this.banners = data.data.banner.list this.recommends = data.data.recommend.list } }