一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第14天,点击查看活动详情。
前言
昨天我们实现了小程序的登录拦截与白名单的处理,今天我们先优化一下昨天留下的坑,然后来编写一个父子组件间传递值得方法
关于在请求未完成的时候,传递token为空的问题处理——promise处理
我将从以下几个方面仔细解释一下原因和解决方案
问题产生的原因
我们按照一开始的方法调用后端接口的时候整个过程是异步的。此时我们在return值的时候,后端没有处理完我们的请求,我们的值不会发生变化
解决的方法——promise
我们在封装统一的request时,已经使用promise封装了,这里我们也使用promise解决异步请求未执行方法就向下执行的问题,大家如果不了解promise的话,可以自己查一下ES6的新特性,了解一下promise
最终的request/index.tsx
import Taro from "@tarojs/taro";
const white_res_code = [200, 10001, 10002];
const white_uri = ["/auth/login"];
import { loginByCode } from "../api/user";
function getTokenByApi() {
return new Promise((resolve) => {
Taro.login({
success: (res) => {
loginByCode(res.code).then((res) => {
resolve(res["token"]);
});
},
});
});
}
async function request(url, data, method): Promise<any> {
let notNeedTokenflag =
white_uri.filter((item) => url.includes(item)).length > 0;
let token = Taro.getStorageSync("token");
if (!notNeedTokenflag && (!token || token === "")) {
token = await getTokenByApi();
Taro.setStorageSync("token", token);
}
const header = {
"content-type": "application/json",
};
if (!notNeedTokenflag) {
header["Authorization"] = `Bearer ${token}`;
}
return new Promise((resolve) => {
let retryCount = Taro.getStorageSync("returCount") || 0;
if (retryCount >= 10) {
setTimeout(() => {
Taro.removeStorageSync("returCount");
}, 5000);
return Taro.showToast({
title: "您已被限制5秒内不可以访问接口",
icon: "none",
});
}
Taro.request({
url,
data,
method,
header,
})
.then((res) => {
if (res.statusCode === 200) {
const backEndRes = res.data;
const resCode = backEndRes.code;
if (!white_res_code.includes(resCode)) {
switch (resCode) {
case 500:
return Taro.showToast({
title: "请求失败,系统异常:" + backEndRes.msg,
icon: "none",
});
case 401:
Taro.removeStorageSync("token");
Taro.setStorageSync("returCount", retryCount + 1);
request(url, data, method);
return Taro.showToast({
title: "请求失败,请您登陆:" + backEndRes.msg,
icon: "none",
});
case 403:
Taro.removeStorageSync("token");
Taro.setStorageSync("returCount", retryCount + 1);
request(url, data, method);
return Taro.showToast({
title: "请求失败,暂无权限:" + backEndRes.msg,
icon: "none",
});
default:
return Taro.showToast({
title: "请求失败:" + res.data.error,
icon: "none",
});
}
} else {
resolve(backEndRes.data);
}
resolve(res.data);
} else {
Taro.showToast({ title: "请求失败:" + res.data.error, icon: "none" });
}
})
.catch((err) => {
Taro.showToast({ title: "网络错误,提示:" + err.errMsg, icon: "none" });
});
});
}
function get(url) {
return request(url, null, "GET");
}
function post(url, data) {
return request(url, data, "POST");
}
function del(url) {
return request(url, null, "DELETE");
}
function put(url, data) {
return request(url, data, "POST");
}
export { get, post, del, put };
复制代码
简单解释一下
- 在request方法前添加async标识它为异步函数
- 在调用获取token的地方添加await方法
- 修改获取token的方法,使其成为返回promise的方法
下面我们主要讲一下今天比较重点的内容,父子组件之间传值
业务场景
我们有很多的业务场景需要父子组件之间传值。比较常见的就是父组件获取出列表之后,点开字组件时传入父组件来获取详情。在子组件更新完对应的数据之后,需要刷新父组件或者从父组件中将子组件关闭。
先看看vue常用的方式
- 通过父组件ref到子组件然后调用子组件的方法赋值,例如
this.$refs("child").open(id)
- 通过子组件的prop属性传参,例如
<child id={chooseData.id}>
- 状态管理器传参,这种传参方式比较少,但是一般复杂度比较高的项目往往用的比较多
使用基于react的父子组件传参的实现
购物车index页面
import { View, Text } from "@tarojs/components";
import { useEffect, useState } from "react";
import ShopCartItem from "./shop-cart-item";
import "./index.scss";
export default function ShopCart() {
const [shopCartList, setShopCartList] = useState([]);
useEffect(() => {
setShopCartList([
{ id: "1", name: "第1个商品", price: 100, num: 4 },
{ id: "2", name: "第2个商品", price: 200, num: 3 },
{ id: "3", name: "第3个商品", price: 300, num: 2 },
{ id: "4", name: "第4个商品", price: 400, num: 1 },
]);
}, []);
return (
<View className="shop-cart">
{shopCartList.map((item,index) => (<ShopCartItem item={item}></ShopCartItem>)
)}
<Text>共{shopCartList.length}条数据</Text>
</View>
);
}
复制代码
购物车item页面
import { View, Text } from "@tarojs/components";
import { Component } from "react";
import "./index.scss";
class ShopCartItem extends Component {
constructor(props) {
super(props);
item: {
}
}
render() {
const item = this.props["item"];
return (
<View className="shop-cart-item">
<Text>商品名称{item.name}</Text>
</View>
);
}
}
export default ShopCartItem;
复制代码
结语
每天的时间都是不太充足,每天都徘徊在鸽了的边缘,今天先完成父数据传子组件的需求吧,明天补充一下子传父的代码(其实开发了,但是功能没实现)。欢迎大家多多关注点赞!