首頁 > web前端 > Vue.js > vue元件實戰:開發一個載入Button元件--LoadingButton

vue元件實戰:開發一個載入Button元件--LoadingButton

青灯夜游
發布: 2022-05-23 20:24:52
轉載
4420 人瀏覽過

這篇文章手把手帶大家開發一個超實用的vue載入Button元件--LoadingButton,希望對大家有幫助。

vue元件實戰:開發一個載入Button元件--LoadingButton

元件背景

在平常的工作中,常常會遇到一個場景:

vue元件實戰:開發一個載入Button元件--LoadingButton

#點擊按鈕時請求一些介面數據,而為了避免用戶重複的點擊我們通常會為這些按鈕添加loading。這個新增loading的功能本身時非常簡單的,只要我們定義一個變數使用在Button元件中即可,但在做後台管理類別專案時,這樣的按鈕可能會有非常非常多,可能一個元件中,很多變數都是xxx_loading,耗時耗力又不夠優雅。

接下來,我們對Button元件做一個簡單的封裝來解決這個耗時耗力又不夠優雅的loading問題。 (學習影片分享:vue影片教學

靈感來源

我們在使用AntdModal對話方塊時,當我們的onOk非同步函數時,此時Modal的確定按鈕會自動新增loading 效果,在函數執行完成後關閉彈窗,就像這樣:

vue元件實戰:開發一個載入Button元件--LoadingButton

#此時,程式碼如下:

asyncFunc() {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve()
    }, 2000)
  })
},
handleTestModal() {
  const that = this
  this.$confirm({
    title: '测试异步函数',
    content: '异步函数延迟两秒结束',
    async onOk() {
      await that.asyncFunc()
    }
  })
},
登入後複製

#看到這種效果後,就想到,如果可以封裝一個Button元件,將需要執行的函數傳入,元件中自動根據函數執行情況添加loading效果豈不是非常的方便。

實作LoadingButton

#定義元件參數

##這邊就定義幾個大家會常用的參數:

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<span style="font-size: 18px;"></span>中的Button<span style="font-size: 18px;"></span>元件進行二次封裝

在我們的自訂

LoadingButton元件中,將上面定義的參數使用起來,並綁定一個click事件,程式碼如下:

<template>
  <Button :type="type" :loading="loading" @click="handleClick">
    {{ text }}
  </Button>
</template>

<script>
import { Button } from &#39;ant-design-vue&#39;

export default {
    components: {
        Button
    },
    methods: {
        handleClick() {}
    }
}
</script>
登入後複製

判斷非同步函數asyncFunc<span style="font-size: 18px;"></span>

##這一部分為整個元件最重要的一個部分,即我們如何去判斷傳入的函數是非同步函數,當我們傳入的
asyncFunc

函數是非同步函數時,元件需要添加loading的動畫,那麼我們應該如何去判斷一個函數是否為非同步函數呢?

參考

antd是如何實現的? 上面我們剛剛介紹了

antd

Modal對話方塊中有類似的邏輯,那麼不妨去閱讀這部分相關的源碼,看看antd的實作方式:<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;toolbar:false;">// 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 &amp;&amp; ret.then) { this.setState({ loading: true }); ret.then( (...args) =&gt; { // It&amp;#39;s unnecessary to set loading=false, for the Modal will be unmounted after close. // this.setState({ loading: false }); closeModal(...args); }, e =&gt; { // 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(); } },</pre><div class="contentsignin">登入後複製</div></div>閱讀

antd

原始碼的實現,我們知道,判斷一個函數是否是非同步函數,可以透過判斷函數是否有 .then(ret && ret.then)方法,那麼我們也可以類似的做一個判斷,程式碼如下:<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;toolbar:false;">async handleClick() { const asyncFunc = this.asyncFunc if (!this.isFunc) { return } const ret = asyncFunc() // 如果是异步函数,则显示loading if (ret &amp;&amp; ret.then) { this.loading = { delay: this.delay } ret.finally(() =&gt; { this.loading = false }) } }</pre><div class="contentsignin">登入後複製</div></div>

測試

LoadingButton元件

到這裡我們的最核心的元件邏輯就開發完成了,後面我們寫一個demo來測試一下這個
LoadingButton

元件是否符合預期:demo程式碼如下:

<template>
  <div>
    <LoadingButton :delay="500" :asyncFunc="asyncFunc" />
  </div>
</template>

<script>
import LoadingButton from &#39;./LoadingButton.vue&#39;

export default {
  data() {
    return {
      loading: false
    }
  },
  components: {
    LoadingButton
  },
  methods: {
    asyncFunc() {
      return new Promise(resolve => {
        setTimeout(() => {
          resolve()
        }, 2000)
      })
    }
  }
}
</script>
登入後複製

我們寫了一個非同步函數
asyncFunc

用來模擬實際業務中的非同步請求,現在可以看效果:

vue元件實戰:開發一個載入Button元件--LoadingButton#符合先前的預期效果,這樣我們再有類似需要

loading

的場景時,就可以直接使用LoadingButton元件,將點擊需要執行的非同步函數傳入即可,不需要再去定義loading變數。

写在最后

这个组件其实核心的代码非常少,也很容易读懂。由于最近在做一些业务这类场景比较多,感觉这个小组件还是挺实用的所以分享给大家,这里也是只对最重要的部分做了一个介绍,相信大家学会了之后也可以通过这个方式封装出符合自己实际场景需求的组件。最后,附上这个组件的完整代码:

<template>
  <Button :type="type" :loading="loading" @click="handleClick">
    {{ text }}
  </Button>
</template>

<script>
import { Button } from &#39;ant-design-vue&#39;

export default {
  data() {
    return {
      loading: false
    }
  },
  props: {
    text: {
      type: String,
      default: &#39;确定&#39;
    },
    type: {
      type: String,
      default: &#39;primary&#39;
    },
    delay: {
      type: Number,
      default: 0
    },
    asyncFunc: {
      type: Function,
      default: () => {}
    }
  },
  components: {
    Button
  },
  computed: {
    isFunc() {
      return typeof this.asyncFunc === &#39;function&#39;
    }
  },
  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

(学习视频分享:web前端开发编程基础视频

以上是vue元件實戰:開發一個載入Button元件--LoadingButton的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:juejin.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板