Pinia状态管理库

目录

使用Pinia步骤:

1.在main.js文件导入pinia:

2.定义store状态:

使用 storeToRefs() 进行解构处理:

eg:文章分类列表渲染: 

添加请求拦截器:


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

Pinia 是 Vue 的存储库,它允许你在组件/页面之间共享状态。如果熟悉组合式 API,可能会认为已经可以与简单的 .这对于单页应用程序来说是正确的,但如果应用程序是服务器端呈现的,则会使应用程序暴露于安全漏洞。但是,即使在小型单页应用程序中,也可以从使用 Pinia 中获得很多好处:export const state = reactive({}) 

如果创建的store没有被使用,则不会创建出来。以至于可以定义许多的store,且必须在不同文件创建他,以此来方便管理。

下面是pinia官网:Introduction | Pinia (vuejs.org) 

使用Pinia步骤:

安装pinia:cnpm install pinia
在vue应用实例中使用pinia
在src/stores/count.js中定义store
在组件中使用store 

1.在main.js文件导入pinia:

这里因为Pinia是默认内存存储,刷新浏览器会丢失数据,我们使用pinia内的Persist插件就可以将Pinia中的数据持久化存储。

为了使用persist,我们需要安装persist:cnpm install pinia-persistedstate-plugin,然后再pinia中使用persist,并且需要再main.js导入一下。

import './assets/main.scss'
 
import { createApp } from 'vue'
import App from './App.vue'
import { createPinia } from 'pinia'
//导入持久化插件
import { createPersistedState } from 'pinia-persistedstate-plugin'
//创建根实例
const app = createApp(App);
//创建createPinia()函数实例
const pinia = createPinia();    
//因为Pinia是默认内存存储,刷新浏览器会丢失数据,使用Persist插件就可以将Pinia中的数据持久化存储
const persist = createPersistedState();
pinia.use(persist)
//pinia插件的安装配置
app.use(pinia)
//视图的挂载
app.mount('#app')

2.定义store状态:

其实无外乎就是使用defineStore()方法,在方法内部分为两个参数来写 :

第一个参数:名字,确保唯一性。
第二个参数:函数,其内部可以定义状态的所有内容,其内部先创建一个响应式数据,然后设置获取数据以及删除数据的方法,最后返回数据以及方法。

加上Persist插件就可以将Pinia中的数据持久化存储。

 我们以操作count为例,在内部添加响应式数据count以及异步方法等,随后并返回,下图是想要获取的异步响应数据:

下面看count.js代码:

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

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

export const useCounterStore = defineStore('counter',()=>{
    //声明数据  => state
    const count = ref(0);

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

    //声明异步方法 => axios
    const getCount = async ()=>{
        //解构:因为最开始的axios会包一层,所以我们先解构得到的data是后台返回过来的整个对象
        //然后根据上图在返回对象内有一层data,所以在解构一层data
        //最后通过最后解构出来的data来使用属性
        const {data:{data}} = await axios.get('url');
        count.value = data.count;
    }
    //声明基于数据派生的计算属性 => getters
    const double = computed(()=>{ count.value * 2});

    //也可以声明多个响应式数据在同一store中
    const msg = ref(0);
    
    //返回想要使用的数据以及方法等,以便于后期再组件调用函数名.数据/.方法等可以直接调用
    return {count,addCount,subCount,double,msg}; 
},{
    persist: true  //因为Pinia是默认内存存储,刷新浏览器会丢失数据,使用Persist插件就可以将Pinia中的数据持久化存储
});

使用 storeToRefs() 进行解构处理:

因为 store 是一个用 reactive 包装的对象,而 reactive 响应性的底层实现是 proxy ,而 proxy 是针对对象进行监视,所以这意味着只要对象在就可以监视对象内所有属性的修改,而如果解构,也就是声明了两个变量将值从对象内属性值复制到变量中,因为这两个变量值是复制过来的,以至于跟响应式对象没有关系,所以这就不能直接解构处理,这就引出了需要我们使用 storeToRefs() 方法。

