uni-app --- 如何快速从Vue转入Uni-app

目录

一.什么是uni-app?

二.创建项目:

三.Vue与小程序的区别?

四.pages.json详解:

 1.组件自动引入规则(easycom):

2.应用页面配置(pages):

五.入门uniapp:

1.项目结构:

2.编写第一个页面:

 3.运行项目:

4.配置微信小程序的AppID:

5.配置页面路由:

6.pinia的使用:

7.拦截器的使用:

(1)定义请求拦截器:

(2)使用 uni.addInterceptor 添加拦截器:

 (3)请求函数封装: 

(4)请求封装:

(5)发起 HTTP 请求并处理返回的数据:


一.什么是uni-app?

uni-app 是一个使用 Vue.js 开发所有前端应用的框架,它支持一次开发,多个平台运行。具体来说,uni-app 可以编译成 iOS、Android、H5、以及各种小程序(如微信小程序、支付宝小程序、百度小程序等)应用,使得开发者能够在多个平台上以同一套代码实现应用。总的来说,uni-app 是一个非常适合需要多平台支持的项目的开发框架,尤其适合快速开发和迭代的产品。

下面是uniapp的官网:uni-app官网

二.创建项目:

uni-app支持通过 可视化界面、vue-cli命令行 两种方式快速创建项目。

我们在开发uniapp通常使用其自主开发的编译器:HBuilderX,下面是下载链接地址:HBuilderX-高效极客技巧,HBuilderX是通用的前端开发工具,但为uni-app做了特别强化。

  • 打开 HBuilderX
  • 点击左上角的 文件 > 新建 > 项目
  • 选择 uni-app,选择一个模板(例如“Hello uni-app”模板),然后设置项目名称和路径。
  • 点击 创建,HBuilderX 会自动为你生成一个初始项目。

同时我们也可以按照官网教程使用 cli 脚手架创建项目工程:uni-app官网 

npm install -g @vue/cli
vue create -p dcloudio/uni-preset-vue my-project

这将通过 Vue CLI 创建一个基于 uni-app 的项目。 

三.Vue与小程序的区别?

我们可以参考下面的博客:https://segmentfault.com/a/1190000015684864

四.pages.json详解:

{
  // 组件自动引入规则
  "easycom": {
    "autoscan": true, // 开启自动扫描
    "custom": {
      // uni-ui 规则如下配置
      "^uni-(.*)": "@dcloudio/uni-ui/lib/uni-$1/uni-$1.vue"
    }
  },
  "pages": [
    //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
    {
      "path": "pages/my/my",
      "style": {
        "navigationBarTitleText": "我的"
      }
    },
    // ...
  ],
  "globalStyle": {
    "navigationBarTextStyle": "black",
    "navigationBarTitleText": "",
    "navigationBarBackgroundColor": "#F8F8F8",
    "backgroundColor": "#F8F8F8"
  },
  // 设置 TabBar
  "tabBar": {
    "color": "#333",
    "selectedColor": "#27ba9b",
    "backgroundColor": "#fff",
    "borderStyle": "white",
    "list": [
      {
        "text": "首页",
        "pagePath": "pages/index/index",
        "iconPath": "static/tabs/home_default.png",
        "selectedIconPath": "static/tabs/home_selected.png"
      },
      // ...
    ]
  }
}

 1.组件自动引入规则(easycom):

"easycom": {
  "autoscan": true, // 开启自动扫描
  "custom": {
    "^uni-(.*)": "@dcloudio/uni-ui/lib/uni-$1/uni-$1.vue"
  }
}

easycom 是 uni-app 的 Easycom 组件自动引入功能的配置。

  • autoscan: true: 开启自动扫描功能,允许自动扫描项目中的组件,无需手动引入。uni-app 会自动根据组件名称进行匹配,加载对应的组件。
  • custom: 自定义组件的自动引入规则。"^uni-(.*)" 表示所有以 uni- 开头的组件都会自动从 @dcloudio/uni-ui/lib/uni-$1/uni-$1.vue 路径引入。这是针对 uni-ui 的自定义规则。比如 uni-button 组件会自动引入 @dcloudio/uni-ui/lib/uni-button/uni-button.vue

2.应用页面配置(pages):

"pages": [
  {
    "path": "pages/my/my",
    "style": {
      "navigationBarTitleText": "我的"
    }
  },
  // ...
]

