Vue3 使用 pinia
什么是Pinia
Pinia是 Vue 的存储库,它允许您跨组件/页面共享状态,与vuex功能一样。
准备
安装
npm install pinia
或者
yarn add pinia
使用
首先修改main.ts文件
main.ts
import './assets/main.css'import { createApp } from 'vue'
import App from './App.vue'
import { createPinia } from 'pinia'const app = createApp(App)
const pinia = createPinia()
// 使用pinia
app.use(pinia)
// 挂载到 #app
app.mount('#app')
现在若有多个组件要使用count组件中的 count 值 和 LoveTalk 组件中的 talkList 值,可使用 Pinia 将这些值存储到一个文件里,使用时直接导入提取即可。
首先在 src 文件夹下创建 store 文件夹用于存放相关ts文件,然后创建useCountStore.ts 和 useTalkListStore.ts文件。
useCountStore.ts
import { defineStore } from "pinia";export const useCountStore = defineStore("count", {actions:{increment(value: number){if (this.count < 10){this.count += value;}}},state(){return {count: 0,school:'atguigu',address:'宏福科技园'}},
});
useTalkListStore
import axios from "axios";
import { nanoid } from "nanoid";
import { defineStore } from "pinia";export const useTalkListStore = defineStore("talkList", {actions:{async getATalk(){let {data:{content:title}} = await axios.get('https://api.uomg.com/api/rand.qinghua?format=json');let obj = {id: nanoid(), title}this.talkList.unshift(obj);}},state(){return {talkList: [{id:'ftrfasdf01',title:'今天你有点怪,哪里怪?怪好看的!'},{id:'ftrfasdf02',title:'草莓、蓝莓、蔓越莓,今天想我了没?'},{id:'ftrfasdf03',title:'心里给你留了一块地,我的死心塌地'}]}},
});
使用定义在store中的数据。
Count.vue
<script lang="ts" setup name="Count">import { ref } from 'vue';import { useCountStore } from '@/store/useCountStore';import { storeToRefs } from 'pinia';let countStore = useCountStore();let n = ref(1);let { count, address, school } = storeToRefs(countStore);function add() {//第一种修改数据方式// countStore.count += n.value;// countStore.address = '北京市海淀区';// countStore.school = '清华大学';//第二种修改数据方式// countStore.$patch({// count: countStore.count + n.value,// address: '北京市海淀区',// school: '清华大学'// });//第三种修改数据方式countStore.increment(n.value);}function minus() {}
</script><template><div class="count"><!-- <h1>Count: {{ countStore.count }}</h1><h2>地址: {{ countStore.address }}, 名称: {{ countStore.school }}</h2> --><h1>Count: {{ count }}</h1><h2>地址: {{ address }}, 名称: {{ school }}</h2><button @click="add">加</button><button @click="minus">减</button><select v-model.number="n"><option value="1">1</option><option value="2">2</option><option value="3">3</option></select></div>
</template><style scoped>.count {background-color: skyblue;padding: 10px;border-radius: 10px;box-shadow: 0 0 10px;}select,button {margin: 0 5px;height: 25px;}
</style>
LoveTalk.vue
<script lang="ts" setup name="LoveTalk">import axios from 'axios';import { reactive } from 'vue';import { nanoid } from 'nanoid';import { useTalkListStore } from '@/store/useTalkListStore';let talkListStore = useTalkListStore();function addTalk() {talkListStore.getATalk();}
</script><template><div class="talk"><h2>LoveTalk</h2><ul><li v-for="talk in talkListStore.talkList" :key="talk.id"> {{ talk.title }} </li></ul><button @click="addTalk">获取一条土味情话</button></div>
</template><style scoped>.talk {background-color: orange;padding: 10px;border-radius: 10px;box-shadow: 0 0 10px;}
</style>
上面两个组件实现了一个计数器和展示土味情话功能。Count组件中 select 标签中若不使用.number将字符串转化为数字,在点击 “加”按钮时会使用字符串拼接方式,例如选择2后,点击“加”后,数字就变成了字符串12。
实现效果
getters
useCountStore.ts
如果对 state 中的数据不满意,想要添加数据时,可以用getters方式,修改useCountStore.ts代码
import { defineStore } from "pinia";export const useCountStore = defineStore("count", {actions:{increment(value: number){if (this.count < 10){this.count += value;}},decrement(value: number){if (this.count > 0){this.count -= value;}}},state(){return {count: 0,school:'atguigu',address:'宏福科技园'}},// 通过 getters 添加新数据getters:{// 需要接受 state 作为参数bigSum(state){return state.count * 2;},smallSum: state => state.count - 1,upperSchool(state){return state.school.toUpperCase();}}
});
Count.vue
修改 Count.vue
<script lang="ts" setup name="Count">import { ref } from 'vue';import { useCountStore } from '@/store/useCountStore';import { storeToRefs } from 'pinia';let countStore = useCountStore();let n = ref(1);// 通过 storeToRefs 得到 getters 添加到的数据let { count, address, school, bigSum, smallSum, upperSchool } = storeToRefs(countStore);function add() {//第一种修改数据方式// countStore.count += n.value;// countStore.address = '北京市海淀区';// countStore.school = '清华大学';//第二种修改数据方式// countStore.$patch({// count: countStore.count + n.value,// address: '北京市海淀区',// school: '清华大学'// });//第三种修改数据方式countStore.increment(n.value);}function minus() {countStore.decrement(n.value);}
</script><template><div class="count"><!-- <h1>Count: {{ countStore.count }}</h1><h2>地址: {{ countStore.address }}, 名称: {{ countStore.school }}</h2> --><h1>Count: {{ count }}</h1><h2>地址: {{ address }}, 名称: {{ school }}</h2><h2>bigSum: {{ bigSum }}</h2><h2>smallSum: {{ smallSum }}</h2><h2>upperSchool: {{ upperSchool }}</h2><button @click="add">加</button><button @click="minus">减</button><select v-model.number="n"><option value="1">1</option><option value="2">2</option><option value="3">3</option></select></div>
</template><style scoped>.count {background-color: skyblue;padding: 10px;border-radius: 10px;box-shadow: 0 0 10px;}select,button {margin: 0 5px;height: 25px;}
</style>
实现效果
$subscribe
Vue中可以用watch来监听数据的变化
同理,Pinia的store中的数据发生变化,可以用$subscribe来监听
这一篇,$subscribe+localStorage实现数据存储的案例,来介绍这个API的功能
LoveTalk.vue
<script lang="ts" setup name="LoveTalk">import axios from 'axios';import { reactive } from 'vue';import { nanoid } from 'nanoid';import { useTalkListStore } from '@/store/useTalkListStore';let talkListStore = useTalkListStore();//这个API的作用,类似于Vue中的watch,监听store中的数据变化talkListStore.$subscribe((mutate, state) => {localStorage.setItem('talkList', JSON.stringify(state.talkList));})function addTalk() {talkListStore.getATalk();}
</script><template><div class="talk"><h2>LoveTalk</h2><ul><li v-for="talk in talkListStore.talkList" :key="talk.id"> {{ talk.title }} </li></ul><button @click="addTalk">获取一条土味情话</button></div>
</template><style scoped>.talk {background-color: orange;padding: 10px;border-radius: 10px;box-shadow: 0 0 10px;}
</style>
useTalkListStore.ts
import axios from "axios";
import { nanoid } from "nanoid";
import { defineStore } from "pinia";export const useTalkListStore = defineStore("talkList", {actions:{async getATalk(){let {data:{content:title}} = await axios.get('https://api.uomg.com/api/rand.qinghua?format=json');let obj = {id: nanoid(), title}this.talkList.unshift(obj);}},state(){return {talkList: JSON.parse(localStorage.getItem('talkList') as string || '[]')}},
});
原文地址:https://blog.csdn.net/weixin_46515691/article/details/142680624
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mrgr.cn/news/45653.html 如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mrgr.cn/news/45653.html 如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!