Vue怎么使用pinia管理数据

寻技术 VUE 2023年08月20日 94

这篇文章主要讲解了“Vue怎么使用pinia管理数据”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Vue怎么使用pinia管理数据”吧!

    Vue使用pinia管理数据

    Vue3 + TS

    步骤:

    main.ts
    中注册
    pinia
    import { createPinia } from 'pinia'
    
    const pinia = createPinia()
    
    app.use(pinia)

    创建文件

    store/modules/home.ts
    ,用于管理home模块的数据
    import { defineStore } from 'pinia'
    
    const useHomeStore = defineStore('home',{
        state:()=>({
            name:'tony'
        })
    })
    
    export default useHomeStore

    创建

    store/index.ts
    统一管理所有的模块
    import useHomeStore from './modules/home'
    
    const useStore = () => {
        return {
            home:useHomeStore()
        }
    }
    
    export default useStore

    测试

    import useStore from '@/store'
    const { home } = useStore()
    console.log(home.tony)

    实际操作:使用 Pinia 获取头部分类导航

    store/modules/home.ts
    中提供 state 和 actions
    const useHomeStore = defineStore('home',{
        state:() =>({
            categoryList:[]
        }),
        actions:{
         aysnc getAllCategory(){
          const {data} = await rquest.get('/home/category/head')
          this.categoryList = data.result                        
         }
        }
    })

    Layout/index.vue
    中发送请求
    <script setup lang="ts">
    import useStore from '@/store'
    const { home } = useStore()
    home.getAllCategory()
    </script>

    TS 类型声明文件

    定义类型声明

    src	ypesapihome.d.ts
    中定义数据类型
    // 分类数据单项类型
    export interface Goods {
      desc: string;
      id: string;
      name: string;
      picture: string;
      price: string;
      title: string;
      alt: string;
    };
    
    export interface Children {
      id: string;
      name: string;
      picture: string;
      goods: Goods[];
    };
    
    export interface Category {
      id: string;
      name: string;
      picture: string;
      children: Children[];
      goods: Goods[];
    };
    
    // 分类数据列表类型
    export type CategoryList = Category[];

    类型出口统一

    新建

    src	ypesindex.d.ts
    // 统一导出所有类型文件
    export * from "./api/home";

    应用

    修改

    store/modules/home.ts
    ,给
    axios
    请求增加泛型
    import { defineStore } from "pinia";
    import request from "@/utils/request";
    import type { CategoryList } from "@/types";
    
    const useHomeStore = defineStore("home", {
      state: () => ({
        categoryList: [] as CategoryList,
      }),
      actions: {
        async getAllCategory() {
          const {data} = await request.get("/home/category/head");
          this.categoryList = data.result;
        },
      },
    });
    
    export default useHomeStore;

    Axios 二次封装

    srcutils
    equest.ts
    -import axios from "axios";
    +import axios, { type Method } from "axios";
    
    const instance = axios.create({
      baseURL: "xxx",
      timeout: 5000,
    });
    
    // 添加请求拦截器
    instance.interceptors.request.use(
      function (config) {
        // 在发送请求之前做些什么
        return config;
      },
      function (error) {
        // 对请求错误做些什么
        return Promise.reject(error);
      }
    );
    
    // 添加响应拦截器
    instance.interceptors.response.use(
      function (response) {
        return response;
      },
      function (error) {
        // 对响应错误做点什么
        return Promise.reject(error);
      }
    );
    
    + // 后端返回的接口数据格式
    + interface ApiRes<T = unknown> {
    +    msg: string;
    +    result: T;
    + }
    
    +/**
    + * axios 二次封装,整合 TS 类型
    + * @param url  请求地址
    + * @param method  请求类型
    + * @param submitData  对象类型,提交数据
    + */
    +export const http = <T>(method: Method, url: string, submitData?: object) => {
    +  return instance.request<ApiRes<T>>({
    +    url,
    +    method,
    +    // ???? 自动设置合适的 params/data 键名称,如果 method 为 get 用 params 传请求参数,否则用 data
    +    [method.toUpperCase() === "GET" ? "params" : "data"]: submitData,
    +  });
    +};
    
    export default instance;

    使用

    store/modules/home.ts
    import { defineStore } from 'pinia'
    -import request from "@/utils/request";
    +import { http } from "@/utils/request";
    
    const useHomeStore = defineStore('home',{
        state:()=>({
            name:'tony'
        }),
        actions: {
        async getAllCategory() {
    -    const res = await request.get<ApiRes<CategoryList>>("/home/category/head");
    +    // 使用起来简洁很多
    +    const res = await http<CategoryList>("GET", "/home/category/head");
         this.categoryList = res.data.result;
        },
      },
    })
    
    export default useHomeStore

    pinia 持久化存储

    目标: 通过

    Pinia
    插件快速实现持久化存储。

    插件文档:点击查看

    用法

    安装

    yarn add pinia-plugin-persistedstate
    # 或
    npm i pinia-plugin-persistedstate

    使用插件

    import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
    
    const pinia = createPinia();
    pinia.use(piniaPluginPersistedstate);
    app.use(pinia);

    模块开启持久化

    const useHomeStore = defineStore("home",()=>{
    ...
    },
    // defineStore 第三个参数
      {
        // 添加配置开启 state/ref 持久化存储
        // 插件默认存储全部 state/ref
        persist: true,
      }
    );

    常见疑问

    Vue2 能不能用 Pinia 和 持久化存储插件。

    • 可以使用,需配合 @vue/composition-api 先让 Vue2 老项目支持 组合式API。

    • Pinia 能在 组合式API 中使用。

    模块做了持久化后,以后数据会不会变,怎么办?

    • 先读取本地的数据,如果新的请求获取到新数据,会自动把新数据覆盖掉旧的数据。

    • 无需额外处理,插件会自己更新到最新数据。

    进阶用法(按需持久化所需数据)

    需求:不想所有数据都持久化处理,能不能按需持久化所需数据,怎么办?

    可以用配置式写法,按需缓存某些模块的数据。

    import { defineStore } from 'pinia'
    
    export const useStore = defineStore('main', {
      state: () => {
        return {
          someState: 'hello pinia',
          nested: {
            data: 'nested pinia',
          },
        }
      },
      // 所有数据持久化
      // persist: true,
      // 持久化存储插件其他配置
      persist: {
        // 按需存储 state/ref
        // 修改存储中使用的键名称,默认为当前 Store的 id
        key: 'storekey',
        // 修改为 sessionStorage,默认为 localStorage
        storage: window.sessionStorage,
        // ????按需持久化,默认不写会存储全部
        paths: ['nested.data'],
      },
    })
    关闭

    用微信“扫一扫”