1.Pinia介绍

Pinia 是 Vue 的专属的最新状态管理库 ,是 Vuex 状态管理工具的替代品

Pinia优势:
1.提供了封建简单的API(去掉了 mutation)
2.提供符合这是风格的API(和 Vue3 新语法统一)
3.去掉了 modules 的概念,每一个 store 都是一个独立的模块
4.配合 TypeScript 更加友好,提供可靠类型推断

2.手动添加Pinia到Vue项目

在以后的项目开发中,并不需要手动添加,这里只是介绍全流程

创建 vue 项目

npm create vue@latest

在这里插入图片描述

项目初始化完成,可执行以下命令:

cd vue3-pinia-demo
npm install
npm run dev

创建成功,然后清理创建好的模板

  • 删除src 下的 assets 和 components
  • main.js 中删除import ‘./assets/main.css’
  • app.vue 中删除 script 中代码 ,清空 template 代码 ,删除 style 标签内的代码
<script setup>
</script>

<template>
<div>
  <h1>App.vue 根组件</h1>
</div>
</template>

<style scoped>
</style>

创建两个组件,方便模拟 pinia 的使用

按照官方文档安装 pinia 到项目中:
pinia 开始官方文档

下载 pinia

npm install pinia

创建实例写入 main.js

import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'

const pinia = createPinia()
const app = createApp(App)

app.use(pinia)
app.mount('#app')

3.Pinia基础使用

1.定义store
2.组件使用store

3.1 定义store

这里用和 Vue3 语法风格更接近的Setup Store定义仓库

在 src 下面创建 store 文件夹,store 文件下创建 js 文件定义仓库
在这里插入图片描述

基本结构:

//导入定义仓库的包
import { defineStore } from 'pinia'
//导入定义数据的包
import {ref} from 'vue'

//定义 store
//define(仓库唯一标识,()=>{...})

defineStore('counter',()=>{
    //声明数据 state-count

    //声明数据操作的方法 action

    //声明基于数据派生的计算属性 getters


})

完整结构:

//导入定义仓库的包
import { defineStore } from 'pinia'
//导入定义数据的包
import {ref} from 'vue'

//定义 store
//defineStore(仓库唯一标识,()=>{...})
//defineStore返回的是函数,用一个函数名接收,方便后续的使用

 export const useCounterStore= defineStore('counter',()=>{

    //声明数据 state-count
    const count=ref(0)
    //声明数据 state-msg
    const msg=ref('hello pinia')

    //声明数据操作的方法 action

    //声明基于数据派生的计算属性 getters

    return{
        count,
        msg
    }

})

3.2 组件使用store

到 app.vue页面使用数据

  • 导包
  • 定义接收
  • 使用
<script setup>
import Son1Com from './components/son1.vue'
import Son2Com from './components/son2.vue'

// 1.导包
import {useCounterStore} from './store/counter'
// 2.定义 接收
const counterStore=useCounterStore()

</script>

<template>
<div>
  <!-- 使用 -->
  <h1>App.vue 根组件
    -{{ counterStore.count }}
    -{{ counterStore.msg }}
  </h1>
  <Son1Com></Son1Com>
  <Son2Com></Son2Com>
</div>
</template>

<style scoped>
</style>

在这里插入图片描述

在其他组件使用的过程中,使用也同理

使用数据操作的方法-action

  • 定义操作方法
  • return出去
export const useCounterStore= defineStore('counter',()=>{

    //声明数据 state-count
    const count=ref(0)
    //声明数据 state-msg
    const msg=ref('hello pinia')

    //声明数据操作的方法 action
    const addCount =()=>{
        count.value++
    }
      const subCount =()=>{
        count.value--
    }


    //声明基于数据派生的计算属性 getters

    return{
        count,
        msg,
        addCount,
        subCount
    }

})

son1 和 son2 中拿这两个方法

在这里插入图片描述

使用 getters(计算属性)
在这里插入图片描述

在这里插入图片描述

3.3 action异步实现

方式:异步action函数的写法和组件中获取异步数据的写法完全一致

  • 接口地址:http://geek.itheima.net/v1_0/channels

  • 请求方式:get

  • 请求参数:无


使用 axios 接收数据,先下载 axios 的包,并且导入进去

接收数据