pages 数组定义了 uni-app 应用的各个页面及其配置信息。每个对象代表一个页面的配置:

  • path: 页面路径,指向相应页面的 .vue 文件(以 pages/ 开头的路径表示项目内的页面)。
  • style: 页面样式配置,设置页面的 navigationBarTitleText 即导航栏的标题文字。例如,首页页面设置了 "首页" 作为标题。

3.全局样式配置(globalStyle):

"globalStyle": {
  "navigationBarTextStyle": "black",
  "navigationBarTitleText": "",
  "navigationBarBackgroundColor": "#F8F8F8",
  "backgroundColor": "#F8F8F8"
}

globalStyle 配置了全局的样式:

navigationBarTextStyle: 设置导航栏文字颜色,这里设置为黑色 ("black")。
navigationBarTitleText: 设置默认的导航栏标题文本,这里为空字符串 "" 表示没有默认标题。
navigationBarBackgroundColor: 设置导航栏的背景颜色,这里设置为 #F8F8F8,即浅灰色。
backgroundColor: 设置应用的背景色,这里也设置为浅灰色 #F8F8F8。

 4.TabBar 配置(tabBar):

"tabBar": {
  "color": "#333",
  "selectedColor": "#27ba9b",
  "backgroundColor": "#fff",
  "borderStyle": "white",
  "list": [
    {
      "text": "首页",
      "pagePath": "pages/index/index",
      "iconPath": "static/tabs/home_default.png",
      "selectedIconPath": "static/tabs/home_selected.png"
    },
    // ... 
  ]
}

tabBar 配置了应用底部导航栏的外观和内容:

  • color: 设置 TabBar 中未选中时的文字颜色,这里是灰色 #333
  • selectedColor: 设置 TabBar 中选中时的文字颜色,这里是绿色 #27ba9b
  • backgroundColor: 设置 TabBar 的背景色,这里设置为白色 #fff
  • borderStyle: 设置 TabBar 的边框样式,这里为白色 white,表示没有边框。
  • list: list 数组定义了 TabBar 的各个项。每个对象配置了:
    text: TabBar 项的文本(例如 "首页"、"分类")。
    pagePath: 点击该 Tab 时跳转的页面路径。
    iconPath: 未选中状态下的图标路径。
    selectedIconPath: 选中状态下的图标路径。

五.入门uniapp:

1.项目结构:

uni-app 项目结构通常包括以下文件和文件夹:

  • /pages:存放应用页面的目录,每个页面都是一个 .vue 文件。
  • /components:存放自定义组件的目录。
  • /static:静态资源,如图片、字体、文件等。
  • /unpackage:项目打包生成的文件目录。
  • pages.json:配置文件,用于配置页面路径、导航栏样式等。
  • manifest.json:项目的配置信息,包括应用名称、版本号等。
  • global.css:全局样式文件。
  • uni.scss:统一的样式文件,适用于全局的布局、颜色等

2.编写第一个页面:

pages 文件夹中,我们默认会看到一个 index.vue 页面。我们来修改这个页面,添加一个简单的内容。

打开 pages/index/index.vue,将文件内容修改为:

<template>
  <!-- 类似于 div 的容器元素,uni-app 使用 view 替代 HTML 中的 div -->
  <view class="content">
    <!-- 似于 span 或 p,用来显示文本内容 -->
    <text>{
  { message }}</text>
    <!-- 用来创建按钮,点击时调用 changeMessage 方法更新文本 -->
    <button @click="changeMessage">Change Message</button>
  </view>
</template>

<script>
export default {
  data() {
    return {
      message: "Hello, uni-app!"
    };
  },
  methods: {
    changeMessage() {
      this.message = "Hello, uni-app updated!";
    }
  }
};
</script>

<style scoped>
.content {
  text-align: center;
  margin-top: 50rpx;
}
button {
  margin-top: 20rpx;
}
</style>

 3.运行项目:

(1)在 HBuilderX 中,点击 运行 按钮,选择 运行到浏览器,你的应用将会在 Web 浏览器中启动。

(2)如果想在微信小程序等平台上运行:

  1. 在 HBuilderX 中,选择 运行 > 运行到小程序
  2. 选择你的小程序平台(如微信、支付宝等)。
  3. HBuilderX 会自动打开该平台的开发者工具,并加载你的应用。

4.配置微信小程序的AppID:

每一个小程序都有一个唯一的 AppID,它用于标识该小程序,并与微信平台进行关联。当你在微信开发者工具或真实环境中访问小程序时,系统需要通过 AppID 来确定这个小程序的身份。没有 AppID,微信无法识别和加载你的程序。

  • 登录微信公众平台,注册并创建一个小程序。
  • 在小程序的管理后台,你可以找到你的 AppID,它是一个由字母和数字组成的字符串。

