Pinia保姆级教学

3,475 阅读6分钟

Pinia

来了,来了,期待已久的保姆级教学他来了,下面就来跟随我的步伐,一起走进Pinia的内心世界吧!😘 1645426679(1).jpg

Pinia是什么

Pinia.js是由Vue.js团队核心成员开发的新一代状态管理器,使用Composition Api进行重新设计的,也被视为下一代Vuex

Pinia是一个Vue的状态管理库,允许跨组件、跨页面进行全局共享状态,也由于其设计的简洁性、和对TypeScript的良好支持,取代Vuex指日可待。

其实吧,我一直觉得Vuex好是好用,但是总觉得他对新手不是特别友好,但是Pinia是真的绝绝子,特别好入手,并且写法比Vuex顺眼多了,Pinia支持Vue2Vue3,这都不值得卷一下吗?😝😝

Vuex的比较

  • mutations不再存在。他们经常被认为是非常冗长的。他们最初带来了 devtools 集成,但这不再是问题。
  • 无需创建自定义复杂包装器来支持 TypeScript,所有内容都是类型化的,并且 API 的设计方式尽可能利用 TS 类型推断。
  • 不再需要注入、导入函数、调用它们,享受自动完成!
  • 无需动态添加stores,默认情况下它们都是动态的,您甚至都不会注意到。请注意,您仍然可以随时手动使用stores进行注册,但因为它是自动的,您无需担心。

有一说一,这玩意儿我是机翻的,要是出错了,不要怪我哦🤣🤣🤣

Pinia优点

  • 完全支持Typescript,不需要进行复杂的配置
  • 支持服务端渲染(SSR)
  • 相比于Vuex更加轻量
  • 去除 mutations,只有 stategettersactions,并且actions支持同步和异步

其实吧,我知道大家想说什么,Vue3都已经吧响应式给大家展示出来了,那么我直接写reactiveref把数据共享,这样就不需要用到VuexPinia的状态管理库了吧,但是,直接reactive和用ref是不支持SSR的!!而且新手嘛,我寻思新手也不会有什么骚操作,并且统一的工具比较方便,可以减少项目上手成本,代码结构也相对统一。🤗

ok,ok介绍完毕下面我们直接一把梭哈,让你看完我的文章,让你直接学会Pinia😉

以下内容使用Vite+TypeScript+Vue3+Pinia,手段极其残忍,请大朋友在小朋友的陪伴下,酌情观看

创建项目

就当你们没有下载过vite吧,第一步

//使用 NPM:
npm init vite@latest
//使用 Yarn:
 yarn create vite

image.png

然后进入项目,下载pinia

    yarn add pinia

image.png 下载完成后,在main.js中,结构引入createPinia

image.png

然后在src文件夹中新建store文件,并且创建index.ts 然后结构引入defineStore,有两个参数,第一个是字符串(相当于id),第二个参数为对象

image.png 也可以在里面写id

image.png state知道嘛,肯定是定义状态数据的咯,getters对数据进行监视,计算数据变化,有缓存的actions对数据进行同步或者异步操作

state

定义state

//第一种
import {defineStore} from "pinia";
export const miluyuStore=defineStore('miluyu',{
    state:()=>{
        return{
            name:'迷鹿鱼',
            age:23,
            hobby:['吃饭饭','睡觉觉','逛街街']
        }
    },
    getters:{

    },
    actions:{

    }
})

//第二种
import {defineStore} from "pinia";
export const miluyuStore=defineStore({
    id:'miluyu',
    state:()=>{
        return{}
    },
    getters:{

    },
    actions:{

    }
})

获取state

接下来,我们在components文件中写一个组件,并在组件中调pinia的数据

image.png

image.png

是不是很简单,对了在这里会出现的问题是在APP.vue没有引入,或者项目启动不成功,项目启动命令为yarn dev

修改state

这边的话会有四种方式进行修改,有一说一我觉得他们各有千秋,看个人习惯吧

第一种

直接用,简单易懂

const addAge=()=>{
  store.age++
}

第二种

官方说的,适用于多状态数据改变并且进行了优化(官方是老大,他说什么我就是什么)

以对象的形式进行传递

const addAgePatch=()=>{
  store.$patch({
    age:store.age+10
    name:store.name+'!!'
  })
}

第三种

以函数的形式进行传递,可以写复杂的业务逻辑

const  addAgePatchs=()=>{
  store.$patch((state)=>{
    state.age=state.age+100
    state.name=state.name+'??'
  })
}

你可能会好奇为什么传递了一个为state的参数,我们打印一下,你就会知道了,他其实就是我们最开始存储的数据

image.png

第四种(actions中进行使用)

哦~ 哦~ 哦~,来到了最快乐的第四种,为什么我会这么开心呢,因为第四种可以在actions中进行使用

actions:{
    subtractAge(){
        this.age=this.age-10
    }
}
//那么我们怎么调用呢🤪,当然,有两种方式调用
//第一种直接调用
<button @click="store.subtractAge">年龄-10</button>
//第二种间接调用
const subtractAge=()=>{
  store.subtractAge()
}