为了在保持其响应性的同时从存储中提取属性,需要使用storeToRefs(),它将为每个响应式属性创建引用。当仅使用 store 的状态而不调用任何方法 action 时,这非常有用。请注意,您可以直接从 store 中解构方法,方法跟响应式没有关系,所以无需使用storeToRefs()。

<script setup>
// import { RouterView } from 'vue-router';
import { storeToRefs } from 'pinia';
import { useTokenStore } from './stores/token';
const countStore = useTokenStore();
//此时直接解构不进行任何处理,数据会丢失响应式
const {count,msg} = storeToRefs(countStore);
//直接解构方法
const {addCount} = countStore;
</script>

eg:文章分类列表渲染: 

 为了跨组件传递JWT令牌,我们就会利用Pinia状态管理库,它允许跨组件或页面共享状态

我们先定义仓库,随后在获取到token将其调用仓库内方法来给仓库内响应式变量赋值(注意:页面不能直接通过定义方法来操作仓库响应式数据,需要使用仓库的方法才能改变),然后我们在仓库添加想要操作数据的方法就可以跨组件使用了。

//定义store
import { defineStore } from "pinia";
import {ref} from 'vue'
/*
  第一个参数:名字,确保唯一性
  第二个参数:函数,其内部可以定义状态的所有内容
  返回值:函数
*/
export const useTokenStore = defineStore('token',()=>{
    //定义状态内容
 
    //1.定义响应式变量
    const token = ref('');
 
    //2.定义函数来修改token值
    const setToken = (newToken)=>{
        token.value = newToken;
    }
 
    //3.定义函数来移除token值
    const removeToken = ()=>{
        token.value = '';
    }
 
    return {
        token,setToken,removeToken
    }
},{
    persist: true  //因为Pinia是默认内存存储,刷新浏览器会丢失数据,使用Persist插件就可以将Pinia中的数据持久化存储
}
);

这样我们就可以调用定义的useTokenStore来使用pinia了。

我们的目的是想要通过pinia来跨组件使用token请求头内的JWT令牌,将其封装给请求头。

我们首先再Login.vue文件中把得到的token存储到pinia中:

//导入store状态
import { useTokenStore } from '@/stores/token.js';
//导入路由器
import { useRouter } from 'vue-router';
const tokenstore = useTokenStore();
const router = useRouter();
//表单数据校验
const login = async()=>{
    let result = await userLoginService(registerData.value);
    // alert(result.msg ? result.msg : '登录成功'); 
    ElMessage.success(result.msg ? result.msg : '登录成功');
    //将得到的token存储到pinia中
    tokenstore.setToken(result.data);
    //通过路由跳转首页
    router.push('/');
}

然后再article.js中定义请求函数:

import request from '@/utils/request.js'
import { useTokenStore } from '@/stores/token.js';
 
export const ArticleCategoryListService = ()=>{
    const tokenStore = useTokenStore();
    //在pinia中定义的响应式数据不需要加.value才能使用数据
    return request.get('/category',{headers:{'Authorization':tokenStore.token}});
} 

但是这样我们需要将剩下的请求函数都要传递JWT令牌,代码会很繁琐,这个时候我们就可以添加请求拦截器来使用回调函数来发送

添加请求拦截器:

在request.js文件中添加请求拦截器:

import { useTokenStore } from '@/stores/token.js';
//添加请求拦截器
instance.interceptors.request.use(
    (config)=>{
        //请求前的回调
        const tokenStore = useTokenStore();
        if(tokenStore.token){
            //通过config调用headers获取请求头,在调用Authorization将JWT令牌存放到内部以此来添加统一的请求头
            config.headers.Authorization = tokenStore.token;
        }
        return config;
    },
    (err)=>{
        //请求错误的回调
        Promise.reject(err);//异步的状态转化成失败的状态
    }
)
export default instance;

修改article.js文件的请求函数:

import request from '@/utils/request.js'
 
export const ArticleCategoryListService = ()=>{
    return request.get('/category');
} 
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

记得开心一点嘛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值