uniapp商城之基础架构


一、uni-ui组件库

安装uni-ui组件库

二、小程序端Pinia持久化

说明:Pinia用法与Vue3项目完全一致,uni-app项目仅需解决持久化插件兼容性问题。

1.持久化存储插件

安装持久化存储插件:pinia-plugin-persistedstate

pnpm i pinia-plugin-persistedstate

注意:插件默认使用localStorage实现持久化,小程序端不兼容,需要替换持久化API。

2.基本用法

src/stores/modules/member.ts

import type { LoginResult } from '@/types/member'
import { defineStore } from 'pinia'
import { ref } from 'vue'

// 定义 Store
export const useMemberStore = defineStore(
  'member',
  () => {
    // 会员信息
    const profile = ref<LoginResult>()

    // 保存会员信息,登录时使用
    const setProfile = (val: LoginResult) => {
      profile.value = val
    }

    // 清理会员信息,退出时使用
    const clearProfile = () => {
      profile.value = undefined
    }

    // 记得 return
    return {
      profile,
      setProfile,
      clearProfile,
    }
  },
  // TODO: 持久化
  {
    // 网页端配置
    // persist: true,
    // 小程序端配置
    persist:{
      storage:{
        getItem(key) {
          return uni.getStorageSync(key)
        },
        setItem(key,value){
          uni.setStorageSync(key,value)
        }
      }
    }
  },
)

stores/index.ts

import { createPinia } from 'pinia'
import persist from 'pinia-plugin-persistedstate'

// 创建 pinia 实例
const pinia = createPinia()
// 使用持久化存储插件
pinia.use(persist)

// 默认导出,给 main.ts 使用
export default pinia

// 模块统一导出
export * from './modules/member'

src/main.ts

import { createSSRApp } from 'vue'
import pinia from './stores'

import App from './App.vue'
export function createApp() {
  const app = createSSRApp(App)

  app.use(pinia)
  return {
    app,
  }
}

2.多端兼容

网页端持久化API

// 网页端API
localStorage.setItem()
localStorage.getItem()

多端持久化API

// 兼容多端API
uni.setStorageSync()
uni.getStorageSync()

三、uni.request请求封装

1.请求和上传文件拦截器

uniapp拦截器uni.addInterceptor
接口说明接口文档

实现需求如下:

  1. 拼接基础地址
  2. 设置超时时间
  3. 添加请求头标识
  4. 添加token
// 添加拦截器:
//     拦截 request 请求
//     拦截 uploadFile 文件上传


import { useMemberStore } from "@/stores"

// TODO:
//     1.非 http 开头需拼接地址
//     2.请求超时
//     3.添加小程序端请求头标识
//     4.添加 token  请求头标识

const baseURL = 
    'https://pcapi-xiaotuxian-front-devtest.itheima.net'

// 添加拦截器
const httpInterceptor = {
    // 拦截器触发
    invoke(options:UniApp.RequestOptions){
        // 1. 非 http 开头需拼接地址
        if (!options.url.startsWith('http')) {
            options.url = baseURL + options.url
        }
        // 2.请求超时,默认60s
        options.timeout = 10000
        // 3.添加小程序端请求头标识
        options.header = {
            ...options.header,
            'source-client':'miniapp',
        }
        // 4.添加 token 请求头标识
        const memberStore = useMemberStore()
        const token = memberStore.profile?.token
        if (token) {
            options.header.Authorization = token
        }

    }
}
uni.addInterceptor('request',httpInterceptor)
uni.addInterceptor('uploadFile',httpInterceptor)

2.封装Promise请求函数

/**
 * 请求函数
 * @param UniApp.RequestOptions
 * @returns Promise
 *  1. 返回 Promise 对象,用于处理返回值类型
 *  2. 请求成功
 *    2.1 提取核心数据 res.data
 *    2.2 添加类型,支持泛型
 *  3. 请求失败
 *    3.1 网络错误 -> 提示用户换网络
 *    3.2 401错误 -> 清理用户信息,跳转到登录页
 *    3.3 其他错误 -> 根据后端错误信息轻提示
 */
interface Data<T> {
    code: string
    msg: string
    result: T
}
export const http = <T>(options:UniApp.RequestOptions) =>{
    // 1. 返回 Promise 对象
    return new Promise<Data<T>>((resolve,reject)=>{
        uni.request({
            ...options,
            // 响应成功
            success(res){
                // 状态码 2XXX  axios 就是这样设计的
                if (res.statusCode >= 200 && res.statusCode < 300) {
                  // 2.1 提取核心数据 res.data
                  resolve(res.data as Data<T>)
                } else if (res.statusCode === 401) {
                    // 401错误  -> 清理用户信息,跳转到登录页
                    const memberStore = useMemberStore()
                    memberStore.clearProfile()
                    uni.navigateTo({url:'/pages/login/login'})
                    reject(res)
                } else {
                    // 其他错误 -> 根据后端错误信息轻提示
                    uni.showToast({
                        icon:'none',
                        title:(res.data as Data<T>).msg  || '请求错误'
                    })
                    reject(res)
                }
            },
            // 相应失败
            fail(err) {
                uni.showToast({
                    icon:'none',
                    title:'网络错误,换个网络试试',
                })
                reject(err)
            }

        })
    })
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值