在 uni-app 中,你需要在 manifest.json 文件中配置你的 AppID

{
  "mp-weixin": {
    "appid": "your-app-id-here"
  }
}

5.配置页面路由:

在 uni-app 中,页面和路由是通过 pages.json 文件来配置的。你可以在该文件中设置页面路径和页面的导航栏配置。

pages.json 配置示例

{
  "pages": [
    {
      "path": "pages/index/index",
      "style": {
        "navigationBarTitleText": "Home"
      }
    },
    {
      "path": "pages/about/about",
      "style": {
        "navigationBarTitleText": "About"
      }
    }
  ]
}
  • "path":指定页面的路径。
  • "style":设置页面的样式和配置(如导航栏标题)。

我们可以在 pages 文件夹中创建一个新页面,如 about.vue,然后在 pages.json 中配置它。 

6.pinia的使用:

uni-app 中使用 Pinia 进行持久化存储,可以确保当用户刷新页面或重新打开应用时,状态数据不会丢失。

在main.ts文件中导入pinia:

在 main.ts 中,我们创建了一个 Vue 应用实例,并将 Pinia 插件应用到该实例。这里的代码主要是进行 应用初始化,将 Pinia 状态管理库与 Vue 应用关联。app.use(pinia) 使得整个 Vue 应用都能够访问 Pinia 的状态管理功能。

Pinia 作为一个插件,通过 app.use(pinia) 的方式加入到 Vue 的应用中,使得应用中的所有组件都可以访问到 Pinia 中定义的状态。

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,
  }
}

随后在index.ts文件中导入pinia需要的配置代码:

在 store/index.ts 中,我们创建了 Pinia 实例,并且使用了 pinia-plugin-persistedstate 插件来实现持久化存储(即使刷新页面,应用的状态能够保留下来)。随后通过 export default pinia 将 pinia 实例导出,方便在 main.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'

通过 export * from './modules/member',我们将模块化的状态管理逻辑(如会员信息、购物车信息等)统一导出,这样就可以在应用中按需引入不同的状态模块,而无需每次都手动引入。 

最后我们在modules目录下创建ts文件:

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

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

    // 保存会员信息,登录时使用
    const setProfile = (val: any) => {
      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)
    //     }
    //   }
    // }
    // 网页端配置: process.env.VUE_APP_PLATFORM 来判断当前平台
      persist: process.env.VUE_APP_PLATFORM === 'h5' ? true : {
        storage: {
          getItem(key) {
            return uni.getStorageSync(key); // 同步
          },
          setItem(key, value) {
            uni.setStorageSync(key, value); // 同步
          }
        }
      }
  },
)

当平台不是 H5 时,persist 选项被设置为一个自定义的存储对象,其中包含 getItemsetItem 方法,用于指定如何读取和写入存储。这里使用的是 uni.getStorageSyncuni.setStorageSync

有关storage的知识可以跳转下面链接:uni.setStorage(OBJECT) @setstorage | uni-app官网

随后我们就可以在vue项目文件中来使用持久化存储的数据:

<script setup lang="ts">
import { useMemberStore } from '@/stores';
const memberStore = useMemberStore();
</script>

<template>
  <view class="my">
    <view>会员信息:{
  { memberStore.profile }}</view>
    <button
      @tap="
        memberStore.setProfile({
          username: '记得开心一点嘛',
          token : '12345'
        })
      "
      size="mini"
      plain
      type="primary"
    >
      保存用户信息
    </button>
    <button @tap="memberStore.clearProfile()" size="mini" plain type="warn">清理用户信息</button>
  </view>
</template>

<style lang="scss">
//
</style>

7.拦截器的使用:

在 /utils/http.ts 文件内编写代码: 

import { useMemberStore } from "@/stores";
const baseURL = "https://pcapi-xiaotuxian-front-devtest.itheima.net";

