其实uni-app中内置的uni.request()已经很强大了,简单且好用。为了让其更好用,同时支持拦截器,支持Promise 写法,特对其进行封装。同时支持H5和小程序环境,更好用啦。文中给出使用示例,可以看到使用变得如此简单。在此分享给有需要的小伙伴,需要的可以点击收藏。
前言
在uni-app中,常见的网络库主要是基于uni-app内置的uni.request()方法,这是一个统一的网络请求接口,支持HTTP和HTTPS协议,可以处理GET、POST等请求方法。这个API提供了基本的HTTP请求功能,可以满足大部分应用的网络通信需求。除此之外,由于uni-app是基于Vue.js的,所以也可以使用一些适用于前端的JavaScript网络库如axios 第三方库,支持Promise API,有丰富的拦截器、配置选项和错误处理。
为了兼容uni-app生态和微信小程序,推荐使用uni-app内置的uni.request()。
原因有以下几点:
集成性:uni.request()是uni-app框架的一部分,与uni-app的其他组件和服务紧密集成,使用起来更加方便,不需要额外安装和配置。
兼容性:uni.request()已经为uni-app的不同平台(包括iOS、Android、H5等)做了优化和适配,可以直接使用,而不需要担心跨平台兼容性问题。
简单易用:uni.request()的API设计简洁,易于理解和使用,对于大多数常规的网络请求任务,它提供了足够的功能。
性能:由于是原生实现,uni.request()通常会有更好的性能表现,特别是在处理数据量较大或需要高效网络交互的场景。
维护成本:使用uni.request(),开发者可以专注于业务逻辑,而不需要关注网络库的更新和维护。
如果你的项目中已经大量使用了axios,或者你需要利用axios提供的特定功能(如拦截器、取消请求、超时重试等),那么可以考虑继续使用axios。但需要注意的是,axios在uni-app中可能需要进行一些适配工作,尤其是小程序端。
网络库封装
原始的uni.request使用,举例如下:
methods(){ getSwiperList() { //方法名 uni.request({ url: "你的数据接口", success: (res) => { //如果成功了 // 打印数据 console.log(res); // 如果请求成功,就把数据转存起来,方便页面使用 this.swipeList = res.data.message; }, fail: (res) => { console.log('请求失败'); } }) }}
可以看出,虽然简单,但是不封装一下还是不够简洁。尤其是不支持Promise写法。
原生态写法太过于繁琐。假如我们一个项目有多个接口,那我们每一个接口,就要写一个uni.request({})方法,而每个方法就要包含url、data、method、header,等等,这样代码很明显就变得多而杂。而用了Promise写法,在编写代码时,我们就可以使用async和await写法来简化请求接口代码了。
封装后的使用,可以看出多么简单,示例如下:
// api.js 获取当前正在热映电影export const getNowHot = async (start,count,city) => { try { console.log('getNowHot request'); const response = await uni.$http.post('/movie/in_theaters',{ apikey: uni.$apiKey,city:city,start:start,count:count}); console.log(response); if (response.statusCode !== 200) { uni.showToast({ title: '数据请求失败! ', duration: 1500, icon: 'none', }); return []; } return response.data; } catch (error) { console.error('Network request failed:', error); uni.showToast({ title: '网络请求失败! ', duration: 1500, icon: 'none', }); return []; }};//index.vue 接口调用mounted() { console.log("mounted") //轮播图接口调用 getSwiperList().then(item => { this.swiperList = item; }); //获取豆瓣top250 getTop250(0,5).then(item => { //this.swiperList = item; }); // 获取最近热播 getNowHot(0,2,"郑州").then(result => { //this.swiperList = item; console.log("getNowHot,result:"); console.log(result); }); }
上述示例为使用豆瓣影视的接口,获取郑州正在热映的电影。豆瓣接口curl测试如下:
curl --location --request POST 'https://api.douban.com/v2/movie/in_theaters?start=0&count=1' --data-urlencode 'apikey=xxxxxxxxx'
接口封装
//utils/http.jsclass Request { constructor(options = {}) { // 请求的根路径 this.baseUrl = options.baseUrl || '' // 请求的 url 地址 this.url = options.url || '' // 请求方式 this.method = 'GET' // 请求的参数对象 this.data = null // header 请求头 this.header = options.header || {} this.beforeRequest = null this.afterRequest = null } // 添加对header的支持 _mergeHeaders(customHeader = {}) { return Object.assign({}, this.header, customHeader); // 合并默认header和自定义header } get(url, data = {}) { this.method = 'GET' this.url = this.baseUrl + url this.data = data return this._() } post(url, data = {},header = {}) { this.method = 'POST' this.url = this.baseUrl + url this.data = data this.header = this._mergeHeaders(header) // 合并header return this._() } put(url, data = {}) { this.method = 'PUT' this.url = this.baseUrl + url this.data = data return this._() } delete(url, data = {}) { this.method = 'DELETE' this.url = this.baseUrl + url this.data = data return this._() } _() { // 清空 header 对象 this.header = {} // 请求之前做一些事 this.beforeRequest && typeof this.beforeRequest === 'function' && this.beforeRequest(this) // 发起请求 return new Promise((resolve, reject) => { let weixin = wx // 适配 uniapp if ('undefined' !== typeof uni) { weixin = uni } weixin.request({ url: this.url, method: this.method, data: this.data, header: this.header, success: (res) => { resolve(res) }, fail: (err) => { reject(err) }, complete: (res) => { // 请求完成以后做一些事情 this.afterRequest && typeof this.afterRequest === 'function' && this.afterRequest(res) } }) }) }}export const $http = new Request()
如何使用
在main.js中引入该模块封装,并将其挂在全局的uni.$http上即可。如下:
import App from './App'// #ifndef VUE3import Vue from 'vue'Vue.config.productionTip = falseApp.mpType = 'app'const app = new Vue({ ...App})app.$mount()// #endif// #ifdef VUE3import { createSSRApp } from 'vue'export function createApp() { const app = createSSRApp(App) return { app }}// #endif import { $http } from './utils/http.js'uni.$http = $http// 配置请求根路径$http.baseUrl = 'https://api.douban.com/v2'uni.$apiKey = 'xxxxxxxxx'// 请求开始之前做一些事情$http.beforeRequest = function (options) { uni.showLoading({ title: '数据加载中...', })} // 请求完成之后做一些事情$http.afterRequest = function () { uni.hideLoading()}
在其他文件夹,如api文件夹下,可以愉快的写接口啦,举例如下:
// api/home.jsexport const getSwiperList = async () => { try { console.log('getSwiperList request'); const response = await uni.$http.get('/api/v1/home/swiperdata'); console.log(response.data.list); if (response.statusCode !== 200) { uni.showToast({ title: '数据请求失败! ', duration: 1500, icon: 'none', }); return []; } return response.data.list; } catch (error) { console.error('Network request failed:', error); uni.showToast({ title: '网络请求失败! ', duration: 1500, icon: 'none', }); return []; }};export const getTop250 = async (start,count) => { try { console.log('getTop250 request'); const response = await uni.$http.post('/movie/top250', {apikey: uni.$apiKey, start:start,count:count},{'Content-Type': 'application/x-www-form-urlencoded'}); console.log(response); if (response.statusCode !== 200) { uni.showToast({ title: '数据请求失败! ', duration: 1500, icon: 'none', }); return []; } return response.data.list; } catch (error) { console.error('Network request failed:', error); uni.showToast({ title: '网络请求失败! ', duration: 1500, icon: 'none', }); return []; }};// 获取当前正在热映电影export const getNowHot = async (start,count,city) => { try { console.log('getNowHot request'); const response = await uni.$http.post('/movie/in_theaters',{ apikey: uni.$apiKey,city:city,start:start,count:count}); console.log(response); if (response.statusCode !== 200) { uni.showToast({ title: '数据请求失败! ', duration: 1500, icon: 'none', }); return []; } return response.data; } catch (error) { console.error('Network request failed:', error); uni.showToast({ title: '网络请求失败! ', duration: 1500, icon: 'none', }); return []; }};
写在最后
最后,附上完整的工程项目模版。为了更通用,这个是从我的业余项目(爱看电影app小程序) 中抽离出来的工程模版和示例。带网络库的封装和可用的豆瓣影视接口封装,以及个人中心页面。可以作为工程模版或小项目练手,分享给有需要的小伙伴。
资源下载地址:
https://download.csdn.net/download/qq8864/89377440
其他资源
豆瓣接口API使用_热映电影api接口怎么用-CSDN博客
https://feizhaojun.com/?p=3813
Movie API Doc | doubanapi
uniapp 请求解决跨域问题_uniapp跨域请求-CSDN博客
豆瓣API常用api总结实例_douban api-CSDN博客
组件使用的入门教程 | uni-app官网
微信小程序 --- wx.request网络请求封装-CSDN博客