1.封装小程序动画hook(支持异步调用)
import Taro from '@tarojs/taro';
import {useCallback, useEffect, useRef, useState} from 'react';
export default function useAsyncAnimation(id = 'default') {
const [animationData, setAnimationData] = useState({});
const animationInstance = useRef({});
const animationPromiseRef = useRef({});
const timer = useRef(null);
useEffect(() => {
return () => {
clearTimeout(timer.current);
};
}, []);
const getAnimation = useCallback(() => {
if (!animationInstance.current[id]) {
animationInstance.current[id] = Taro.createAnimation({
duration: 500,
timingFunction: 'ease',
});
}
return animationInstance.current[id];
}, [id]);
const animateStep = useCallback(
async (actions, options = {}) => {
// 如果已有动画在进行,等待它完成
if (animationPromiseRef.current[id]) {
await animationPromiseRef.current[id];
}
const anim = getAnimation();
animationPromiseRef.current[id] = new Promise((resolve) => {
// 执行动画动作
actions(anim);
// 设置动画步骤
anim.step({
duration: options.duration || 500,
timingFunction: options.timingFunction || 'ease',
delay: options.delay || 0,
});
timer.current = setTimeout(() => {
animationPromiseRef.current[id] = null;
resolve();
clearTimeout(timer.current);
}, options.duration || 500);
// 立即更新动画数据
setAnimationData(anim.export());
});
return animationPromiseRef.current[id];
},
[getAnimation, id],
);
const reset = useCallback(() => {
const anim = getAnimation();
anim.step({duration: 0});
setAnimationData(anim.export());
}, [getAnimation]);
return {
animationData,
animateStep,
reset,
};
}
调用案例
import {useAsyncAnimation} from '@hooks';
export default function GuaShark({onSubmit}) {
const {animationData: decAnime, animateStep: decAnimeStep} =
useAsyncAnimation('decBox');
useEffect(() => {
startAnime();
}, []);
const startAnime = () => {
await decAnimeStep((anim) => anim.opacity(0), {duration: 800});
await decAnimeStep((anim) => anim.opacity(1), {duration: 800});
}
return (
<View className='dec-box' animation={decAnime}></View>
)
}
2. 订单轮询
调用机制:支付成功的回调里轮询订单,确保订单是已支付状态。
export function paymentPoll(orderId, queryFuc, succCallBack) {
let attempts = 0;
let timer = null;
const maxAttempts = 10;
// 验证订单是否支付成功
const isPaymentSuccess = (order) => {
return order.status === 'paid';
};
// 显示加载提示
Taro.showLoading({
title: '支付确认中...',
mask: true,
});
// 执行轮询
const poll = async () => {
attempts++;
// 更新加载提示
Taro.showLoading({
title: `支付确认中...(${attempts}/${maxAttempts})`,
mask: true,
});
try {
const orderRes = await queryFuc(orderId);
if (isPaymentSuccess(orderRes?.data)) {
// 支付成功
Taro.hideLoading();
clearTimeout(timer);
Taro.showToast({
title: '支付成功',
icon: 'success',
duration: 2000,
});
// 执行成功回调
setTimeout(() => {
succCallBack(orderRes?.data);
}, 1500);
return;
}
// 检查是否支付失败
if (orderRes?.data?.status.status === 'created') {
Taro.hideLoading();
clearTimeout(timer);
Taro.showToast({
title: '支付失败',
icon: 'error',
duration: 3000,
});
return;
}
// 检查是否超过最大尝试次数
if (attempts >= maxAttempts) {
Taro.hideLoading();
clearTimeout(timer);
Taro.showToast({
title: '支付确认超时',
icon: 'none',
duration: 3000,
});
return;
}
// 继续轮询
timer = setTimeout(poll, 2000);
} catch (error) {
Taro.hideLoading();
clearTimeout(timer);
console.error('查询订单状态失败:', error);
Taro.showToast({
title: '网络错误,请稍后检查',
icon: 'none',
duration: 3000,
});
}
};
// 开始轮询
poll();
// 返回停止函数(可选)
return {
stop: () => {
if (timer) clearTimeout(timer);
Taro.hideLoading();
},
};
}
3.小程序分包
一、什么是分包?
小程序分包是指将小程序代码分成多个包,在构建时打包成不同的分包,用户使用时按需加载。
二、分包的优势
- 优化首次加载时间:主包只包含核心功能,分包按需加载
- 代码组织更清晰:功能模块化,便于团队协作
- 提高开发效率:可以并行开发不同分包
- 避免包体积过大:突破主包2M限制(微信小程序为例)
三、分包配置
1. 目录结构
text
project/
├── app.js
├── app.json
├── app.wxss
├── pages/ # 主包页面
│ ├── index/
│ └── logs/
├── packageA/ # 分包A
│ ├── pages/
│ │ ├── cat/
│ │ └── dog/
│ └── utils/
├── packageB/ # 分包B
│ ├── pages/
│ │ ├── apple/
│ │ └── banana/
│ └── components/
└── common/ # 公共代码(建议放主包)
2. app.json 配置示例
json
{
"pages": [
"pages/index",
"pages/logs"
],
"subpackages": [
{
"root": "packageA",
"pages": [
"pages/cat",
"pages/dog"
],
"name": "packA", // 分包别名(非必需)
"independent": false // 是否独立分包
},
{
"root": "packageB",
"pages": [
"pages/apple",
"pages/banana"
]
}
],
"preloadRule": {
"pages/index": {
"network": "all",
"packages": ["packageA"]
}
}
}
四、分包限制和注意事项
1. 包大小限制(微信小程序):
- 整个小程序所有分包大小不超过 20M
- 单个分包/主包大小不超过 2M
2. 打包原则:
-
主包:
app.js、app.json、app.wxss、tabBar页面、公共资源 -
分包:私有页面、组件、资源
-
引用规则:
- 分包不能引用其他分包的内容
- 分包可以引用主包内容
- 主包可以引用分包内容(通过
require等方式)