「这是我参与2022首次更文挑战的第10天,活动详情查看:2022首次更文挑战」
写在前面
前几天,有小伙伴在我们的issue下留言,大致意思是询问能否给button组件添加一个自动加载的事件,也就是说当click的方法返回一个Promise时自动去维护按钮的loading状态,从而省去在外部手动维护loading的工作。
这个功能听着就很实用,自然而然的就进了我们的feature。
本文将从我cr以及refactor这部分功能的心得来分享一下。
设计思路
-
我们需要添加一个
auto-loading的props用来标记是否是否开启自动loading -
在组件内部维护一个
pending用于标记是否显示loading -
对
onClick&&onTouchstart事件进行处理,为其添加维护pending的逻辑
代码实现
我们新增一个attemptAutoLoading函数用来处理自动加载的逻辑。
该函数接收onClick&&onTouchstart事件的返回值。
如果开起了自动加载,那么到这个方法内我们先开启loading,然后使用Promise.resolve将函数返回值包裹成Promise
最终在finally中,将loading关闭。(组件并不关新Promise是resolve还是reject,只要结束就关闭loading)
Promise.resolve(value)方法返回一个以给定值解析后的Promise对象。如果这个值是一个 promise ,那么将返回这个 promise ;如果这个值是thenable(即带有"then"方法),返回的promise会“跟随”这个thenable的对象,采用它的最终状态;否则返回的promise将以此值完成。此函数将类promise对象的多层嵌套展平。
const pending: Ref<boolean> = ref(false)
const attemptAutoLoading = (result: any) => {
if (props.autoLoading) {
pending.value = true
Promise.resolve(result).finally(() => {
pending.value = false
})
}
}
const handleClick = (e: Event) => {
const { loading, disabled, onClick } = props
if (!onClick || loading || disabled || pending.value) {
return
}
attemptAutoLoading(onClick(e))
}
单元测试
完成功能后,对应的单元测试也是必不可少的,我们来逐行解析看看auto-loading的单测该如何编写。
test('test button auto-loading', async () => { 定义一个 auto-loading 的单元测试
const onClick = () => { // 声明 onClick 方法 是一个有100ms延迟的异步方法
return new Promise((resolve) => {
setTimeout(resolve, 100)
})
}
const onTouchstart = () => { // 声明 onTouchstart 方法 是一个有100ms延迟的异步方法
return new Promise((resolve) => {
setTimeout(resolve, 100)
})
}
const wrapper = mount(VarButton, { // 加载按钮组件
props: {
autoLoading: true, // 开启自动loading
onClick,
onTouchstart,
},
})
await trigger(wrapper, 'click') // 触发 onClick 方法
expect(wrapper.find('.var-loading').exists()).toBeTruthy() // 检查是否开启了 loading
await delay(100) // 等待 100ms
expect(wrapper.find('.var-loading').exists()).toBeFalsy() // 检查是否关闭了 loading
await trigger(wrapper, 'touchstart') // 触发 onTouchstart 方法
expect(wrapper.find('.var-loading').exists()).toBeTruthy() // 检查是否开启了 loading
await delay(100)
expect(wrapper.find('.var-loading').exists()).toBeFalsy() // 检查是否关闭了 loading
expect(wrapper.html()).toMatchSnapshot() // 对比快照
wrapper.unmount() // 卸载按钮组件
})
最后
感谢 a145789 的建议。
varlet 这是我们的仓库地址欢迎大家star && pr。
issue 也欢迎大家提出宝贵的意见与建议以帮助我们更好的发展。