Vue3学习03 pinia

pinia

在vue2中使用vuex,在vue3中使用pinia。

集中式状态管理,(状态=数据)。多个组件共享数据的时候使用。

一个简单效果

在这里插入图片描述

  • Count.vue

注意事项①select中的数字限制 v-model.number ② ref响应式数据 要加value

<template>
  <div class="count">
    <h1>当前求和为:{{ sum }}</h1>
    <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="minus"></button>
  </div>
</template>

<script setup lang="ts" name="Count">
  import {ref} from 'vue'
  let sum = ref(0)
  let n = ref(1) // 用户选择的数字

  // 方法
  function add(){
    sum.value += n.value
  }
  function minus(){
    sum.value -= n.value
  }
</script>

<style>
.count {
  background-color: skyblue;
  padding: 10px;
  padding: 10px;
  border-radius: 10px;
}
select,button {
  margin-left: 10px;
}
</style>
  • LoveTalk.vue

注意事项 ① axios的 async await写法,② reactive监测数组的变化(unshift),③ 连续解构赋值+重命名

<template>
  <div class="talk">
    <button @click="getLoveTalk">获取一句土味情话</button>
    <ul>
      <li v-for="talk in talkList" :key="talk.id">{{talk.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:'ftrfasdf01',title:'今天你有点怪,哪里怪?怪好看的!'},
    {id:'ftrfasdf02',title:'草莓、蓝莓、蔓越莓,今天想我了没?'},
    {id:'ftrfasdf03',title:'心里给你留了一块地,我的死心塌地'}
  ])
  // 方法
  async function getLoveTalk(){
    // 发请求,下面这行的写法是:连续解构赋值+重命名
    let {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;
  }
</style>
  • App.vue
<template>
  <Count></Count>
  <hr>
  <LoveTalk></LoveTalk>
</template>

<script lang="ts" setup name="App">
  import Count from './components/Count.vue';
  import LoveTalk from './components/LoveTalk.vue';

</script>

搭建 pinia 环境

第一步:npm install pinia

第二步:操作src/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')

在这里插入图片描述

此时开发者工具中已经有了pinia选项

在这里插入图片描述

存储+读取数据

  1. Store是一个保存:状态业务逻辑 的实体,每个组件都可以读取写入它。(/src/store/xxx.ts)

  2. 它有三个概念:stategetteraction,相当于组件中的: datacomputedmethods

  3. 具体编码:src/store/count.ts

    // 引入defineStore用于创建store
    import {defineStore} from 'pinia'
    
    // 定义并暴露一个store
    export const useCountStore = defineStore('count',{
      // 动作
      actions:{},
      // 状态
      state(){
        return {
          sum:6
        }
      },
      // 计算
      getters:{}
    })
    
  4. 具体编码:src/store/talk.ts

    // 引入defineStore用于创建store
    import {defineStore} from 'pinia'
    
    // 定义并暴露一个store
    export const useTalkStore = defineStore('talk',{
      // 动作
      actions:{},
      // 状态
      state(){
        return {
          talkList:[
            {id:'yuysada01',content:'你今天有点怪,哪里怪?怪好看的!'},
         	{id:'yuysada02',content:'草莓、蓝莓、蔓越莓,你想我了没?'},
            {id:'yuysada03',content:'心里给你留了一块地,我的死心塌地'}
          ]
        }
      },
      // 计算
      getters:{}
    })
    
  5. 组件中使用state中的数据

    <template>
      <h2>当前求和为:{{ sumStore.sum }}</h2>
    </template>
    
    <script setup lang="ts" name="Count">
      // 引入对应的useXxxxxStore	
      import {useSumStore} from '@/store/sum'
      
      // 调用useXxxxxStore得到对应的store
      const sumStore = useSumStore()
    </script>
    
    <template>
    	<ul>
        <li v-for="talk in talkStore.talkList" :key="talk.id">
          {{ talk.content }}
        </li>
      </ul>
    </template>
    
    <script setup lang="ts" name="Count">
      import axios from 'axios'
      import {useTalkStore} from '@/store/talk'
    
      const talkStore = useTalkStore()
    </script>
    

示例

我想让 count.vue中的sum变量、Lovetalk.vue中的talkList变成共有的

① npm i pinia

② 创建store文件夹,store可以理解为 使用pinia的实体。里面对应组件创建ts文件

image-20240410170520601

count.ts

import {defineStore} from 'pinia'

// useCountStore和hooks命名方法一致
export const useCountStore = defineStore('count', {
  // 真正存储数据的地方
  state(){ 状态(数据)
    return {
      sum :6
    }
  } 
})

loveTalk.ts

import {defineStore} from 'pinia'

// useCountStore和hooks命名方法一致
export const useTalkStore = defineStore('talk', {
  // 真正存储数据的地方
  state(){ 状态(数据)
    return {
      talkList: [
        {id:'ftrfasdf01',title:'今天你有点怪,哪里怪?怪好看的!'},
        {id:'ftrfasdf02',title:'草莓、蓝莓、蔓越莓,今天想我了没?'},
        {id:'ftrfasdf03',title:'心里给你留了一块地,我的死心塌地'}
      ]
    }
  } 
})

③ 在组件中使用 store里的数据

count.vue

<template>
  <div class="count">
    <h1>当前求和为:{{ countStore.sum }}</h1>
  </div>
</template>

<script setup lang="ts" name="Count">
  // let sum = ref(0)

  import { useCountStore } from '@/store/count';
  const countStore = useCountStore()
  //console.log(countStore);
    
  // 以下两种方式都可以拿到state中的 数据
  //console.log(countStore.sum);
  //console.log(countStore.$state.sum);
</script>

拿到 store 中的数据:

  import { useCountStore } from '@/store/count';
  const countStore = useCountStore()

打印countStore:
在这里插入图片描述

修改数据 (三种方式)

import { useCountStore } from '@/store/count';
const countStore = useCountStore()
  1. 第一种修改方式,直接修改

    countStore.sum = 666
    
  2. 第二种修改方式:批量修改

    countStore.$patch({
      sum:999,
      school:'atguigu'
    })
    
  3. 第三种修改方式:借助action修改(action中可以编写一些业务逻辑)

    底层维护了一个this。

    import { defineStore } from 'pinia'
    
    export const useCountStore = defineStore('count', {
      /*************/
      actions: {
        //加
        increment(value:number) {
          if (this.sum < 10) {
            //操作countStore中的sum
            this.sum += value
          }
        },
        //减
        decrement(value:number){
          if(this.sum > 1){
            this.sum -= value
          }
        }
      },
      /*************/
    })
    

    组件中调用action即可

    // 使用countStore
    const countStore = useCountStore()
    
    // 调用对应action
    countStore.incrementOdd(n.value)
    

storeToRefs

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

注意:pinia提供的storeToRefs只会将数据做转换,不会对方法进行包裹。而VuetoRefs会转换store中数据。

<template>
	<div class="count">
		<h2>当前求和为:{{sum}}</h2>
	</div>
</template>

<script setup lang="ts" name="Count">
  import { useCountStore } from '@/store/count'
  /* 引入storeToRefs */
  import { storeToRefs } from 'pinia'

	/* 得到countStore */
  const countStore = useCountStore()
  /* 使用storeToRefs转换countStore,随后解构 */
  const {sum} = storeToRefs(countStore)
</script>

getters

  1. 概念:当state中的数据,需要经过处理后再使用时,可以使用getters配置。类似computed

    getters 中维护的this也是store

  2. 追加getters配置。

    // 引入defineStore用于创建store
    import {defineStore} from 'pinia'
    
    // 定义并暴露一个store
    export const useCountStore = defineStore('count',{
      // 动作
      actions:{
        /************/
      },
      // 状态
      state(){
        return {
          sum:1,
          school:'atguigu'
        }
      },
      // 计算
      getters:{
        bigSum: state => state.sum *10,
        upperSchool():string{
          return this.school.toUpperCase()
        }
      }
    })
    
  3. 组件中读取数据:

    const {increment,decrement} = countStore
    let {sum,school,bigSum,upperSchool} = storeToRefs(countStore)
    

$subscribe

通过 store 的 $subscribe() 方法侦听 state 及其变化

  • LoveTalk.vue
import { useTalkStore } from '@/store/count';
const talkList = useTalkStore()

talkStore.$subscribe((mutate,state)=>{
  // console.log('talkStore发生变化');
  console.log('LoveTalk',mutate,state)
  localStorage.setItem('talk',JSON.stringify(talkList.value))
})
  • loveTalk.ts
export const useTalkStore = defineStore('talk', {
  state(){ 
    return {
        // 断言+空数组
      talkList: JSON.parse(localStorage.getItem('talk') as string)||[]
    }
  }
  ...
})

store组合式写法

  • 之前是选项式
import {defineStore} from 'pinia'
import axios from "axios";
import {nanoid} from 'nanoid'

// defineStore('名字',{配置对象})
export const useTalkStore = defineStore('talk', {
  state(){ 
    return {
      talkList: JSON.parse(localStorage.getItem('talk') as string)||[]
    }
  },
  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)
    }
  },
  getters:{

  }
})
  • 组合式写法(注意defineStore的第二项变为函数,需要返回值)

    ① state数据直接用 reactive/ref

    ② actions里面的函数配置,写为function函数

    ③ 没有this了

