vue3(四)、Pinia(集中式数据管理,类似于Vue2的vuex)


Vue2用vuex,Vue3用pinia进行集中式状态(数据)管理。就是组件共用的数据交给pinia管理,组件自用的数据自己管理就好。

一、搭建pinia环境并准备案例

  1. 安装:npm i pinia
  2. 引入创建并安装
    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")
    
  3. 案例包括两个组件: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呢。

  1. 如果是自己定义的ref对象,读取数据则需要.value
  2. 如果是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));

在这里插入图片描述

总结:

  • 借助storeToRefsstore中的数据转为ref对象,方便在模板中使用。

四、getters

  1. 添加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(){...}
  1. 组件使用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))
})

在这里插入图片描述
将数据存储起来可实现页面刷新不丢失数据。
在这里插入图片描述

七、组合式写法

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值