//声明数据操作的方法 
const getList=async()=>{
 //支持异步
const {data:{data}}=await axios.get('http://geek.itheima.net/v1_0/channels')
} 

讲解一下这种写法:
await axios.get(…)

  • 这是通过 axios 发送 GET 请求
  • await 表示等待它返回结果(是一个 Promise)
  • 返回结构如下(假设返回成功)
data:{data}拿的 response.data.data
虽然接口数据是这样的,但是 axios 本身就会封装一个 data,所以拿的是 data.data
{
  "data": {
    "channels": [
      {
        "id": 0,
        "name": "推荐"
      },

不用解构的写法的等价写法

const getList = async () => {
  const res = await axios.get('http://geek.itheima.net/v1_0/channels')
  const channelList = res.data.data
  console.log(channelList)
}

完整写法,查看数据是否接收到
在这里插入图片描述

在这里插入图片描述

渲染列表:

 <button @click="ChannelStore.getList">获取频道数据</button>
 <ul>
    <li v-for="item in ChannelStore.channelList" :key="item.id">{{ item.name }}</li>
  </ul>

在这里插入图片描述

3.4 storeToRefs()

//错误写法 直接解构 会让数据失去响应式
const {count,msg}=counterStore

//正确写法
import {storeToRefs} from 'pinia'

const {count,msg}=storeToRefs(counterStore)

解释说明:

为什么在 pinia 中,不能直接解构,而要用storeToRefs()?
inia 的 state 是响应式对象(reactive),直接解构会失去响应性
Pinia 的 store 是一个包含了响应式对象的 Proxy,但当你做 const { count } = store,你只是把 .value 拿出来了,相当于“脱壳”了

3.5 数据持久化

使用持久化插件,默认存储在 local storage 中

官方文档:https://prazdevs.github.io/pinia-plugin-persistedstate/zh/

补充知识

localStorage 的生命周期

  • 永久存储(除非主动删除)。
  • 浏览器关闭、电脑重启都不会消失。
  • 只有在下面几种情况才会消失:
  • 用户手动清除浏览器缓存/存储。
  • 用户用代码调用 localStorage.removeItem(key) 或 localStorage.clear()。
  • 浏览器运行在某些“隐身/无痕模式”下,可能在会话结束时清空。
  • 👉 所以我们一般说 localStorage 生命周期 = 永久,直到被清除为止。

1.安装插件 pinia-plugin-persistedstate

npm i pinia-plugin-persistedstate

2.main.js 中将持久化插件加入到 pinia 中

import { createPinia } from 'pinia'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'

const pinia = createPinia()
pinia.use(piniaPluginPersistedstate)

这里的重点是把piniaPluginPersistedstate加入到pinia中,核心代码是pinia.use(piniaPluginPersistedstate),在已经有 pinia 的情况下

3.配置 store/counter.js

import { defineStore } from 'pinia'
import { ref } from 'vue'

export const useStore = defineStore(
  'main',
  () => {
    const someState = ref('hello pinia')
    return { someState }
  },
  {
    persist: true,
  },
)

演示:

演示中,只展示开启全部数据永久化和修改存储的数据名称,其他的配置都在官方文档的配置中,如修改部分数据永久化等

开启全部数据永久化
counter.js 代码如下:

//导入定义仓库的包
import { defineStore } from 'pinia'
//导入定义数据的包
import {ref} from 'vue'

//导入computed
import {computed} from 'vue'



//定义 store
//defineStore(仓库唯一标识,()=>{...})
//defineStore返回的是函数,用一个函数名接收,方便后续的使用

 export const useCounterStore= defineStore('counter',()=>{

    //声明数据 state-count
    const count=ref(0)
    //声明数据 state-msg
    const msg=ref('hello pinia')

    //声明数据操作的方法 action
    const addCount =()=>{
        count.value++
    }
      const subCount =()=>{
        count.value--
    }
    //声明基于数据派生的计算属性 getters
     const double =computed(()=>count.value*2)

    return{
        count,
        msg,
        addCount,
        subCount,
        double,
    }
},{
    persist: true
}
)

在这里插入图片描述

将存储的数据 key 修改:
官方配置文档中:
在这里插入图片描述

,{
    persist: true
}该写成
,{
    persist: 
    {
    key:'mydata'
    }
}

在这里插入图片描述

更多推荐