// 添加拦截器
const httpInterceptor = {
  // 拦截前触发,该方法会在每次发起 HTTP 请求之前被调用
  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
    }
    console.log(options);
  },

  // 响应拦截器
  response: {
    invoke(response: UniApp.RequestSuccessCallbackResult) {
      const res = response.data;
      const statusCode = response.statusCode;

      // 1.统一处理 401 错误,跳转到登录页
      if (statusCode === 401) {
        const memberStore = useMemberStore();
        memberStore.clearProfile(); // 清除用户信息
        uni.navigateTo({
          url: '/src/pages/login/login',
        });
        uni.showToast({
          title: '登录已过期,请重新登录!',
          icon: 'none',
        });
        return Promise.reject('登录已过期');
      }

      // 2.其他状态码处理
      if (statusCode >= 200 && statusCode < 300) {
        // 业务处理成功(如状态码200-299),但可能返回的是业务错误
        if (res.code !== '0') { // 假设 `code` 为 '0' 表示成功
          uni.showToast({
            title: res.msg || '操作失败,请稍后再试',
            icon: 'none',
          });
          return Promise.reject(res); // 业务错误,直接拒绝Promise
        }
        return res; // 成功的响应数据,返回
      }

      // 3.其他未知错误
      uni.showToast({
        title: '网络错误,请稍后再试',
        icon: 'none',
      });
      return Promise.reject('网络错误');
    }
  }
};

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

// 请求函数封装
interface Data<T>{
  code: string,
  msg: string,
  data: T
}
export const http = <T>(options:UniApp.RequestOptions) => {
  // 1.返回 Promise 对象
  return new Promise<Data<T>>((resolve,reject)=>{
    uni.request({
      ...options,
      // 2.请求成功
      success(res){

        if(res.statusCode >= 200 && res.statusCode < 300){
          // 获取数据成功,调用 resolve
          resolve(res.data as Data<T>) // 断言
        }else if(res.statusCode === 401){
          // 401错误,调用 reject,清理用户信息并跳转到登录页
          const memberStore = useMemberStore()
          memberStore.clearProfile();
          // 跳转
          uni.navigateTo({
            url: '/src/pages/login/login'
          })
          reject(res)
        }else{
          // 通用错误,调用 reject
          uni.showToast({
            icon: 'none',
            title: (res.data as Data<T>).msg || '请求错误'
          })
          reject(res)
        }
      },
      // 响应失败
      fail(err){
        // 网络错误,调用reject
        uni.showToast({
          icon: 'none',
          title: '网络错误,换个网络试试'
        })
        reject(err)
      }
    })
  })
}

①请求拦截器 (invoke):用于在请求发送之前对请求进行修改和增强,比如拼接请求 URL、设置请求头、添加 token 等。

②响应拦截器(response.invoke):如果响应的状态码是 401,说明用户的 token 过期或未授权,清除用户信息,并跳转到登录页面。

③拦截器的注册:使用 uni.addInterceptor 注册请求和上传文件请求的拦截器。通过拦截器,对请求和响应做统一处理,减少了重复代码。

④封装请求函数 (http):使用 uni.request 封装一个返回 Promise 的 HTTP 请求函数,统一处理请求成功和失败的逻辑,并根据响应的状态码进行不同的处理。

下面我们来分段解析一下上述代码: 

(1)定义拦截器:

①请求拦截器: 

invoke 方法:这是一个请求拦截器的回调函数,它在每次发起 HTTP 请求之前都会被调用。你可以在此修改请求的配置,加入统一的参数、头部信息等。 

const httpInterceptor = {
  // 拦截前触发,该方法会在每次发起 HTTP 请求之前被调用
  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, // ...options.header 是 JavaScript 的扩展运算符语法
                         // 它用于将原来的请求头属性保留并展开,同时可以新增或覆盖某些字段。
      'source-client': 'miniapp', // 添加 source-client 标识
    };
    // 4.添加 token 请求头标识
    const memberStore = useMemberStore();
    const token = memberStore.profile?.token;
    if (token) {
      options.header.Authorization = token;
    }
    console.log(options); // 在控制台打印请求的配置信息,便于调试
  }
};

 ②响应拦截器:

httpInterceptor 对象中的 response 属性包含响应拦截器的逻辑,它是一个对象,负责处理请求返回的响应。response 内部又包含一个 invoke 方法。 

// 添加拦截器
const httpInterceptor = {
  // 响应拦截器
  response: {
    invoke(response: UniApp.RequestSuccessCallbackResult) {
      const res = response.data;
      const statusCode = response.statusCode;

      // 1.统一处理 401 错误,跳转到登录页
      if (statusCode === 401) {
        const memberStore = useMemberStore();
        memberStore.clearProfile(); // 清除用户信息
        uni.navigateTo({
          url: '/src/pages/login/login',
        });
        uni.showToast({
          title: '登录已过期,请重新登录!',
          icon: 'none',
        });
        return Promise.reject('登录已过期');
      }

      // 2.其他状态码处理
      if (statusCode >= 200 && statusCode < 300) {
        // 业务处理成功(如状态码200-299),但可能返回的是业务错误
        if (res.code !== '0') { // 假设 `code` 为 '0' 表示成功
          uni.showToast({
            title: res.msg || '操作失败,请稍后再试',
            icon: 'none',
          });
          return Promise.reject(res); // 业务错误,直接拒绝Promise
        }
        // 如果是登录成功接口,保存用户信息到 Pinia
        if (response.config.url.includes('/login')) { // 判断是否是登录接口
          const memberStore = useMemberStore();
          memberStore.setProfile(res.data.profile); // 假设返回的数据中有 profile 字段
          // 显示登录成功的提示
          uni.showToast({
            title: '登录成功',
            icon: 'none',
          });

          // 跳转到首页
          uni.switchTab({
            url: '/src/pages/home/home', // 假设首页的路径是 '/src/pages/home/home'
          });
        }

        return res; // 成功的响应数据,返回
      }

      // 3.其他未知错误
      uni.showToast({
        title: '网络错误,请稍后再试',
        icon: 'none',
      });
      return Promise.reject('网络错误');
    }
  }
};

invoke 是响应拦截器的主要函数,它接收一个参数 response,这个参数是 UniApp 中的请求成功回调结果(UniApp.RequestSuccessCallbackResult 类型),包含了返回的数据、状态码等信息。

  • response.data:请求返回的实际数据(通常是后台返回的业务数据)。
  • response.statusCode:响应的 HTTP 状态码。

判断状态码是否为 401。通常401 状态码表示用户未授权或登录已过期,需要重新登录。通过 useMemberStore 获取当前用户的状态管理(Pinia store)并清除用户的个人资料信息,确保用户在被强制退出登录后,清除缓存的登录信息,防止未授权访问。

我们需要在 Pinia 中创建一个 setProfile 方法来保存用户信息。假设你的 profile 字段包含了用户的登录信息(如 token、用户名等)。 

import { defineStore } from 'pinia';

export const useMemberStore = defineStore('member', {
  state: () => ({
    profile: null as { token: string; name: string; email: string } | null, // 假设 profile 包含用户信息
  }),
  actions: {
    setProfile(profile: { token: string; name: string; email: string }) {
      this.profile = profile;
    },
    clearProfile() {
      this.profile = null;
    },
  },
});

(2)使用 uni.addInterceptor 添加拦截器:

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

'request':用于普通的 HTTP 请求。

'uploadFile':用于文件上传请求。

'downloadFile':用于文件下载请求。

'uploadTask':用于上传任务。

例如,uni.addInterceptor('request', httpInterceptor) 是为所有的普通 HTTP 请求添加 httpInterceptor 拦截器,而 uni.addInterceptor('uploadFile', httpInterceptor) 是为文件上传请求添加同样的拦截器。

uni.addInterceptor('request', httpInterceptor) 中的 httpInterceptor 是一个包含了请求拦截和响应拦截的对象。当你注册 httpInterceptor 对象时,uni.addInterceptor 会自动识别其中的 invoke 方法(用于请求拦截)和 response.invoke 方法(用于响应拦截)。

 (3)请求函数封装: 

interface Data<T> {
  code: string;
  msg: string;
  data: T;
}

Data<T>:这是一个泛型接口,用于定义请求成功后的数据结构。codemsg 是 API 返回的状态码和消息,data 是返回的实际数据。通过泛型 <T>,我们可以灵活地处理不同类型的响应数据。

(4)请求封装:

