课程地址: VUE新一代状态管理工具Pinia超详细基础入门
贴两个链接:
vue3官方文档
pinia官方文档
P1 《pinia的简介》
不得不说“开卷有益,学有所获”,前两天自己找pinia的官方文档好像也没找对,原来在vue3官方生态系统里有pinia官网入口,不学习真是不知道!
pinia简介看文档:
pinia可以用来创建一个仓库,里面可以存储一些多个组件都需要使用的数据;如果数据是从后端接口获取的,也可以由仓库去发送请求接口数据,然后存储在仓库,使用数据的组件都可以从仓库获取数据:
P2 《创建vue3项目并安装pinia》
使用以下命令创建vue项目,选择选项时我们先不自动安装pinia,之后手动安装:
npm init vue@latese
安装pinia:
运行并打开项目:
安装完成后查看package.json文件,可以看到pinia的版本:
在项目中引入并安装pinia:
import { createPinia } from 'pinia'
const pinia = createPinia()
app.use(pinia)
(下图红框语句第二个红框框错了,应该框下一行即第9行,懒得改啦)
如果是vue2,则需要如下操作:
store承载着全局状态,每个组件都可以从store读取和存入状态,store包括三个概念:state、getter、action。其中,state相当于组件中的data,getter相当于组件中的computed,action则相当于组件中的methods。
P3《定义Option store》
pinia中,可以使用 createStore() 方法创建多个store,比如a、b、c三个store数据,组件中都可以去引入这些数据:
用 defineStore() 方法 来定义一个store,第一个参数是这个store的名字,相当于id。
摘自文档:
同时,对于 defineStore() 方法的返回值,你可以任意命名defineStore()
的返回值,但最好使用 store 的名字,同时以use
开头且以Store
结尾。 (比如useUserStore
,useCartStore
,useProductStore
)
第一个参数是你的应用中 Store 的唯一 ID。
defineStore()的第二个参数可以是setup函数或Option对象,先来看下Option对象的情况:
项目中src目录下新建stores目录,在其中新建index.js文件,在其中定义一个store数据:
P3《定义setup store以及使用store》
这一节看一下 defineStore() 的第二个参数的setup形式:
在index.js文件中再用setup形式定义另一个store:
注意:defineStore() 方法执行后返回的是一个函数,也即 useAgeStore、useCounterStore 都是一个函数。
在组件中使用store数据:
将定义的store函数引入并执行,打印出来观察:发现它是一个Proxy对象,其上面有我们定义的属性(state、getter)和方法(action):
在模板中使用store数据与方法:
如果将store实例上的属性和方法解构出来,会发现页面展示正常,但点击按钮时数据不会改变,说明此时数据已经丧失了响应性:
总结一下就是:store实例上的数据不能直接解构出来,需要使用 storeToRefs 来解构,这样才不会丧失响应性:
但需要注意,storeToRefs 不能解构actions 方法;actions 方法直接解构就可以(亲测如果用storeToRefs 将action方法解构出来,点击执行该方法无效):
P5《pinia核心概念-State的基本使用》
pinia的核心概念有3个:store、getters、actions
关于state:既可以直接返回一个对象,也可以返回一个箭头函数,函数中返回一个对象,这种函数的形式主要是为了服务端渲染时防止数据污染。这里要区别vuex中的state直接返回一个对象,pinia中的state尽量都写成返回函数,函数中返回一个对象的形式。
修改store中的状态值:
假如store中有多个状态值,可以使用 store实例的 $patch(对象参数) 方法来修改,其中,未修改的状态值不会受到影响:
假如state中还有数组类型的数据:
但这种针对数组的修改方式不够优雅,且当对数组进行从中间删除某些元素或插入某些元素时,也不方便操作,这时来看下 $patch() 的第二种使用方式,即 $patch(函数) 的形式,这种方式是强烈推荐的方式:
总结,修改state中的数据的方式有4种,分别是:
const changeState = ()=>{
// 方法一:直接修改
ageStore.name = 'sy888'
ageStore.age = 28
ageStore.list.push(4,5,6)
// 方法二:使用 $patch(对象)
ageStore.$patch({
name:'sy888',
age:28,
list:[...ageStore.list, 4,5,6]
})
// 方法三:使用 $patch(函数) —— 强烈推荐使用此种方法
ageStore.$patch((state)=>{
state.name = 'sy888'
state.age = 28
state.list.splice(2,1,8)
})
// 方法四:使用actions中封装好的方法
}
P6《pinia核心概念-Getter的基本使用》
1、getter的第一个知识点:在其中使用this,this指向store实例。
但使用this的方式,无法获取ts的类型推断:
使用 state 作为 函数参数的形式,可以获得ts的类型推断:
2、getter的第二个知识点:访问同一个store中的其它getter值:直接通过this获取其它getter,先写成箭头函数的形式试一试看行不行呢?
发现报错:
原因就是在这里使用了箭头函数,箭头函数中的this不再是state对象,而是undefined(亲测打印为undefined):
改为普通函数的形式,就可以成功了:
3、getter的第三个知识点:向getter传递参数
在模板中这样使用:调用函数的形式使用并传递参数:
4、getter的第四个知识点:一个store使用另一个store中的getter数据:直接通过执行另一个store的方法获取另一个store的实例,通过这个实例就可以直接拿到其getter数据:
P7《pinia核心概念-Action的基本使用》
在actions中定义一个方法,在其中调用接口获取数据:
在页面中触发这个action时,可以获取到数据:
在一个store中使用另一个store中的action:
在counter的store中增加一个login的action:
在 age 的 store 中获取到counter 的 store的实例,并使用其定义的action:
pinia的action与vuex的action的不同是:pinia的action既可以处理同步操作,也可以处理异步操作。
P8《pinia和vuex的比较》
总结 pinia 与 vuex 的不同: