章
目
录
uniapp中的uni.addInterceptor
是个非常实用的API,可以给特定的异步API方法添加拦截器,通过在方法执行前后插入自定义逻辑,实现权限校验、日志记录、数据预处理等功能。接下来,我们详细了解下它的具体用法和在实际项目中的应用。下面先附上官方文档链接,方便大家查阅更详细的信息。
uni.addInterceptor
有多个参数,每个参数都有不同的作用:
- invoke:类型为Function,非必填项。它会在拦截前触发,可用于在异步API方法执行前对参数进行处理。
- returnValue:同样是Function类型,非必填。在方法调用后触发,主要用于处理返回值。
- success:Function类型,非必填。这是成功回调拦截,当异步API方法执行成功时会被调用。
- fail:Function类型,非必填。用于失败回调拦截,在异步API方法执行失败时触发。
- complete:Function类型,非必填。完成回调拦截,无论异步API方法执行成功与否,都会在最后调用它。
一、项目实战应用
(一)uni.request拦截器
在实际开发中,uni.request
用于发起网络请求,通过拦截器可以对请求和响应进行统一处理。比如,我们可以设置一个基础URL,在每次请求前自动拼接完整的URL,同时对请求结果进行错误上报。
const BASE_URL = 'https://www.example.com/'
const httpInterceptor: UniNamespace.InterceptorOptions = {
// 在request触发前,拼接完整的URL
invoke(args) {
args.url = BASE_URL + args.url
},
// 处理请求成功的情况,如果接口返回的data中code符合特定值,进行错误上报
success(result) {
console.log('interceptor-success',result)
if(result.data.code === xxx){
errorReport(result.data.msg)
}
},
// 处理请求失败的情况,进行错误上报
fail(err) {
console.log('interceptor-fail',err)
errorReport()
},
// 无论请求成功或失败,都会执行这里的逻辑
complete(res) {
console.log('interceptor-complete',res)
}
}
// 进行错误上报的函数
function errorReport(errMsg?: string){
uni.showToast({
icon: "none",
title: errMsg || "网络错误,换个网络试试",
});
customReport({
msg: 'xxxx'
})
}
为了方便使用这个拦截器,我们可以把它封装起来:
export const requestInterceptor = {
install() {
// 对request请求进行拦截
uni.addInterceptor("request", httpInterceptor);
// 对uploadFile文件上传操作也进行同样的拦截处理
uni.addInterceptor("uploadFile", httpInterceptor);
},
};
在这段代码里,invoke
函数负责拼接URL,success
和fail
函数分别处理请求成功和失败时的错误上报,complete
函数用于记录请求完成的信息。通过requestInterceptor.install()
调用,就能对request
和uploadFile
操作生效。
(二)登录校验拦截器
在很多应用中,部分页面需要用户登录后才能访问。这时,我们可以利用拦截器来实现登录校验。
const loginRoute = "/pages/login/index";
// 定义需要登录才能访问的页面数组
let needLoginPages: string[] = [
"/pages/order/index",
];
// 判断用户是否登录的函数,这里返回false只是示例,实际需要根据业务逻辑实现
export function isLogged(): boolean {
return false;
}
// 黑名单登录拦截器,适用于大部分页面不需要登录,少部分页面需要登录的场景
const navigateToInterceptor: UniNamespace.InterceptorOptions = {
// 这里的url是 '/' 开头的,如 '/pages/index/index',与 'pages.json' 里面的path不同
invoke({ url }: { url: string }) {
// 提取url中的路径部分,去除参数
const path = url.split("?")[0];
// 判断当前路径是否在需要登录的页面数组中
const isNeedLogin = needLoginPages.includes(path);
if (!isNeedLogin) {
return true;
}
// 判断用户是否已经登录
const hasLogin = isLogged();
if (hasLogin) {
return true;
}
// 如果需要登录且用户未登录,跳转到登录页面
goLogin(url);
return false;
},
};
// 跳转到登录页面的函数,同时带上当前页面的url作为参数,方便登录后返回
function goLogin(redirect: string = "") {
uni.navigateTo({
url: `${loginRoute}?redirect=${encodeURIComponent(redirect)}`,
});
}
export const routeInterceptor = {
install() {
// 对navigateTo、reLaunch、redirectTo、switchTab等页面跳转方法进行拦截
uni.addInterceptor("navigateTo", navigateToInterceptor);
uni.addInterceptor("reLaunch", navigateToInterceptor);
uni.addInterceptor("redirectTo", navigateToInterceptor);
uni.addInterceptor("switchTab", navigateToInterceptor);
},
};
在这个登录校验拦截器中,invoke
函数会在页面跳转前被调用。它先判断目标页面是否需要登录,如果需要,再检查用户是否已登录。若用户未登录,就跳转到登录页面,并把当前页面的URL作为参数传递过去,以便登录成功后能返回原页面。
(三)uni.setStorage数据预处理
在使用uni.setStorage
存储数据时,有时需要对数据进行预处理。比如下面这个例子:
// 这是个数据处理函数,具体逻辑根据实际需求编写
function processingData(){
}
const storage: UniNamespace.InterceptorOptions = {
// 在数据存储前,对数据进行处理
invoke(args) {
console.log('存储数据前:', args);
args.data = processingData(args.data);
console.log('处理后的数据:', args.data);
},
// 数据存储成功时的回调
success() {
console.log('数据存储成功');
},
// 数据存储失败时的回调
fail(err) {
console.error('数据存储失败:', err);
}
}
同样,我们可以把这个拦截器封装起来,方便使用:
export const storageInterceptor = {
install() {
uni.addInterceptor("setStorage", storage);
},
};
在这个拦截器中,invoke
函数在数据存储前对args.data
进行处理,success
和fail
函数分别处理存储成功和失败的情况。
(四)借助拦截器修复快手小程序平台的一个bug
在快手小程序开发中,ks.setStorage
存在不支持储存proxy
对象的问题,会导致报错。我们可以利用拦截器来解决这个问题。
const setStorageInterceptor: UniNamespace.InterceptorOptions = {
// 在快手小程序平台下,将数据转换为JSON字符串再解析,避免存储proxy对象报错
invoke(args: { data: any }) {
// #ifdef MP-KUAISHOU
args.data = JSON.parse(JSON.stringify(args.data));
// #endif
},
success(args) {
// console.log(args, "========success=======");
},
fail(err) {
// console.log(err, "========fail=======");
},
};
/**
* 解决快手小程序setStorage不支持proxy对象的问题
* */
export const KuaiShouSetStorageProxyFixInterceptor = {
install() {
// 对setStorage操作进行拦截
uni.addInterceptor("setStorage", setStorageInterceptor);
},
};
在这段代码中,invoke
函数里通过#ifdef MP-KUAISHOU
条件判断,只有在快手小程序平台下才会对数据进行处理,将数据转换为JSON字符串再解析,从而避免存储proxy
对象时报错。
通过上述这些实例可以看出,uniapp的拦截器功能非常强大,在项目开发中合理运用它,能够提高代码的复用性和可维护性,大家一定要用起来。