vue3pinia
文章目录
- 前言
- 1.定义
- 2.准备一个效果
- 3.构建pinia环境
- 4.存储与读取数据
- 5.修改数据
- 6.storeToRefs
- 7.getters方法
- 8.$subscribe
- 9.组合式写法
- 总结
前言
1.定义
- Pinia是Vue3的官方状态管理库,可以看作是Vuex的替代品,它提供了更简单的API,让所有组件都可以在里面读取数据并修改数据。
- 一句话:全局共享的数据。
2.准备一个效果
Count.vue
<template><div class="count"><h2>当前求和为:{{ sum }}</h2>// 1.双向绑定n值 .number是确定类型<select v-model.number="n"><!-- 双向绑定n值 默认为1 --><option value="1">1</option><option value="2">2</option><option value="3">3</option></select><button @click="add">加</button><button @click="minus">减</button></div>
</template><script setup lang="ts" name="Count">import { ref } from 'vue'let sum = ref(1)let n = ref(1)function add() {sum.value += n.value}function minus() {sum.value -= n.value}
</script><style scoped>.count {background-color: skyblue;padding: 10px;border-radius: 10px;box-shadow: 0 0 10px;}
</style>
LoveTalk.vue
<template><div class="talk"><button @click="getLoveTalk">获得一句土味情话</button><ul><li v-for="item in talkList" :key="item.id">{{ item.title }}</li></ul></div>
</template><script setup lang="ts" name="LoveTalk">import { reactive } from 'vue'import axios from 'axios'import { nanoid } from 'nanoid';let talkList = reactive([{id:'01',title:'哈哈哈哈'},{id:'02',title:'嘿嘿嘿嘿'},{id:'03',title:'噢噢噢噢'},])async function getLoveTalk() {// 1.使用axios发送get请求并解构返回的数据// 2.只能在async 函数中使用 await// 3.一层解构data// 二层从data中解构content并命名为titlelet {data:{content:title}} = await axios.get('https://api.uomg.com/api/rand.qinghua?format=json')let obj = {id:nanoid(),title}// 从列表开头添加元素talkList.unshift(obj)}
</script><style scoped>.talk {background-color: orange;padding: 10px;border-radius: 10px;box-shadow: 0 0 10px;}
</style>
App.vue
<template><Count/><LoveTalk/>>
</template><script lang="ts" setup name="App">import Count from './components/PiniaTest/Count.vue';import LoveTalk from './components/PiniaTest/LoveTalk.vue';
</script>
嵌套解构的等价写法:
let response = await axios.get('https://api.uomg.com/api/rand.qinghua?format=json')
let data = response.data
let title = data.content
3.构建pinia环境
- 1.下载pinia
npm i pinia
- 2.配置main.ts
import { createApp } from 'vue'
import App from './App.vue'/* 引入createPinia,用于创建pinia */
import { createPinia } from 'pinia'/* 创建pinia */
const pinia = createPinia()
const app = createApp(App)/* 使用插件 */
app.use(pinia)
app.mount('#app')
4.存储与读取数据
- 1.新创建store文件夹。
- 2.在store文件夹中定义xxx.ts,例如count.ts,表示将count组件的数据存入这个count.ts中。一一对应。
// 1.导入定义数据存储的包
import {defineStore} from 'pinia'
// 2.将这个存储的公共数据暴露出去
// 注意:需要写成state()函数的形式
// 'count'表示与文件名一致的名字
export const useCountStore = defineStore('count',{// 真正存储数据的地方state(){return {sum:6}}
})
- 3.使用store。
<template><div class="count">// 1.更改为countStore.sum<h2>当前求和为:{{ countStore.sum }}</h2><select v-model.number="n"><!-- 双向绑定n值 默认为1 --><option value="1">1</option><option value="2">2</option><option value="3">3</option></select><button @click="add">加</button><button @click="minus">减</button></div>
</template><script lang="ts">export default {name : "Count"}
</script>
<script setup lang="ts">import { ref } from 'vue'// 2.引入useCountStore包import { useCountStore } from '@/store/count';let sum = ref(1)let n = ref(1)// 3.使用useCountStore()const countStore = useCountStore()function add() {// 4.直接引用即可countStore.sum += n.value}function minus() {countStore.sum -= n.value}
</script><style scoped>.count {background-color: skyblue;padding: 10px;border-radius: 10px;box-shadow: 0 0 10px;}
</style>
- 5.为什么不需要.value:因为如果不是直接暴露在外层的ref数据,使用reactive,不管嵌套了ref还是reactive,都是直接调用。
let a = ref(1)
let b = reactive({'name':'jojo','age':19,'relation':{'love':'k'}
})
console.log(b.relation.love)
console.log(a.value)
5.修改数据
- 方式1:直接修改。
function add() {countStore.sum += 1
}
- 方式2:通过store.$patch({})碎片进行修改。
function add() {countStore.$patch({sum:sum+1})
}
- 方式3:通过actions进行修改。在store中使用this来访问其他数据。定义好actions后,在组件中通过store直接调用方法即可。
count.ts
import {defineStore} from 'pinia'
export const useCountStore = defineStore('count',{actions:{increment(v) {if(this.sum < 10){this.sum += v}}},state(){return {sum:6}}
})
Count.vue
function add() {countStore.increment(n.value)
}
小知识点:vue3中的$符号含义(超级精简版):看到$表示我们在使用vue3提供的功能,仅此而已。
6.storeToRefs
- 作用:在组件中直接解构store数据,看起来更美观,注意:我们可以使用toRefs,但是store里面的配置多,如果一股脑的使用toRefs开销比较大,所以我们使用它专属的storeToRefs。
const countStore = useCountStore()
count {sum, school, address} = storeToRefs(countStore)
7.getters方法
- 在store中,还可以对返回的结果数据进行再一次加工。
count.ts
import {defineStore} from 'pinia'
export const useCountStore = defineStore('count', {actions:{increment(v){if(this.v > 10){this.sum += v}}},store(){return {sum:6}},getters:{// 将state里面的sum扩大10倍 命名为bigSum并返回bigSum:state => state.sum * 10}
})
8.$subscribe
- 订阅store中的state的一种方法。
- 在浏览器刷新时仍然可以保存更新的数据。
Talk.vue
// $subscribe方法监听talkStore状态变化 在talkList更新时自动将其存入localStorage
talkStore.$subscribe((mutate, state)=>{
// mutate:包含变更的详细信息
// state:当前talkStore的最新状态
// 设置state里面的talkList这个列表存入浏览器内存并转换成人类看得懂的json字符串localStorage.setItem('talkList', JSON.stringify(state.talkList))
})
talk.ts
import {defineStore} from 'pinia'
export const useTalkListStore = defineStore('talkList', {// 真正存储数据的地方state() {return {talkList:JSON.parse(localStorage.getItem('talkList') as string || [])}}
})
9.组合式写法
talk.ts
import {reactive} from 'vue'
export const useTalkStore = defineStore('talk',()=>{// talkList就是stateconst talkList = reactive(JSON.parse(localStorage.getItem('talkList') as string) || [])// getTalk相当于actionsfunction getTalk(){console.log('获得一句话')}// 把state和actions返回return {talkList, getTalk}
})
总结
- pinia是用来管理组件公共属性的库,能够管理所有组件都能操作和访问的数据或动作,符合直觉的操作。