export const http = <T>(options: UniApp.RequestOptions) => {
  // 1.返回 Promise 对象
  return new Promise<Data<T>>((resolve, reject) => {
    uni.request({
      ...options, // 2.将传入的请求配置(options)解构并传入 uni.request
      // 通过 ...options 将传入的 options 配置对象解构并传给 uni.request
      // 这样可以动态修改请求的各项设置(如 URL、请求头等)。

这段代码是一个 uni-app 中的请求封装,使用了 Promiseuni.request 来处理 HTTP 请求。它的功能是向服务器发起请求并根据响应结果执行不同的逻辑

return new Promise<Data<T>>((resolve, reject) => {...})

return new Promise() 的作用是在你封装的 API 请求函数中使用 Promise 对象进行异步操作的封装。这是因为 uni.request 本身是一个基于回调的异步操作,而为了更好地与现代 JavaScript 的 async/await 语法兼容,并确保能够统一处理请求结果(成功或失败),需要将其包装成 Promise。这样,调用者就可以像调用普通 Promise 那样使用 thencatch,或者使用 await 来处理请求结果。Promise 允许链式调用,thencatch 可以用来处理成功和失败的逻辑。这让你可以对请求结果进行一系列的处理,比如跳转、提示错误等。


该函数返回一个 Promise 对象,类型为 Data<T>,表示异步操作的最终结果Data<T> 是一个接口,包含了 codemsgdata 三个字段,其中 data 的类型是泛型 T,即返回的数据类型。resolve 用于处理成功的回调,reject 用于处理失败的回调。

uni.request({
      ...options,
      // 2.请求成功
      success(res){

        if(res.statusCode >= 200 && res.statusCode < 300){
          // 获取数据成功,调用 resolve
          resolve(res.data as Data<T>) // 断言
        }else if(res.statusCode === 401){
          // 401错误,调用 reject,清理用户信息并跳转到登录页
          const memberStore = useMemberStore()
          memberStore.clearProfile();
          // 跳转
          uni.navigateTo({
            url: '/src/pages/login/login'
          })
          reject(res)
        }else{
          // 通用错误,调用 reject
          uni.showToast({
            icon: 'none',
            title: (res.data as Data<T>).msg || '请求错误'
          })
          reject(res)
        }
      }
}

①success(res)

当请求成功并且响应返回时,success 回调函数会被触发,res 是响应的结果对象。

②resolve(res.data as Data<T>)

如果响应成功且 statusCode 合法,调用 resolve 返回数据,res.data 是服务器返回的数据。as Data<T> 是 TypeScript 的类型断言,告诉编译器 res.data 确实符合 Data<T> 类型,这样可以确保返回的数据结构是我们期望的。

uni.navigateTo({ url: '/src/pages/login/login' })

跳转到登录页面,让用户重新登录。

reject(res)

调用 reject,将响应对象 res 作为参数传递,表示请求失败。后续可以通过 catch 来处理这个错误。

uni.showToast({ icon: 'none', title: (res.data as Data<T>).msg || '请求错误' })

使用 uni.showToast 显示一个提示消息,提示用户请求出错。消息内容是从 res.data 中提取的 msg 字段(如果存在),如果没有,则使用默认消息 '请求错误'

fail(err) {
        // 网络错误,调用 reject
        uni.showToast({
          icon: 'none',
          title: '网络错误,换个网络试试'
        });
        reject(err);
}

fail(err)

fail 回调函数用于处理请求失败的情况,如网络不可用、请求超时等错误。 

(5)发起 HTTP 请求并处理返回的数据:

<script setup lang="ts">
import { useMemberStore } from '@/stores'
import '@/utils/http'
import { http } from '@/utils/http';
const memberStore = useMemberStore()
const getData = async () =>{
  const res = await http<string[]>({
    method:'GET',
    url: '/home/banner',
    header : {},
  })
  console.log("请求成功",res);
}
</script>

<template>
  <view class="my">
    <view>会员信息:{
  { memberStore.profile }}</view>
    <button
      @tap="
        memberStore.setProfile({
          nickname: '黑马先锋',
          token : '12345'
        })
      "
      size="mini"
      plain
      type="primary"
    >
      保存用户信息
    </button>
    <button @tap="memberStore.clearProfile()" size="mini" plain type="warn">清理用户信息</button>
    <button @tap="getData()" size="mini" plain type="warn">测试请求</button>
  </view>
</template>

<style lang="scss">
//
</style>

await http<string[]>({...})

调用之前引入的 http 函数发起请求。这里传入了请求的配置:

  • method: 'GET':请求方法是 GET,意味着从服务器获取数据。
  • url: '/home/banner':请求的 URL 地址,这里是请求首页的横幅数据。
  • header: {}:请求头,这里为空对象,表示没有添加额外的请求头(实际应用中可能需要添加认证信息、请求类型等)。

await

等待 http 请求返回的结果。由于 http 返回的是一个 Promise 对象,await 会让函数暂停,直到 Promise 被解决(即请求完成)。

const res

请求的响应结果会赋值给 res,类型是 string[](字符串数组)。这意味着我们期望返回的是一个字符串数组,可能是首页的横幅数据。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

记得开心一点嘛

您的打赏是对我最大的鼓励与期待

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

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

打赏作者

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

抵扣说明:

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

余额充值