vue3_pinia学习

一、state

1.初始化仓库store

  • 安装pinia
npm install pinia
  •  main.ts中引入
import { createPinia } from 'pinia'
app.use(createPinia())
  • src下新建store文件夹,store下新建 index.ts,以及user.ts

 info.ts

export const enum Names {
    TEST='TSET'
}

index.ts

存储是使用定义的defineStore(),并且它需要一个唯一的名称,作为第一个参数传递

import {defineStore} from 'pinia'
import {Names} from './user'
//形式1
export const useTestStore = defineStore(Names.TEST,{
    state:()=>{
        return { 
            current:1,
            name:'hello word'
        }
    },
    // 也可以定义为
    // state:()=>({current:1,name:'hello word'}),
    getters:{

    },
    actions:{
        change(){
            this.current++
        }
    }
})

// 或者也可以写成如下 ---形式2
// export const useTestStore = defineStore(Names.TEST, () => {
//     const current = ref(0)
//     const name = ref('hahaha')
//     function change() {
//         current.value++
//         name.value = '形式2'
//     }
  
//     return { current, name, change}
// })

2.组件中的使用store

  • 直接修改

  • 调用actions里面的方法

  • $patch

  • $state

  $state您可以通过将store的属性设置为新对象来替换store的整个状态

        (缺点就是必须修改整个对象的所有属性)

<template>
  <div class="container"  ref="el">
    {{ test.current }}
    {{ test.name }}
    <el-button @click="change">change</el-button>
  </div>
</template>

<script setup lang="ts">
import {ref} from 'vue'
import {useTestStore} from '@/store/index'
const test = useTestStore()
const change = ()=>{
    // 1.直接修改
    test.current = 1000
    test.name='xiaoluo'

    // 2.调用actions里面的方法
    // test.change()

    // 3.$patch
    // test.$patch({current:2000,name:'heiehei'})

    //4.$state
    // test.$state = {current:300,name:'state'}
    
    //5.$reset $reset() 方法将状态 重置 到其初始值
    test.$reset()
    
}
</script>

注意点:

storeToRefs()

store 是一个用reactive 包裹的对象,这意味着不需要在getter 之后写.value,但是,就像setup 中的props 一样,我们不能对其进行解构

<template>
  <div class="container"  ref="el">
    {{ current }}
    {{ name }}
    <el-button @click="change">change</el-button>
  </div>
</template>

<script setup lang="ts">
import {ref} from 'vue'

import {useTestStore} from '@/store/index'
import { storeToRefs } from 'pinia'

const test = useTestStore()

// const {current,name} = test
const {current,name} = storeToRefs(test) //使用storeToRefs响应式不会丢失
const change = ()=>{
    // 1.直接修改
    test.current = 1000
    test.name='xiaoluo'
    console.log(test);//这里数据变了,但页面上数据不会变
}
</script>

3.$subscribe()$onAction

  • $subscribe()

通过 store 的 $subscribe() 方法查看状态及其变化,类似于 Vuex 的 subscribe 方法。 与常规的 watch() 相比,使用 $subscribe() 的优点是 subscriptions 只会在 patches 之后触发一次

默认情况下,state subscriptions 绑定到添加它们的组件(如果 store 位于组件的 setup() 中)。 意思是,当组件被卸载时,它们将被自动删除。 如果要在卸载组件后保留它们,请将 { detached: true } 作为第二个参数传递给 detach 当前组件的 state subscription

test.$subscribe((mutation, state) => {
  console.log(mutation,state);
  // 每当它发生变化时,将整个状态持久化到本地存储
  localStorage.setItem('test', JSON.stringify(state))
},{ detached: true })

二、Getters

Getter 完全等同于 Store 状态的 计算值

使用场景:

import {defineStore, mapStores} from 'pinia'
import {Names} from './user'
export const useUserStore = defineStore(Names.INFO,{
    state:()=>({
        adress:'湖南'
    }),
    getters:{
        userGet(state){
            return state.adress+'cs'
        }
    }
})
// 形式1
export const useTestStore = defineStore(Names.TEST,{
    // 也可以定义为
    state:()=>({current:1,name:'hello word',age:25}),
    getters:{
        // 自动将返回类型推断为数字
        doubleCurrent(state):number{
            return state.current *2
        },
         // 返回类型必须明确设置
        doubleName():string{
            return this.name +' No.1'
        },
        // 访问其他 getter
        getOthers():number{
            return this.doubleCurrent*3
        },
        //将参数传递给 getter
        getParams:(state) =>{
            return (num:number) =>state.current*num
        },
        // 访问其他 Store 的getter
        getOtherStore(state){
            const user = useUserStore()
            return user.userGet
        }
    },
})

组件中使用getter和使用state一样

三、Actions

export const useUserStore = defineStore(Names.INFO,{
    state:()=>({
        adress:'湖南'
    }),
    getters:{
        userGet(state){
            return state.adress+'cs'
        }
    }
})
const login = ():Promise<string> =>{
    return new Promise(resolve=>{
        setTimeout(()=>{
            resolve('周杰伦')
        },2000)
    })
}
// 形式1
export const useTestStore = defineStore(Names.TEST,{
    state:()=>({current:1,name:'hello word',age:25}),
    actions:{
        // 同步 以及使用其他store里的数据
        change(){
            const user = useUserStore()
            this.name = user.adress
            this.current++
        },
        // 异步
        async registerUser() {
            const res = await login()
            this.name = res
        },
    }
})

页面中调用:

import { storeToRefs } from 'pinia'
const test = useTestStore()

function add(){
 test.change()
}

订阅 Actions:

使用 store.$onAction() 订阅 action 及其结果。传递给它的回调在 action 之前执行。after 处理 Promise 并允许您在 action 完成后执行函数。 以类似的方式,onError 允许您在处理中抛出错误。

const unsubscribe = someStore.$onAction(
  ({
    name, // action 的名字
    store, // store 实例
    args, // 调用这个 action 的参数
    after, // 在这个 action 执行完毕之后,执行这个函数
    onError, // 在这个 action 抛出异常的时候,执行这个函数
  }) => {
    // 记录开始的时间变量
    const startTime = Date.now()
    // 这将在 `store` 上的操作执行之前触发
    console.log(`Start "${name}" with params [${args.join(', ')}].`)

    // 如果 action 成功并且完全运行后,after 将触发。
    // 它将等待任何返回的 promise
    after((result) => {
      console.log(
        `Finished "${name}" after ${
          Date.now() - startTime
        }ms.\nResult: ${result}.`
      )
    })

    // 如果 action 抛出或返回 Promise.reject ,onError 将触发
    onError((error) => {
      console.warn(
        `Failed "${name}" after ${Date.now() - startTime}ms.\nError: ${error}.`
      )
    })
  }
)

// 手动移除订阅
unsubscribe()

四、pinia持久化插件pinia-plugin-persist

常规的store存储数据,刷新页面数据会丢失

1.安装

npm install pinia-plugin-persist

2.引入

index.ts: 

import { createPinia } from "pinia"
import piniaPluginPersist from "pinia-plugin-persist"
 
const store = createPinia()
store.use(piniaPluginPersist)
 
export default store

main.ts:

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

const pinia = createPinia()
const app = createApp(App)
createApp(App)
.use(pinia)
.use(store)
.mount('#app')
import {defineStore, mapStores} from 'pinia'
import {Names} from './user'
export const useUserStore = defineStore(Names.INFO,{
    state:()=>({
        adress:'湖南',
        name:'hello'
    }),
    getters:{
        userGet(state){
            return state.adress+'cs'
        }
    },
    persist:{
        //开启 enabled 之后,默认会对整个 Store 的 state 内容进行 sessionStorage 储存
        enabled: true,
        strategies:[
            {
                key:'cus',//自定义存储的 key,默认是 store.$id,此处是INFO
                storage:localStorage,//可以指定任何 extends Storage 的实例,默认是 sessionStorage
                paths:['adress','name']// state 中的字段名,按组打包储存
            }
        ]
    }
}
)

 参考链接:Pinia 持久化存储插件 pinia-plugin-persist 介绍及源码解读 - 掘金

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值