This article will guide you step by step in developing a super practical vueLoadingButton component--LoadingButton. I hope it will be helpful to everyone.
Component background
In daily work, we often encounter a scene:
Request some interface data when clicking a button, and in order to avoid repeated clicks by users, we usually add loading to these buttons. The function of adding loading
itself is very simple. As long as we define a variable and use it in the Button
component, but when doing background management projects, such a button may There are many, many variables in one component may be xxx_loading
, which is time-consuming, labor-intensive and not elegant enough.
Next, we make a simple encapsulation of the Button
component to solve this time-consuming, labor-intensive and inelegant loading
problem. (Learning video sharing: vue video tutorial)
Inspiration source
We are using Antd
Modal
dialog box, when ouronOk
isasynchronous function
, the OK button ofModal
will automatically addloading
Effect, close the pop-up window after the function execution is completed, like this:
At this time, the code is as follows:
asyncFunc() { return new Promise(resolve => { setTimeout(() => { resolve() }, 2000) }) }, handleTestModal() { const that = this this.$confirm({ title: '测试异步函数', content: '异步函数延迟两秒结束', async onOk() { await that.asyncFunc() } }) },
After seeing this effect, I thought that if I could encapsulate a
Button
component and pass in the function that needs to be executed, the component would automatically addloading
according to the function execution. What effect would it have? Not very convenient.
Implement LoadingButton
Define component parameters
Just define a few here Commonly used parameters: text (button text)
, type (button type)
, asyncFunc (asynchronous function executed when the button is clicked)
, delay(loading delay)
, in addition, a loading
variable inside the component is needed to control the state of our Button
component, the code is as follows:
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: () => {} } }, }
Use the <span style="font-size: 18px;">Button</span>
component in <span style="font-size: 18px;">antd</span>
to perform the second step Sub-encapsulation
In our custom LoadingButton
component, use the parameters defined above and bind a click
event, The code is as follows:
<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>
Judge asynchronous function<span style="font-size: 18px;">asyncFunc</span>
This part is The most important part of the entire component is how we determine whether the incoming function is an asynchronous function. When the
asyncFunc
function we pass in is an asynchronous function, the component needs to add a loading animation, then we should How to determine whether a function is an asynchronous function?
Referenceantd
How is it implemented?
We just introduced the Modal
dialog box of antd
above. There is similar logic in it, so you might as well read this part of the related source code and take a look. Implementation method of 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(); } },
Read the implementation of antd
source code. We know that to determine whether a function is an asynchronous function, we can determine whether the function has .then
(ret && ret.then
) method, then we can also make a similar judgment. The code is as follows:
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 }) } }
TestLoadingButton
Component
At this point our core component logic has been developed. Later we will write a demo to test whether this
LoadingButton
component meets expectations: demo The code is as follows:
<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>
We wrote an asynchronous function asyncFunc
to simulate asynchronous requests in actual business. Now you can see the effect:
is in line with the previous expected effect, so that when we have similar scenarios that require loading
, we can directly use the LoadingButton
component to click the asynchronous function that needs to be executed. Just pass it in, there is no need to define the loading
variable.
写在最后
这个组件其实核心的代码非常少,也很容易读懂。由于最近在做一些业务这类场景比较多,感觉这个小组件还是挺实用的所以分享给大家,这里也是只对最重要的部分做了一个介绍,相信大家学会了之后也可以通过这个方式封装出符合自己实际场景需求的组件。最后,附上这个组件的完整代码:
<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>
原文地址:https://juejin.cn/post/7099234795720278046
作者:liangyue
The above is the detailed content of Vue component practice: Develop a loading Button component--LoadingButton. For more information, please follow other related articles on the PHP Chinese website!

vue中props可以传递函数;vue中可以将字符串、数组、数字和对象作为props传递,props主要用于组件的传值,目的为了接收外面传过来的数据,语法为“export default {methods: {myFunction() {// ...}}};”。

本篇文章带大家聊聊vue指令中的修饰符,对比一下vue中的指令修饰符和dom事件中的event对象,介绍一下常用的事件修饰符,希望对大家有所帮助!

如何覆盖组件库样式?下面本篇文章给大家介绍一下React和Vue项目中优雅地覆盖组件库样式的方法,希望对大家有所帮助!

react与vue的虚拟dom没有区别;react和vue的虚拟dom都是用js对象来模拟真实DOM,用虚拟DOM的diff来最小化更新真实DOM,可以减小不必要的性能损耗,按颗粒度分为不同的类型比较同层级dom节点,进行增、删、移的操作。


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

SAP NetWeaver Server Adapter for Eclipse
Integrate Eclipse with SAP NetWeaver application server.

EditPlus Chinese cracked version
Small size, syntax highlighting, does not support code prompt function

Dreamweaver Mac version
Visual web development tools

Notepad++7.3.1
Easy-to-use and free code editor

VSCode Windows 64-bit Download
A free and powerful IDE editor launched by Microsoft
