pinia使用
安装和引入
- 在使用
pinia
时需要将模块下载并且需要引入
下载pinia
# yarn
yarn add pinia
# 或 npm
npm i -D pinia
引入pinia
方式一:在main.ts
中
- 在
main.ts
中引用
const app = createApp(App);
// 引入pinia
import { createPinia } from "pinia";
// 初始化pinia
const pinia = createPinia();
app.use(pinia);
方式二:定义 文件导出
- 方式二看得会稍微简洁些,但是官方写法是方式一中的,可以根据自己的需求来选择
// 引入pinia
import { createPinia } from "pinia";
// 初始化pinia
const pinia = createPinia();
// 导出pinia
export default pinia;
- 导出后在
main.ts
中再去引用
import pinia from "@/store/index";
app.use(pinia);
效果也是一样的
定义和使用store
定义
- 需要定义的名字一定要为唯一的,否则会有冲突
- 后面的花括号中就是一些其它数据选项,如果想把后面对象单独拎出来,后面要想修改数据会用到
this
,正是如此不建议单独拎出来。 - 如果单独拿出来此时的
this
指向就变了
import { defineStore } from 'pinia'
export const useStore = defineStore('需要定义的名字', {
// 其它的一些数据选项
})
使用sore
- 如果使用,需要定义数据之类的,和在vuex中类似,语法形式像vue2
state的定义
- 在vuex中会看到state,在vuex中state后面直接跟着花括号即可,但是在pinia中需要写成函数式,在官方中推荐使用箭头函数,因为有利于推断类型
- 在这种定义的
user
,需要在state中返回一个对象
import { defineStore } from "pinia";
export const userStore = defineStore("user", {
state: () => {
return {
count: 0,
age: 18,
};
},
});
- 使用函数式原因
- 使用return 防止数据污染
- 推荐使用箭头函数,因为可以更好的类型推理
修改state值
- 修改state值就需要用到
actions
,这时就不用像state再去写函数式了,直接写成对象即可,如下所示 - 直接使用
this
之后点出state中的值,之后在对其进行需要的操作
import { defineStore } from "pinia";
export const userStore = defineStore("user", {
// 状态值
state: () => {
return {
count: 0,
age: 18,
};
},
// 修改值
actions: {
// 修改age
getAge() {
this.age++;
},
},
});
这就是为什么在上面所说不要单独拎出来后面的对象,否则this的指向也会改变
getters计算属性
- 在vuex中也会有
getters
属于计算属性,如果不了解可以参考vue中的computed
属性和其类似 - 写法和
action
差不多,注意后面是花括号不是函数,并且要把处理好的数据返回出去!!!
import { defineStore } from "pinia";
export const userStore = defineStore("user", {
state: () => {
return {
count: 0,
age: 18,
};
},
// 相当于compute的 计算属性
getters: {
getterAge(state: any) {
return `仓库中的${state.age + 5}`;
},
},
actions: {
// 修改age
getAge() {
this.age++;
},
// 修改count
getCount() {
this.count++;
},
},
});
在组件中使用
- 和vuex不同的是,pinia很多都是响应式,只要改了仓库中的数据也会发生改变,除了结构时会有个坑,但是只要外边包个函数即可解决这个问题
不解构方式使用
- 使用值方式有很多种,下面说三种全都是响应式的,十分的简单
- 在下面代码中就已经获取到了仓库中的数据
import { userStore } from "@/store/user"; // 引入仓库
const store = userStore();// 使用
// 状态
const State = reactive({
age: computed(() => store.age),
});
const store = userStore();// 使用
注意是函数,不是直接解构出来就可以用的
组件使用
- 值的使用
- 可以使用
reactive
的方式去使用 - 也可以直接用
store.xxx
的方式去使用 - 也可以在
reactive
中使用计算属性去使用
- 可以使用
- 函数的使用—和值使用的方式一样,需要去要点击事件等,直接调用即可,根据自己的需求
<template>
<h1>pinia使用</h1>
<h4>有计算属性的age:{{ State.age }}</h4>
<h4>没有计算属性的age:{{ store.age }}</h4>
<h4>仓库中计算属性的age:----{{ store.getterAge }}</h4>
<h4>结构出来的的age:----{{ age }}</h4>
<h4>结构出来的的count:----{{ count }}</h4>
<button @click="store.getAge()">点击增加-age</button>
<button @click="store.getCount()">点击增加-count</button>
<button @click="HandelFun.changeAge">在组件中直接修改age</button>
</template>
解构方式使用
- 在结构时如果解构的是state中的数据,会出现不是响应式的问题,如果状态修改并不会引起值的更新,这时候需要映入
storeToRefs
如下所示
import { storeToRefs } from "pinia"; // 解决结构后值不是响应式
- 之后只需要将仓库数据用这个包起来就行了
// 如果这样写是不会有响应式的,但是可以把函数结构出来可以用,只是不会是响应式的
const { age, count } = userStore();
// 通过这种方式可以将数据结构但是不能结构出函数,数据是响应式的
const { age, count } = storeToRefs(userStore());
在组件函数中使用
- 直接调用即可
const HandelFun = reactive({
// 在组件中直接修改age也是响应式的
changeAge() {
store.age++;
},
});
直接在组件中修改
- 在组件中直接修改当前仓库中的值也是可以的,效果也是响应式的
批量修改
方式一
- 如果相对仓库中状态的值想做多个修改,可以使用
$patch
,使用方式如下
store.$patch({
age: 100,
count: 100,
});
- 如果仓库中当前需要修改的值没有,但是还是加上了,例如下面这样,没有
name
和list
store.$patch({
age: 100,
count: 100,
name: "哈哈哈哈",
list: [1, 2, 3, 4, 5, 6],
});
如果仓库中没有上面两个值,但是有需要加上,直接修改再去state中找是没有的
<!-- 修改多个值 --> <h2>{{ store.age }}</h2> <h2>{{ store.count }}</h2> <h2 v-if="store.$state.name">{{ store.$state.name }}</h2> <h2 v-if="store.$state.list">{{ store.$state.list }}</h2> <button @click="HandelFun.changeState">修改多个值</button>
需要使用
store.$state.xxx
方式二
- 可以直接使用
$patch
的箭头函数形式去做
changeState2() {
console.log(store);
store.$patch((state: any) => {
state.name = "方式二修改";
state.age = 888;
state.count = 888;
state.list = [6, 6, 6, 6, 6];
});
},
getters高阶函数
- 如果想对getters进行传参,需要使用到高阶函数,不要忘记一定要return
getterAge(state) {
return (data: number) => {
if (data) state.age = data;
else {
`仓库中的${state.age + 5}`;
}
};
},
- 在组件中需要对函数进行传值
<!-- 对getters中进行传参该怎么做 -->
<h2>{{ store.age }}</h2>
<button @click="store.getterAge(10)">对getters传参</button>
actions处理异步请求
- 需要安装
axios
store中
actions: {
// 模拟获取数据
async getApi() {
const result = await axios.get("https://api.apiopen.top/api/sentences");
this.getApiObj = result.data.result;
return result.data.result;
},
},
点按钮取数据
<h2>模拟获取数据</h2>
<h3>诗名:{{ store.getApiObj.from }}</h3>
<h3>诗句:{{ store.getApiObj.name }}</h3>
<button @click="store.getApi">获取数据</button>