文章目录
Vue2用vuex,Vue3用pinia进行集中式状态(数据)管理。就是组件共用的数据交给pinia管理,组件自用的数据自己管理就好。
一、搭建pinia环境并准备案例
- 安装:
npm i pinia
- 引入创建并安装
import { createApp } from "vue" import App from "./App.vue" // 1. 引入pinia import { createPinia } from "pinia" const app = createApp(App) // 2. 创建pinia const pinia = createPinia() // 3. 使用pinia app.use(pinia) // 挂载整个应用到app容器中 app.mount("#app")
- 案例包括两个组件:
Count.vue
,LoveTalk.vue
LoveTalk.vue
:页面结构就是循环遍历+按钮
import { reactive } from 'vue'
import axios from "axios";
import { nanoid } from 'nanoid'
// 数据
let talkList = reactive([
{ id: 'ftrfasdf01', title: '今天你有点怪,哪里怪?怪好看的!' },
{ id: 'ftrfasdf02', title: '草莓、蓝莓、蔓越莓,今天想我了没?' },
{ id: 'ftrfasdf03', title: '心里给你留了一块地,我的死心塌地' }
])
// 方法
async function getLoveTalk() {
// 发请求,下面这行的写法是:连续解构赋值+重命名; 将content重命名为title
let { data: { content: title } } = await axios.get('https://api.uomg.com/api/rand.qinghua?format=json')
// 把请求回来的字符串,包装成一个对象,kv一致,简写
// let obj = { id: nanoid(), title:title }
let obj = { id: nanoid(), title }
// 放到数组中
talkList.unshift(obj)
}
二、pinia存储并读取数据
1. 存储数据
state是函数(Vuex中是对象):state(){return{...}}
创建src/store/count.ts
,存储Count组件的数据:
import { defineStore } from "pinia";
export const useCountStore = defineStore('count',{
// 真正存储数据的地方
state(){
return{
sum:6
}
}
})
创建src/store/loveTalk.ts
,存储LoveTalk组件的数据:
import {defineStore} from 'pinia'
export const useTalkStore = defineStore('talk',{
// 真正存储数据的地方
state(){
return {
talkList:[
{id:'ftrfasdf01',title:'今天你有点怪,哪里怪?怪好看的!'},
{id:'ftrfasdf02',title:'草莓、蓝莓、蔓越莓,今天想我了没?'},
{id:'ftrfasdf03',title:'心里给你留了一块地,我的死心塌地'}
]
}
}
})
2. 读取数据
Count组件(LoveTalk组件也类似,不多赘述)
打印countStore
:
countStore
是一个Proxy实例对象,而sum
是一个RefImpl对象,为什么读取数据时不用sum.value
呢。
- 如果是自己定义的ref对象,读取数据则需要
.value
- 如果是reactive里包裹了一个ref,则会自动拆包,不需要
.value
let obj = reactive({
a: 1,
b: 2,
c: ref(3)
})
console.log(obj.a);
console.log(obj.b);
console.log(obj.c);
let x = ref(9)
console.log(x.value);
三、修改store数据的三种方式
以Count
组件里的加
为例。
1. 修改一个变量
function add() {
countStore.sum += n.value
// 第二种:适合批量修改
countStore.$patch({
sum: 888,
name: 'jerry',
age: 10
})
}
2. 适合批量修改多个变量
$patch
function add() {
countStore.$patch({
sum: 888,
name: 'jerry',
age: 10
})
}
3. 需要在仓库里配置actions
actions方法的使用
function add() {
// 第三种:actions
countStore.increment(n.value)
}
当方法逻辑比较复杂时,更适合用actions
方式修改数据。比如修改订单信息,好几个组件都有这个功能,写到actions
里可以实现代码的复用,提高效率。
也就是公用的方法写在action
里面。
四、storeToRefs
countstore
是一个Proxy实例对象,对其解构赋值,得到的不是响应式数据。
<template>
<div class="count">
<h2>当前求和为:{{ sum }}</h2>
<h3>姓名:{{ name }},年龄{{ age }}</h3>
<h3>姓名:{{ upperName }},求和10倍{{ bigSum }}</h3>
</div>
</template>
<script setup lang="ts" name="Count">
// 这样解构得到的不是响应式数据,即使仓库里的数据发生变化,页面也不会改变
let { sum, name, age } = toRefs(countStore)
</script>
storeToRefs,只会对state里的数据进行包裹
import { storeToRefs } from "pinia";
let { sum, name, age } = storeToRefs(countStore)
consoloe.log(storeToRefs(countStore))
若采用toRefs,则countStore里的所有数据都被改为RefImpl类型
console.log(toRefs(countStore));
总结:
- 借助
storeToRefs
将store
中的数据转为ref
对象,方便在模板中使用。
四、getters
- 添加getters配置项,
store/count.ts
getters:{
// 1. 借助state
bigSum(state){
return state.sum*10
},
// 2. 借助this :string是ts语法检查,表示返回的是string类型的数据
upperName():string{
console.log('@@@',this)
// 这里的this指的是store
return this.name.toUpperCase()
}
},
state(){...}
- 组件使用getter数据
let { sum, name, age, bigSum, upperName } = storeToRefs(countStore)
五、actions方法
将LoveTalk.vue
里的 getLoveTalk()
方法提到actions
里。
loveTalk.ts
:
actions:{
async getATalk() {
// 发请求,下面这行的写法是:连续解构赋值+重命名; 将content重命名为title
let { data: { content: title } } = await axios.get('https://api.uomg.com/api/rand.qinghua?format=json')
// 把请求回来的字符串,包装成一个对象,kv一致,简写
// let obj = { id: nanoid(), title:title }
let obj = { id: nanoid(), title }
// 放到数组中
this.talkList.unshift(obj)
}
}
组件中使用方法:
<script setup lang="ts" name="LoveTalk">
import { useTalkStore } from '@/store/loveTalk'
// 数据
const talkStore = useTalkStore()
// 点击按钮触发getLoveTalk,进而调用actions里的方法,修改state数据talkList
function getLoveTalk() {
talkStore.getATalk()
}
</script>
六、$subscribe
$subscribe((mutate,state)=>{...})
:监听store的变化,参数mutate一般不用。
组件:LoveTalk.vue
// state里包含数据talkList
talkStore.$subscribe((mutate, state) => {
console.log('talkStore数据发生了变化',state);
localStorage.setItem('talkList', JSON.stringify(state.talkList))
})
将数据存储起来可实现页面刷新不丢失数据。