state的小问题

哦哦哦,忘了给你们说,肯定会有人会犯这个错误(必不可能是我),大家可能会使用解构,把数据结构出来,但是结构出来的数据就不是响应式了哦,简单的来打印一下。

image.png 不知道onMounted的给我滚去看第一篇文章!!!

image.png Proxy大家也知道是什么了吧,不知道情况同上!!!

但是我们不可能不使用结构吧,不要惊慌,我们要使用pinia给我们的方法storeToRefs,让数据重新变为响应式

image.png

image.png

getters

计算属性

//vue页面
<div>QQ:<span>{{store.conceal}}</span></div>
//store/index.ts
getters:{
    conceal(state){
        return state.qq.toString().replace(/^(.{3})(.*)(.{4})$/, '$1 $2 $3')
    }
},

当然也可以不传参数,使用this,但是我们用到的是TypeScript,可以进行类型推导,现在就没有办法推导出来,那我们就可以告诉函数,我们return出来的是什么

conceal():string{
    return this.qq.toString().replace(/^(.{3})(.*)(.{4})$/, '$1 $2 $3')
}

最后这个是有缓存的,只会最开始的时候调用一次,然后修改值时oldValue!==newValue调用一次

actions

...感觉这个玩意没有什么好讲的,对了,还有个调用同步异步和调用其他actions用法

//可以用this直接调用actions的方法
async deleteList(id:number) {
    console.log(id)
    const {data} = await postAjax(url + '/matter/delete', {id: id})
    this.subtractAge()
    return data
}
//当然,你也可以不使用this,只需要在传入一个参数
deleteList(store:any,id:number){
    console.log(id)
    store.subtractAge()
}

多数据产库调用

当然大型项目里面不可能只有一个数据库咯,那么我们要怎么做呢? 第一步:在store文件夹中新创建新的数据库

import {defineStore} from "pinia";
export const homeStore=defineStore({
    id:'home',
    state:()=>{
        return{
            looks:'大帅B'
        }
    },
    getters:{
    },
    actions:{
    }
})

第二步:在最初创建的store/index.ts中引入注意,它是一个方法

import {homeStore} from'./hone'
getLooks(){
    console.log(homeStore().looks)
}

第三步:直接就在页面中调用咯

<button @click="store.getLooks()">颜值打印</button><br>

数据持久化

我们可以下载pinia-plugin-persist插件,实现数据持久化。

yarn add pinia-plugin-persist

//main.ts
import piniaPluginPersist from 'pinia-plugin-persist'
pinia.use(piniaPluginPersist

//store/index.ts
export const miluyuStore = defineStore({
    id: 'miluyu',
    state: () => {
        return {
            name: '迷鹿鱼',
            age: 23,
            hobby: ['吃饭饭', '睡觉觉', '逛街街'],
            qq: 1234567890
        }
    },
    getters: {
        conceal(): string {
            console.log('state发生改变了')
            // return state.qq.toString().replace(/^(.{3})(.*)(.{4})$/, '$1 $2 $3')
            return this.qq.toString().replace(/^(.{3})(.*)(.{4})$/, '$1 $2 $3')
        }
    },
    actions: {
        subtractAge() {
            this.age = this.age - 10
        },
        getLooks() {
            console.log(homeStore().looks)
        },
        // async deleteList(id:number) {
        //     console.log(id)
        //     const {data} = await postAjax(url + '/matter/delete', {id: id})
        //     this.subtractAge()
        //     return data
        // }
        deleteList(store: any, id: number) {
            console.log(id)
            store.subtractAge()
        }

    },
    persist: {
        enabled: true
    }
})

数据默认是存储在sessionStorage里面,key是自己最开始命名的id

当然,我们也可以修改这些,比如改变key或者存储在localStorage

persist: {
    enabled: true,
    strategies: [
        {
            key: 'indexStore',
            storage: localStorage,
        }
    ]
}

也可以单独只持久化几个数据

persist: {
    enabled: true,
    strategies: [
        {
            key: 'indexStore',
            storage: localStorage,
            paths: [ 'age']
        }
    ]
}

奇奇怪怪的方法

$reset()

可以将状态重置为初始值

const empty=()=>{
  store.$reset()
}

$state

可以替换store

const newStore=()=>{
  store.$state = { name: "℃", age: 22 }
}

$subscribe

...有一说一这个东西我看官方文档没有怎么看明白的,大概意思是可以使用订阅机制subscribe来实现数据的持久化存储,优点是与watch相比,subscribe在补丁之后,订阅只会触发一次。(我能说什么呢,我只能说高级,牛蛙,流下了没有技术含量的眼泪😥😥😥)

store.$subscribe((mutation, state) => {
  localStorage.setItem(store.$id, JSON.stringify(state));
});

未完不续......

当然,我还是会把写的东西上传到码云上,大家可以一起来学习,写的有什么问题,我也会改正,那么,就此告辞(下期节目我也不知道写什么,反正我是只鸽子精🧐)

e1ee8d38d2a069e6f9cd0238e95f909.jpg