vue3 | pinia | axios | 持久化存储 | setup语法糖 | 把axios请求全部挂载到stores里面

630 阅读2分钟

基于vue3语法糖完成axios的封装,把请求挂载到pinia上

pinia官网:pinia.vuejs.org/

image.png

pinia-plugin-persistedstate官网:prazdevs.github.io/pinia-plugi…

image.png

axios官网:www.axios-http.cn/

image.png

demo

安装

npm install pinia
npm i pinia-plugin-persistedstate
npm install axios

注册引入

在main.js文件中全局注册:

import { createApp } from 'vue'
import { createPinia } from 'pinia'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'

const app = createApp(App)

app.use(createPinia().use(piniaPluginPersistedstate))
app.mount('#app')

封装axios

src/axios/request.js文件中:

// 将Axios封装成模块
import axios from 'axios'
import router from '@/router/index.js'
import { Toast } from '@/utils/extract'
import { useUserStore } from '@/stores/user'

// 创建axios实例
const request = axios.create({
  baseURL: import.meta.env.VITE_API_URL, // api的base_url
  timeout: 10000 // 请求超时时间
})

let store = null
let token
// 请求拦截器
request.interceptors.request.use(
  (config) => {
    // 可以在这里添加请求头等信息
    // 登录后才挂载user🍍
    if (!store) store = useUserStore()
    token = store.token
    if (token) {
      // 判断是否存在token,如果存在的话,则每个http header都加上token
      config.headers.Authorization = `Bearer ${token}` //请求头加上token
    }
    return config
  },
  (error) => {
    // 请求错误处理
    console.log(error) // for debug
    Promise.reject(error)
  }
)

// 响应拦截器
request.interceptors.response.use(
  (response) => {
    console.log(response)
    if (response.status == 200) {
      return response.data
    } else {
      router.push('/notFound')
    }
  },
  (error) => {
    // 对响应错误做处理
    console.log('err' + error) // for debugd
    Toast('服务器异常')
    return Promise.reject(error)
  }
)
export default request

src/stores/user.js文件中:

import { ref, reactive } from 'vue'
import { defineStore } from 'pinia'
import { Toast, Toast_Success } from '@/utils/extract'
import request from '@/axios/request.js'
import router from '@/router/index.js'

export const useUserStore = defineStore(
  'user',
  () => {
    const resp_signIn = reactive({})
    const token = ref()
    const isRemember = ref()
    const userData = reactive({})
    const resp_getUserInfo = reactive({})

    // post登录
    async function signIn(data) {
      Object.assign(resp_signIn, await request.post('/onlineShop/signIn', data))
      token.value = this.resp_signIn.data.token
      isRemember.value = data.isRemember
      if (this.resp_signIn.errCode == 1000) {
        localStorage.setItem('token', this.resp_signIn.data.token)
        Toast_Success('Successfully!')

        // get用户信息
        // 当获取token后,自动获取用户信息并保存在pinia中
        if (localStorage.getItem('token') != null) {
          Object.assign(
            resp_getUserInfo,
            await request.get('/onlineShop/getUserInfo', { params: {} })
          )
          Object.assign(userData, resp_getUserInfo.data)
        }

        router.push({
          path: '/home'
        })
      } else {
        Toast(this.resp_signIn.errMsg)
      }
      return token
    }

    // post注册
    async function signUp(data) {
      return await request.post('/onlineShop/signUp', data)
    }

    // get用户信息
    async function getUserInfo() {
      Object.assign(resp_getUserInfo, await request.get('/onlineShop/getUserInfo', { params: {} }))
      Object.assign(userData, resp_getUserInfo.data)
    }

    // put更改用户信息
    async function updateUserInfo(data) {
      return await request.put('/onlineShop/updateUserInfo', data)
    }

    // post更改头像
    const resp_uploadImage = reactive({})
    async function uploadImage(data) {
      Object.assign(resp_uploadImage, await request.post('/onlineShop/uploadImage', data))
    }

    // get验证码
    const resp_getVerificationCode = reactive({})
    async function getVerificationCode(data) {
      Object.assign(
        resp_getVerificationCode,
        await request.get('/onlineShop/getVerificationCode', { params: { phoneNumber: data } })
      )
      return resp_getVerificationCode
    }

    return {
      resp_signIn,
      token,
      isRemember,
      signIn,
      signUp,
      userData,
      resp_getUserInfo,
      getUserInfo,
      updateUserInfo,
      resp_uploadImage,
      uploadImage,
      resp_getVerificationCode,
      getVerificationCode
    }
  },
  {
    persist: true
  }
)

在需要发送请求的vue文件中调用:

<-- 直接使用 -->
<div class="name">{{ userStore.userData.name }}</div>
import { useUserStore } from '@/stores/user'

// 接口
const userStore = useUserStore()

onBeforeMount(async () => {
  // get用户信息
  await userStore.getUserInfo()

  if (userStore.userData.iconImage != '') {
    originIcon.value = userStore.userData.iconImage
  }
})

在请求还未完成时,有缓存的user信息在页面上显示;待到onBeforeMount生命周期内调用的请求完成,页面的信息便会更新

创建接口实例的时候,一定要在script部分的开头,不然会报错ReferenceError: Cannot access 'useUserStore' before initialization