目录
1. 搭建 Pinia 环境
1.1 准备一个效果
1.2 搭建 pinia
2. 存储+读取数据
2.1 存储数据
2.1 组件中读取数据
3. 修改数据
3.1 直接修改
3.2 批量修改
3.3 借助 actions 修改
4. storeToRefs
5. getters
6. $subscribe
7. 总结
Pinia 是一个用于 Vue 3 的状态管理库,类似于 vue2 中的 vuex,
Pinia 不像 Vuex 那样有严格的规则(如必须使用 mutations 来修改状态),这使得代码更加灵活。
1. 搭建 Pinia 环境
1.1 准备一个效果
Sum.vue 组件
<template><div class="sum"><h2>当前求和为{{ sum }}</h2><div class="btn"><select v-model.number="n"><option value="1">1</option><option value="2">2</option><option value="3">3</option></select><button @click="add">加</button><button @click="subtract">减</button></div></div>
</template><script setup lang="ts">
import { ref } from 'vue'
let sum = ref(0);
let n = ref(1);function add() {sum.value += n.value;
}function subtract() {sum.value -= n.value;
}
</script><style>
.sum {width: 400px;height: 100px;background: skyblue;border-radius: 10px;padding: 10px;
}
.btn {display: flex;gap: 20px;
}
</style>
LoveTalk 组件
<template><div class="love-talk"><button @click="getTalk">获取一句土味情话</button><ul><li v-for="item in list" :key="item.id">{{item.content}}</li></ul></div>
</template><script setup lang="ts">
import { ref } from 'vue'
import axios from 'axios'
import { nanoid } from 'nanoid'
import { useTalkStore} from '@/store/talk'let talkStore = useTalkStore()
let list = ref([{id:1,content:'今天你有点怪,哪里怪?怪好看的'},{id:2,content:'草莓、蓝莓、蔓越莓,今天想我了没'},{id:3,content:'心里给你留了一块地,我的死心踏地'},
])async function getTalk() {let result = await axios.get('https://api.uomg.com/api/rand.qinghua')let obj = {id:nanoid(),content:result.data.content}list.value.unshift(obj);console.log(list.value)
}
</script><style>
.love-talk{width: 500px;height: auto;padding: 20px;background-color: salmon;border-radius: 10px;box-shadow: 0 0 10px rgba(0,0,0,.1);margin-top: 30px;
}
</style>
App.vue 组件
<template><div class="app"><h2 class="title">pinia测试效果</h2><Sum /><LoveTalk /></div>
</template><script lang="ts" setup name="App">
import Sum from '@/components/Sum.vue'
import LoveTalk from './components/LoveTalk.vue';
</script>
1.2 搭建 pinia
下载pinia
npm install pinia
main.ts 注册pinia
import { createApp } from 'vue'import App from './App.vue'
// 引入createPinia,用于创建 piniaimport { createPinia } from 'pinia';// 创建piniaconst pinia = createPinia();const app = createApp(App);// 将pinia挂载到app上app.use(pinia)app.mount('#app')
此时开发者工具上已经有了 pinia 选项 ↓ ↓ ↓
2. 存储+读取数据
(1). Store 是一个保存:状态、业务逻辑的实体,每个组件都可以读取、写入它。
(2). 它有三个概念:state、getter、action,相当于组件中的: data、 computed 和 methods。
2.1 存储数据
在由于这个例子有两部分数据,一个是求和数据,一个是土味情话列表数据,所以在这里我们分开存储。
在 src 目录下新建 store目录,在此目录下新建 count.ts 和 talk.ts,用于存储公共数据。
counts.ts
// 引入defineStore 用于创建store
import { defineStore } from "pinia";// 定义并暴露一个store
export const useCountStore = defineStore("count", {actions:{},state(){return {sum:1}},
})
talk.ts
import { defineStore } from "pinia";export const useTalkStore = defineStore("talk",{state(){return {list:[{id:1,content:'今天你有点怪,哪里怪?怪好看的de'},{id:2,content:'草莓、蓝莓、蔓越莓,今天想我了没'},{id:3,content:'心里给你留了一块地,我的死心踏地'},]}},
})
2.1 组件中读取数据
将从 store 中读取到的数据在页面进行展示。
Sum.vue组件
<template><div class="sum"><h2>当前求和为{{ countStore.sum }}</h2><div class="btn"><select v-model.number="n"><option value="1">1</option><option value="2">2</option><option value="3">3</option></select><button @click="add">加</button><button @click="subtract">减</button></div></div>
</template><script setup lang="ts">
import { ref } from 'vue'
import { useCountStore } from '@/store/count';
const countStore = useCountStore();
console.log(countStore.sum);
let n = ref(1);
function add() {}function subtract() {}
</script><style>
.sum {width: 400px;height: 100px;background: skyblue;border-radius: 10px;padding: 10px;
}
.btn {display: flex;gap: 20px;
}
</style>
LoveTalk.vue组件
<template><div class="love-talk"><button >获取一句土味情话</button><ul><li v-for="item in talkStore.list" :key="item.id">{{item.content}}</li></ul></div>
</template><script setup lang="ts">import { useTalkStore} from '@/store/talk'let talkStore = useTalkStore()
</script><style>
.love-talk{width: 500px;height: auto;padding: 20px;background-color: salmon;border-radius: 10px;box-shadow: 0 0 10px rgba(0,0,0,.1);margin-top: 30px;
}
</style>
可以看到页面正常展示求和数目和土味情话列表 ↓ ↓ ↓
3. 修改数据
3.1 直接修改
举例:利用Sum.vue组件中获取到的 countStore,直接修改 store 中存储的数据。
Sum.vue组件
<template><div class="sum"><h2>当前求和为{{ countStore.sum }}</h2><div class="btn"><select v-model.number="n"><option value="1">1</option><option value="2">2</option><option value="3">3</option></select><button @click="add">加</button><button @click="subtract">减</button></div></div>
</template><script setup lang="ts">
import { ref } from 'vue'
import { useCountStore } from '@/store/count';
const countStore = useCountStore();
console.log(countStore.sum);
let n = ref(1);
function add() {countStore.sum++;
}
function subtract() {}
</script><style>
.sum {width: 400px;height: 100px;background: skyblue;border-radius: 10px;padding: 10px;
}
.btn {display: flex;gap: 20px;
}
</style>
效果如下 ↓ ↓ ↓
3.2 批量修改
如果 store 中存储了多个数据,可以通过 $patch 来进行批量修改。
/store/count.ts
// 引入defineStore 用于创建store
import { defineStore } from "pinia";// 定义并暴露一个store
export const useCountStore = defineStore("count", {actions:{},state(){return {sum:1,name:'神圣兽国游尾郡窝窝乡独行族妖侠,蛮吉'}},
})
Sum.vue
<template><div class="sum"><h2>当前求和为{{ countStore.sum }}</h2><h2>地址:{{ countStore.name }}</h2><div class="btn"><select v-model.number="n"><option value="1">1</option><option value="2">2</option><option value="3">3</option></select><button @click="add">加</button><button @click="subtract">减</button></div></div>
</template><script setup lang="ts">
import { ref } from 'vue'
import { useCountStore } from '@/store/count';
const countStore = useCountStore();
console.log(countStore.sum);
let n = ref(1);
function add() {countStore.$patch({sum: 99,name:'灵山军中部战区指挥官基思卡人奇衡三'})
}
function subtract() {}
</script><style>
.sum {width: 550px;height: 200px;background: skyblue;border-radius: 10px;padding: 10px;
}
.btn {display: flex;gap: 20px;
}
</style>
效果如下 ↓ ↓ ↓
3.3 借助 actions 修改
/store/count.ts
// 引入defineStore 用于创建store
import { defineStore } from "pinia";// 定义并暴露一个store
export const useCountStore = defineStore("count", {actions:{//加add(value:number) {if (this.sum < 10) {//操作countStore中的sumthis.sum += value}},//减subtract(value:number){if(this.sum > 1){this.sum -= value}}},state(){return {sum:1,}},
})
然后 Sum.vue 组件中调用 store 中 actions 中的方法即可
Sum.vuez组件
<template><div class="sum"><h2>当前求和为{{ countStore.sum }}</h2><div class="btn"><select v-model.number="n"><option value="1">1</option><option value="2">2</option><option value="3">3</option></select><button @click="add">加</button><button @click="subtract">减</button></div></div>
</template><script setup lang="ts">
import { ref } from 'vue'
import { useCountStore } from '@/store/count';
const countStore = useCountStore();
console.log(countStore.sum);
let n = ref(1);function add() {countStore.add(n.value)
}
function subtract() {countStore.subtract(n.value)
}
</script><style>
.sum {width: 550px;height: 200px;background: skyblue;border-radius: 10px;padding: 10px;
}
.btn {display: flex;gap: 20px;
}
</style>
效果如下 ↓ ↓ ↓
4. storeToRefs
借助 storeToRefs 将 store 中的数据转为 ref 对象,方便在模板中使用。因为在结构式,数据会丢失响应式,所以需要用storeToRefs。但有人会问了,那我为什么不用 toRefs 呢
那是因为 pinia 提供的 storeToRefs 只会将数据做转换,而 Vue 的 toRefs 除了数据会转换,连store中的actions中的方法都会转换。
Sum.vue组件
<template><div class="sum"><h2>当前求和为{{ sum }}</h2><div class="btn"><select v-model.number="n"><option value="1">1</option><option value="2">2</option><option value="3">3</option></select><button @click="add">加</button><button @click="subtract">减</button></div></div>
</template><script setup lang="ts">
import { ref } from 'vue'
import { useCountStore } from '@/store/count';
import { storeToRefs } from 'pinia'
const countStore = useCountStore();
const { sum } = storeToRefs(countStore);
let n = ref(1);function add() {countStore.add(n.value)
}
function subtract() {countStore.subtract(n.value)
}
</script><style>
.sum {width: 550px;height: 200px;background: skyblue;border-radius: 10px;padding: 10px;
}
.btn {display: flex;gap: 20px;
}
</style>
5. getters
概念:当 state 中的数据,需要经过处理后再使用时,可以使用 getters 配置。
这里不过多赘述。
6. $subscribe
通过 store 的 $subscribe() 方法侦听 state 及其变化,和 watch 相似。
在Sum.vue组件中演示。
Sum.vue组件
<template><div class="sum"><h2>当前求和为{{ sum }}</h2><div class="btn"><select v-model.number="n"><option value="1">1</option><option value="2">2</option><option value="3">3</option></select><button @click="add">加</button><button @click="subtract">减</button></div></div>
</template><script setup lang="ts">
import { ref } from 'vue'
import { useCountStore } from '@/store/count';
import { storeToRefs } from 'pinia'
const countStore = useCountStore();
const { sum } = storeToRefs(countStore);
let n = ref(1);countStore.$subscribe((mutate,state)=>{console.log('countStore中数据发生了变化',state);
})
function add() {countStore.add(n.value)
}
function subtract() {countStore.subtract(n.value)
}
</script><style>
.sum {width: 550px;height: 200px;background: skyblue;border-radius: 10px;padding: 10px;
}
.btn {display: flex;gap: 20px;
}
</style>
效果如下图所示,当 state 中的数据变化时,$subscribe 可以检测到
7. 总结
以上就是 pinia的部分内容演示。包含了如何搭建 pinia、数据存储与读取、数据i修改、以及pinia提供的 storeToRefs、getters、$subscribe等等。
更多与Vue3相关的内容请点击下方链接查看 ↓ ↓ ↓
Vue3入门到实战_借来一夜星光的博客-CSDN博客