import {defineStore} from 'pinia'
import axios from 'axios'
import {nanoid} from 'nanoid'
import {reactive} from 'vue'

export const useTalkStore = defineStore('talk',()=>{
  // talkList就是state
  const talkList = reactive(
    JSON.parse(localStorage.getItem('talkList') as string) || []
  )

  // getATalk函数相当于action
  async function getATalk(){
    // 发请求,下面这行的写法是:连续解构赋值+重命名
    let {data:{content:title}} = await axios.get('https://api.uomg.com/api/rand.qinghua?format=json')
    // 把请求回来的字符串,包装成一个对象
    let obj = {id:nanoid(),title}
    // 放到数组中
    talkList.unshift(obj)
  }
   
  return {talkList,getATalk}
})
  • count.ts
import {ref} from 'vue'
export const useCountStore = defineStore('count',()=>{
  let sum = ref(6)

  function increment(value:number) {
    if (sum.value < 10) {
      //操作countStore中的sum
      sum.value += value
    }
  }
  //减
  function decrement(value:number){
    if(sum.value > 1){
      sum.value -= value
    }
  }

  return {sum,increment,decrement}
})

相关推荐

  1. Vue3 基础知识》Pinia 02 之 项目中从 VuexPinia

    2024-04-12 08:10:03       8 阅读
  2. vue3-Pinia

    2024-04-12 08:10:03       25 阅读
  3. vue3Pinia

    2024-04-12 08:10:03       16 阅读
  4. Vue3 基础知识》Pinia 01 之 基础

    2024-04-12 08:10:03       11 阅读
  5. Vue3Pinia状态管理库学习笔记

    2024-04-12 08:10:03       21 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-04-12 08:10:03       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-04-12 08:10:03       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-04-12 08:10:03       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-04-12 08:10:03       20 阅读

热门阅读

  1. CIrcuits--Sequential--Finite_1

    2024-04-12 08:10:03       12 阅读
  2. Thinkphp下载图片至压缩包

    2024-04-12 08:10:03       14 阅读
  3. netty实现mqtt(IOT)

    2024-04-12 08:10:03       15 阅读
  4. MySQL数据库——5、创建数据表

    2024-04-12 08:10:03       9 阅读
  5. python如何学习数据分析

    2024-04-12 08:10:03       14 阅读