Vue3-Pinia(大菠萝)附源码

文章目录

更多相关内容可查看

Pinia 开源地址

git地址:https://gitee.com/its-a-little-bad/vue.git

pinia官网地址:https://pinia.vuejs.org/zh/

node版本:20.8.1

Pinia 定义与起源

定义 :Pinia 是 Vue 的存储库,允许跨组件/页面共享状态。它实际上可以被视为 Vuex 的升级版,但为了尊重原作者,所以命名为 Pinia 而不是 Vuex。
起源:Pinia 是 Vue 3 官方推荐的状态管理库,旨在提供一个更加简单和灵活的 API,同时保留 Vuex 的主要功能。

优点与特性

  • 简化流程:Pinia 抛弃了 Vuex 中的 Mutation,这意味着你可以直接更新状态,无需再注册
    Commit,从而简化了状态管理流程。
  • 支持Vue 2和Vue 3:Pinia 同时支持 Vue 2 和 Vue 3,这使得开发者在迁移项目或同时使用不同版本的 Vue
    时能够更加灵活。
  • TypeScript 支持:Pinia 提供了出色的 TypeScript
    支持,允许开发者在编写代码时获得类型提示和自动补全,提高了代码的质量和可维护性。
  • 灵活的状态组织:与 Vuex 中的模块不同,Pinia 允许开发者自由地组织和管理状态,使得在大型应用中管理状态变得更加灵活和方便。
  • 与 Vue 3 的组合式 API 无缝集成:Pinia 能够与 Vue 3 的组合式 API 无缝集成,使得状态管理代码更加清晰和模块化。
  • 轻量级:Pinia 的体积非常小,只有大约1KB左右,这对于需要优化项目大小的应用程序来说是一个优势。
  • 支持插件:Pinia 支持插件来扩展自身功能,为开发者提供了更多的灵活性和可定制性。

Pinia使用

准备一个小模块(可参考以下程序)

js 复制代码
<template>
  <div class="Count"></div>
  <h2>当前求和为{{sum}}</h2>
  <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="sub">减</button>
</template>

<script>
export default {
    name:'Count'

}
</script>

<script setup>
import { ref } from 'vue';
let sum = ref(0)
let n = ref(1)
function add(){
    sum.value += n.value
}
function sub(){
    sum.value -= n.value
}

</script>

<style>
.select,button{
    margin:0 5px;
    height:40px;
}

</style>
js 复制代码
<template>
  <button @click="getMseeage">获取</button>
  <ul>
    <li v-for="talk in talkList" :key="talk.id">{{ talk.title }}</li>
  </ul>
</template>

<script>
export default {
    name:'LoveTalk'
}
</script>

<script setup>
import { idText } from 'typescript';
import { reactive } from 'vue';
import axios from 'axios';
import {nanoid} from 'nanoid'
let talkList = reactive([
    {id:1,title:'aaa'},
    {id:2,title:'bbb'},
    {id:3,title:'ccc'},
])

async function getMseeage(){
    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>

</style>

搭建 pinia 环境

第一步:npm install pinia

第二步:操作src/main.ts

typescript 复制代码
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是一个保存:状态业务逻辑 的实体,每个组件都可以读取写入它。
  2. 它有三个概念:stategetteraction,相当于组件中的: datacomputedmethods
  3. 具体编码:src/store/count.ts
typescript 复制代码
// 引入defineStore用于创建store
import {defineStore} from 'pinia'

// 定义并暴露一个store
export const useCountStore = defineStore('count',{
  // 动作
  actions:{},
  // 状态
  state(){
    return {
      sum:6
    }
  },
  // 计算
  getters:{}
})
  1. 具体编码:src/store/talk.ts
javascript 复制代码
// 引入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:{}
})
  1. 组件中使用state中的数据
js 复制代码
<template>
  <h2>当前求和为:{{ sumStore.sum }}</h2>
</template>

<script setup lang="ts" name="Count">
  // 引入对应的useXxxxxStore	
  import {useSumStore} from '@/store/sum'
  
  // 调用useXxxxxStore得到对应的store
  const sumStore = useSumStore()
</script>
js 复制代码
<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>

修改数据(三种方式)

  1. 第一种修改方式,直接修改
typescript 复制代码
countStore.sum = 666
  1. 第二种修改方式:批量修改
typescript 复制代码
countStore.$patch({
  sum:999,
  school:'twl'
})
  1. 第三种修改方式:借助action修改(action中可以编写一些业务逻辑)
javascript 复制代码
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
      }
    }
  },
})
  1. 组件中调用action即可
javascript 复制代码
// 使用countStore
const countStore = useCountStore()

// 调用对应action
countStore.incrementOdd(n.value)

storeToRefs

  • 借助storeToRefsstore中的数据转为ref对象,方便在模板中使用。
  • 注意:pinia提供的storeToRefs只会将数据做转换,而VuetoRefs会转换store中数据。
js 复制代码
<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配置。
  2. 追加getters配置。
javascript 复制代码
// 引入defineStore用于创建store
import {defineStore} from 'pinia'

// 定义并暴露一个store
export const useCountStore = defineStore('count',{
  // 动作
  actions:{
    /************/
  },
  // 状态
  state(){
    return {
      sum:1,
      school:'twl'
    }
  },
  // 计算
  getters:{
    bigSum:(state):number => state.sum *10,
    upperSchool():string{
      return this. school.toUpperCase()
    }
  }
})
  1. 组件中读取数据:
javascript 复制代码
const {increment,decrement} = countStore
let {sum,school,bigSum,upperSchool} = storeToRefs(countStore)

$subscribe

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

typescript 复制代码
talkStore.$subscribe((mutate,state)=>{
  console.log('LoveTalk',mutate,state)
  localStorage.setItem('talk',JSON.stringify(talkList.value))
})

store组合式写法

typescript 复制代码
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}
})
相关推荐
RaidenLiu3 分钟前
告别陷阱:精通Flutter Signals的生命周期、高级API与调试之道
前端·flutter·前端框架
非凡ghost3 分钟前
HWiNFO(专业系统信息检测工具)
前端·javascript·后端
非凡ghost5 分钟前
FireAlpaca(免费数字绘图软件)
前端·javascript·后端
非凡ghost12 分钟前
Sucrose Wallpaper Engine(动态壁纸管理工具)
前端·javascript·后端
拉不动的猪13 分钟前
为什么不建议项目里用延时器作为规定时间内的业务操作
前端·javascript·vue.js
该用户已不存在20 分钟前
Gemini CLI 扩展,把Nano Banana 搬到终端
前端·后端·ai编程
地方地方22 分钟前
前端踩坑记:解决图片与 Div 换行间隙的隐藏元凶
前端·javascript
jason_yang26 分钟前
vue3+element-plus按需自动导入-正确姿势
vue.js·vite·element
小猫由里香27 分钟前
小程序打开文件(文件流、地址链接)封装
前端
Tzarevich31 分钟前
使用n8n工作流自动化生成每日科技新闻速览:告别信息过载,拥抱智能阅读
前端