在Vue3中高级前端是这样给按钮添加loading效果的

前言

一个页面有多个按钮,每个按钮都要添加loading效果,高级前端是如何在Vue3控制按钮是否显示loading效果的呢?

普通前端

我们先来看看初级普通前端平常是怎么给按钮添加loading效果的:

xml 复制代码
<script setup >
import { ref } from 'vue'

const asyncFn = () => new Promise(resolve => {
  setTimeout(resolve, 3000)
})

const loading1 = ref(false)
const handler1 = async () => {
 loading1.value = true
  try {
    await asyncFn()
  } finally {
    loading1.value = false
  }
}

const loading2 = ref(false)
const handler2 = async () => {
 loading2.value = true
  try {
    await asyncFn()
  } finally {
    loading2.value = false
  }
}
    
const loading3 = ref(false)
const handler3 = async () => {
 loading3.value = true
  try {
    await asyncFn()
  } finally {
    loading3.value = false
  }
}
</script>

<template>
  <el-button type="primary" @click="handler1" :loading="loading1">
    按钮1
  </el-button>
  <el-button  @click="handler2" :loading="loading2">
    按钮2
  </el-button>
  <el-button type="primary" plain  @click="handler3" :loading="loading3">
    按钮3
  </el-button>
</template>

通过以上代码可以看到,一个页面有多个按钮,每个按钮都要添加loading效果,所以声明了loading1、loading2、loading3 ...变量来控制按钮是否显示loading效果,非常不优雅。 那么高级前端是如何优雅的给按钮添加loading效果的呢?

高级前端

首先先封装一个MyButton组件:

xml 复制代码
<script setup >
import { ref, useSlots } from 'vue'

const props = defineProps(['onClick'])

const loading = ref(false)
const clickHandler = async (e) => {
  loading.value = true
  try {
    await props.onClick(e)
  } finally {
    loading.value = false
  }
}
const slots = useSlots()
</script>

<template>
  <el-button @click="clickHandler" :loading="loading">
    <template v-for="(_, key, i) in slots" :key="i" #[key]>
      <slot :name="key" />
    </template>
  </el-button>
</template>

接下来引用MyButton组件,绑定click事件,返回Promise就可以优雅的给按钮添加一个loading效果了

xml 复制代码
<script setup >
import MyButton from './MyButton.vue';
const asyncFn = () => new Promise(resolve => {
  setTimeout(resolve, 3000)
})

const handler1 = async () => {
  // ...
  await asyncFn()
}



const handler3 = () => {
  // ...
  return asyncFn()
}
</script>

<template>
  <MyButton type="primary" @click="handler1">
    按钮1
  </MyButton>
  <MyButton @click="asyncFn">
    按钮2
  </MyButton>
  <MyButton type="primary" plain @click="handler3">
    <template #loading>
      <div class="custom-loading">
        <svg class="circular" viewBox="-10, -10, 50, 50">
          <path class="path" d="
            M 30 15
            L 28 17
            M 25.61 25.61
            A 15 15, 0, 0, 1, 15 30
            A 15 15, 0, 1, 1, 27.99 7.5
            L 15 15
          " style="stroke-width: 4px; fill: rgba(0, 0, 0, 0)" />
        </svg>
      </div>
    </template>
    按钮3
  </MyButton>
</template>
<style scoped>
.el-button .custom-loading .circular {
  margin-right: 6px;
  width: 18px;
  height: 18px;
  animation: loading-rotate 2s linear infinite;
}

.el-button .custom-loading .circular .path {
  animation: loading-dash 1.5s ease-in-out infinite;
  stroke-dasharray: 90, 150;
  stroke-dashoffset: 0;
  stroke-width: 2;
  stroke: var(--el-button-text-color);
  stroke-linecap: round;
}
</style>

相关源码

总结

  1. 可以通过defineProps(['onEventName'])声明事件,组件内部通过props.onEventName()触发事件,并且可以获取到事件回调函数的返回值,进而组件内部做更多逻辑处理,如给一个按钮组件自动添加loading等
  2. @eventName本质就是一个语法糖,最后还是会编译为onEventName通过属性的形式 传递给组件。如需了解更多,请查看文章:通过编译源码解析Vue不同方式监听事件的区别

结语

感谢您的耐心阅读,如果觉得这篇文章对您有帮助和启发,麻烦给个大大的赞~

相关推荐
anyup_前端梦工厂2 小时前
了解几个 HTML 标签属性,实现优化页面加载性能
前端·html
前端御书房2 小时前
前端PDF转图片技术调研实战指南:从踩坑到高可用方案的深度解析
前端·javascript
2301_789169542 小时前
angular中使用animation.css实现翻转展示卡片正反两面效果
前端·css·angular.js
风口上的猪20153 小时前
thingboard告警信息格式美化
java·服务器·前端
程序员黄同学3 小时前
请谈谈 Vue 中的响应式原理,如何实现?
前端·javascript·vue.js
爱编程的小庄4 小时前
web网络安全:SQL 注入攻击
前端·sql·web安全
宁波阿成5 小时前
vue3里组件的v-model:value与v-model的区别
前端·javascript·vue.js
柯腾啊5 小时前
VSCode 中使用 Snippets 设置常用代码块
开发语言·前端·javascript·ide·vscode·编辑器·代码片段
Jay丶萧邦5 小时前
el-select:有关多选,options选项值不包含绑定值的回显问题
javascript·vue.js·elementui
weixin_535854225 小时前
oppo,汤臣倍健,康冠科技,高途教育25届春招内推
c语言·前端·嵌入式硬件·硬件工程·求职招聘