Vue从入门到实战Day12

一、Pinia快速入门

1. 什么是Pinia

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

1. 提供更加简单的API(去掉了mutation)

2. 提供符合组合式风格的API(和Vue3新语法统一)

3. 去掉了modules的概念,每一个store都是一个独立的模块

4. 配合TypeScript更加友好,提供可靠的类型推断

2. 手动添加Pinia到Vue项目

在实际开发项目的时候,关于Pinia的配置,可以在项目创建时自动添加

1. 使用Vite创建一个空的Vue3项目

npm create vue@latest

2. 按照官方文档安装Pinia到项目中

①安装Pinia

npm install pinia

②创建一个 pinia 实例 (根 store) 并将其传递给应用 - mian.js

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

const pinia = createPinia()  // 创建Pinia实例
const app = createApp(App)  // 创建根实例

app.use(pinia)  // pinia插件的安装配置
app.mount('#app')  // 视图的挂载

3. Pinia基础使用 - 计数器案例

1. 定义store

src/store/counter.js

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

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

export const useCounterStore =  defineStore('counter', () => {
    // 声明数据 - state
    const count = ref(6)
    // 声明操作数据的方法 - action(普通函数)
    const addCount = () => {
        count.value++
    }
    const subCount = () => count.value--

    // 声明基于数据派生的计算属性 - getters(computed)
    const double = computed(() => count.value * 2)

    // 声明数据 - state
    const msg = ref('hello Pinia')

    return {
        count, 
        addCount,
        subCount,
        double,
        msg
    }
})

2. 组件使用store

App.vue

<script setup>
import Son1Com from '@/components/Son1Com.vue'
import Son2Com from '@/components/Son2Com.vue'
import { useCounterStore } from '@/store/counter'

const counterStore = useCounterStore()
console.log(counterStore)
</script>

<template>
  <div>
    <h3>
      App.vue根组件
      - {{ counterStore.count }}
      - {{ counterStore.msg }}
    </h3>
    
    <Son1Com></Son1Com>
    <Son2Com></Son2Com>
  </div>
</template>

<style scoped>

</style>

src/components/Son1Com.vue

<script setup>
import { useCounterStore } from '@/store/counter'

const counterStore = useCounterStore()
</script>

<template>
  <div>
    我是Son1Com.vue 
    - {{ counterStore.count }}
    - {{ counterStore.double }}
    <button @click="counterStore.addCount">+</button>
  </div>
</template>

<style scoped>

</style>

src/components/Son2Com.vue

<script setup>
import { useCounterStore } from '@/store/counter'

const counterStore = useCounterStore()
</script>

<template>
  <div>
    我是Son2Com.vue
    - {{ counterStore.count }}
    <button @click="counterStore.subCount">-</button>
  </div>
</template>

<style scoped>

</style>

4. action异步实现

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

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

需求:在Pinia中获取频道列表数据并把数据渲染App组件的模板中

示例代码:

src/store/channel.js

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

export const useChannelStore = defineStore('channel', () => {
    // 声明数据
    const channelList = ref([])
    // 声明操作数据的方法
    const getList = async () => {
        // 支持异步
        const { data: {data} } = await axios.get('http://geek.itheima.net/v1_0/channels')
        channelList.value = data.channels
        console.log(data.channels)
    }
    // 声明getters相关

    return {
        channelList,
        getList
    }
})

App.vue

<script setup>
import Son1Com from '@/components/Son1Com.vue'
import Son2Com from '@/components/Son2Com.vue'
import { useCounterStore } from '@/store/counter'
import { useChannelStore } from '@/store/channel.js'

const counterStore = useCounterStore()
const channelStore = useChannelStore()
// console.log(counterStore)


</script>

<template>
  <div>
    <h3>
      App.vue根组件
      - {{ counterStore.count }}
      - {{ counterStore.msg }}
    </h3>
    
    <Son1Com></Son1Com>
    <Son2Com></Son2Com>
    <hr>
    <button @click="channelStore.getList">获取频道数据</button>
    <ul>
      <li v-for="item in channelStore.channelList" :key="item.id">{{ item.name }}</li>
    </ul>
  </div>
</template>

<style scoped>

</style>

5. storeToRefs()

为了从 store 中提取属性时保持其响应性,你需要使用 storeToRefs()。它将为每一个响应式属性创建引用。当你只使用 store 的状态而不调用任何 action 时,它会非常有用。请注意,你可以直接从 store 中解构 action,因为它们也被绑定到 store 上:

<script setup>
import { storeToRefs } from 'pinia'
const store = useCounterStore()
// `name` 和 `doubleCount` 是响应式的 ref
// 同时通过插件添加的属性也会被提取为 ref
// 并且会跳过所有的 action 或非响应式 (不是 ref 或 reactive) 的属性
const { name, doubleCount } = storeToRefs(store)
// 作为 action 的 increment 可以直接解构
const { increment } = store
</script

示例代码:

App.vue

<script setup>
import { storeToRefs } from 'pinia'
import Son1Com from '@/components/Son1Com.vue'
import Son2Com from '@/components/Son2Com.vue'
import { useCounterStore } from '@/store/counter'
import { useChannelStore } from '@/store/channel.js'

const counterStore = useCounterStore()
const channelStore = useChannelStore()

// 此时,直接结构,不处理,数据会丢失响应式
// const { count, msg } = counterStore
const { count, msg } = storeToRefs(counterStore)
const { channelList } = storeToRefs(channelStore)
const { getList } = channelStore


</script>

<template>
  <div>
    <h3>
      App.vue根组件
      - {{ count }}
      - {{ msg }}
    </h3>
    
    <Son1Com></Son1Com>
    <Son2Com></Son2Com>
    <hr>
    <button @click="getList">获取频道数据</button>
    <ul>
      <li v-for="item in channelList" :key="item.id">{{ item.name }}</li>
    </ul>
  </div>
</template>

<style scoped>

</style>

6. Pinia的调试

Vue官方的dev-tools调试工具对Pinia直接支持,可用直接进行调试

Pinia持久化插件

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

注:要先安装Pinia,且Pinia版本在2.0.0以上

1. 安装插件 pinia-plugin-persistedstate

npm i pinia-plugin-persistedstate

2. main.js使用

import persist from 'pinia-plugin-persistedstate'
...
app.use(createPinia().use(persist))

3. store仓库中,persist: true开启

如src/store/counter.js

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

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

export const useCounterStore =  defineStore('counter', () => {
    // 声明数据 - state
    const count = ref(6)
    // 声明操作数据的方法 - action(普通函数)
    const addCount = () => {
        count.value++
    }
    const subCount = () => count.value--

    // 声明基于数据派生的计算属性 - getters(computed)
    const double = computed(() => count.value * 2)

    // 声明数据 - state
    const msg = ref('hello Pinia')
    // 声明操作数据的方法 - action

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

    return {
        count, 
        addCount,
        subCount,
        double,
        msg
    }
},
{
    // persist: true,  // 开启当前模块的持久化
    persist: {
        key: 'hm-counter',  // 修改本地存储的唯一标识
        // 这个 store 将被持久化存储在 sessionStorage中
        // storage: sessionStorage,
        paths: ['count'],  // 存储的是哪些数据
    }
})

7. 总结

1. Pinia是用来做什么的?

答:新一代的状态管理工具,替代vuex

2. Pinia中还需要mutation吗?

答:不需要,action既支持同步也支持异步

3. Pinia如何实现getter?

答:computed计算属性函数

4. Pinia产生的Store如何解构赋值数据保持响应式?

答:storeToRefs

5. Pinia如何快速实现持久化?

答:pinia-plugin-persistedstate

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值