本篇内容介绍了“vue如何开发一个加载Button组件”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!
点击按钮时请求一些接口数据,而为了避免用户重复的点击我们通常会为这些按钮添加loading。这个添加loading
的功能本身时非常简单的,只要我们定义一个变量使用在Button
组件中即可,但在做后台管理类项目时,这样的按钮可能会有非常非常多,可能一个组件中,很多变量都是xxx_loading
,耗时耗力又不够优雅。
接下来,我们对Button
组件做一个简单的封装来解决这个耗时耗力又不够优雅的loading
问题。
此时,代码如下:
asyncFunc() {
return new Promise(resolve => {
setTimeout(() => {
resolve()
}, 2000)
})
},
handleTestModal() {
const that = this
this.$confirm({
title: '测试异步函数',
content: '异步函数延迟两秒结束',
async onOk() {
await that.asyncFunc()
}
})
},
看到这种效果后,就想到,如果可以封装一个
Button
组件,将需要执行的函数传入,组件中自动根据函数执行情况添加loading
效果岂不是非常的方便。
定义组件参数
这边就定义几个大家会常用到的参数:text(按钮文字)
、type(按钮类型)
、asyncFunc(按钮点击时执行的异步函数)
、delay(loading延迟)
,另外,还需要一个组件内部的loading
变量来控制我们Button
组件的状态,代码如下:
export default {
data() {
return {
loading: false
}
},
props: {
text: {
type: String,
default: '确定'
},
type: {
type: String,
default: 'primary'
},
delay: {
type: Number,
default: 0
},
asyncFunc: {
type: Function,
default: () => {}
}
},
}
使用antd
中的Button
组件进行二次封装
在我们的自定义LoadingButton
组件中,将上面定义的参数使用起来,并绑定一个click
事件,代码如下:
<template>
<Button :type="type" :loading="loading" @click="handleClick">
{{ text }}
</Button>
</template>
<script>
import { Button } from 'ant-design-vue'
export default {
components: {
Button
},
methods: {
handleClick() {}
}
}
</script>
判断异步函数asyncFunc
这一部分为整个组件最重要的一个部分,即我们如何去判断传入的函数是异步函数,当我们传入的
asyncFunc
函数是异步函数时,组件才需要添加loading的动画,那么我们应该如何去判断一个函数是否为异步函数呢?
参考antd
是如何实现的?
上面我们刚介绍了antd
的Modal
对话框中有类似的逻辑,那么不妨去阅读一下这部分相关的源码,看下antd
的实现方式:
// components/modal/ActionButton.jsx
onClick() {
const { actionFn, closeModal } = this;
if (actionFn) {
let ret;
if (actionFn.length) {
ret = actionFn(closeModal);
} else {
ret = actionFn();
if (!ret) {
closeModal();
}
}
if (ret && ret.then) {
this.setState({ loading: true });
ret.then(
(...args) => {
// It's unnecessary to set loading=false, for the Modal will be unmounted after close.
// this.setState({ loading: false });
closeModal(...args);
},
e => {
// Emit error when catch promise reject
// eslint-disable-next-line no-console
console.error(e);
// See: https://github.com/ant-design/ant-design/issues/6183
this.setState({ loading: false });
},
);
}
} else {
closeModal();
}
},
阅读antd
源码的实现,我们知道,判断一个函数是否是异步函数,可以通过判断函数是否有.then
(ret && ret.then
)方法,那么我们也可以类似的做一个判断,代码如下:
async handleClick() {
const asyncFunc = this.asyncFunc
if (!this.isFunc) {
return
}
const ret = asyncFunc()
// 如果是异步函数,则显示loading
if (ret && ret.then) {
this.loading = {
delay: this.delay
}
ret.finally(() => {
this.loading = false
})
}
}
测试LoadingButton
组件
到这里我们的最核心的组件逻辑就开发完成了,后面我们写一个demo来测试一下这个
LoadingButton
组件是否符合预期:demo代码如下:
<template>
<div>
<LoadingButton :delay="500" :asyncFunc="asyncFunc" />
</div>
</template>
<script>
import LoadingButton from './LoadingButton.vue'
export default {
data() {
return {
loading: false
}
},
components: {
LoadingButton
},
methods: {
asyncFunc() {
return new Promise(resolve => {
setTimeout(() => {
resolve()
}, 2000)
})
}
}
}
</script>
符合之前的预期效果,这样我们再有类似需要loading
的场景时,就可以直接使用LoadingButton
组件,将点击需要执行的异步函数传入即可,不需要再去定义loading
变量。
这个组件其实核心的代码非常少,也很容易读懂。由于最近在做一些业务这类场景比较多,感觉这个小组件还是挺实用的所以分享给大家,这里也是只对最重要的部分做了一个介绍,相信大家学会了之后也可以通过这个方式封装出符合自己实际场景需求的组件。最后,附上这个组件的完整代码:
<template>
<Button :type="type" :loading="loading" @click="handleClick">
{{ text }}
</Button>
</template>
<script>
import { Button } from 'ant-design-vue'
export default {
data() {
return {
loading: false
}
},
props: {
text: {
type: String,
default: '确定'
},
type: {
type: String,
default: 'primary'
},
delay: {
type: Number,
default: 0
},
asyncFunc: {
type: Function,
default: () => {}
}
},
components: {
Button
},
computed: {
isFunc() {
return typeof this.asyncFunc === 'function'
}
},
methods: {
async handleClick() {
const asyncFunc = this.asyncFunc
if (!this.isFunc) {
return
}
const ret = asyncFunc()
// 如果是异步函数,则显示loading
if (ret && ret.then) {
this.loading = {
delay: this.delay
}
ret.finally(() => {
this.loading = false
})
}
}
}
}
</script>
“vue如何开发一个加载Button组件”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注亿速云网站,小编将为大家输出更多高质量的实用文章!
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。