基於vue2.x實現loading bar(載入進度條)元件
阿新 • • 發佈:2019-02-07
在這之前,我更新了有關一個單選框與複選框的元件實現,有興趣的小夥伴也可以瞭解一下,今天我們來介紹一下loading bar 元件的實現原理。
實現思路
- 整個元件
ui
部分有兩部分組成,分別為頂部條形記載進度條,和spinner
載入圈組成,整個部分包含在一個大的div裡,並且通過fixed
進行佈局,然後我們通過定時器控制其增長,如果未結束,進度條會一直停留在最後的位置,等待end()
事件的觸發。如果end()
事件觸發,進度條載入結束,spinner
停止旋轉並且消失。 - 因為可複用的關係,
Loading Bar
全域性之後一個,我們通過this.$loading
來操作例項。 - 通過呼叫 $Loading 提供的三種方法來控制全域性的載入進度條
start()
end()
、error()
。
實現過程
ui
部分以及樣式
<template>
<div class="w__loading-bar">
<div
class="w__loading-bar--bar"
:class="isError ? 'w__loading-bar--error' : ''"
role="bar"
:style="{transform: 'translate3d(-'+(100-totalProgress)+'%, 0, 0)'}">
<div class ="w__loading-bar--peg"></div>
</div>
<div class="w__loading-bar--spinner" role="spinner" v-if="showSpinner">
<div class="spinner-icon" :class="isError ? 'spinner-icon--error' : ''"
:style="{'animation': 'w-spinner 400ms '+easing+' infinite'}">
</div >
</div>
</div>
</template>
這裡面注意的部分就是class中我們通過傳遞引數來控制樣式,注意傳遞引數時拼接字串的寫法。其中tatalProgressd
的初始值我們設定為0,我們之後會通過js來控制此值的大小,另一個引數時easing
其控制變換的一種方式,預設值時linear
具體樣式檔案loadingbar.css
- data函式中的資料,元件通過全域性進行註冊,所以子元件不需要通過props接收引數
<script>
export default{
name: 'WLoadingBar',
data () {
return {
speed: 5,
easing: 'linear',//載入動畫
percentNum: 0,//每次前進的百分比
totalProgress: 0,//控制頂部條形進度條x軸的位移
showSpinner: true,//是否顯示圓圈載入
isError: false//是否發生錯誤
}
}
}
</script>
- 下面時最關鍵的一個部分,我們通過
Vue.extend(LoadingBar)
來建立一個擴充套件例項的構造器LoadingBarConstructor
,我們通過給構造器的原型上來新增一系列方法來實現組建的開始,結束、錯誤等功能。
let LoadingBarConstructor = Vue.extend(LoadingBar);
let timer = null, removeTimer = null;
let WLoadingBar = () => {
return new LoadingBarConstructor()
};
LoadingBarConstructor.prototype.config = function (options) {
Object.keys(options).forEach((key) => {
if (key === 'isError' || key === 'totalProgress') {
return;
}
this[key] = options[key]
})
};
LoadingBarConstructor.prototype.init = function () {
clearTimeout(timer);
this.totalProgress = 0;
this.isError = false;
this.vm = this.$mount();
document.body.appendChild(this.vm.$el);
return this
};
LoadingBarConstructor.prototype.start = function () {
this.init();
timer = setInterval(() => {
if (this.totalProgress < 90) {
this.totalProgress += (this.percentNum || Math.random()) * this.speed;
}
}, 100);
};
LoadingBarConstructor.prototype.end = function () {
timer || this.init();
this.totalProgress = 100;
clearTimeout(removeTimer);
removeTimer = setTimeout(() => {
clearTimeout(timer);
timer = null;
document.body.removeChild(this.vm.$el)
}, 200)
};
我們來說下這些函式的功能,
config
該函式接收一個引數,引數是我們需要設定的配置,這裡面使用了一個Object.keys()
來遍歷options
配置裡的可列舉屬性,並且通過將其新增到例項物件上(過濾掉isError
和totalProgress
)init
函式進行初始化操作,清除定時器,並將例項進行掛載,通過dom
操作將例項新增到body
中。shart
函式將進度條控制在90%以下,在此之下,通過定時器定時增加totalProgress
的數值來實現進度條的變化。end
函式我們將totalProgress
設定為100完成載入,並且清除定時器,從body
中移除dom
。error
函式將進度條設定為報錯樣式。
注意:我們通過給構造器的原型上來新增一系列方法的時候千萬不要試圖使用箭頭函式,不要問我為什麼,就相當於我們vue中的methods一樣,理由是箭頭函式綁定了父級作用域的上下文,所以 this 將不會按照期望指向 Vue 例項,這一點希望大家在寫程式碼的時候注意。
- 父元件的呼叫
由於我的開發文件已經寫的很詳細了,大家詳情可以參考我的開發文件來看元件的使用開發文件
LoadingBar config引數
引數 | 說明 | 型別 | 可選值 | 預設值 |
---|---|---|---|---|
speed | 載入速度 | Number | 0-100 | 5 |
easing | spinner載入動畫 | String | linear, ease, cubic-bezier… | 貝薩爾曲線值 |
percentNum | 每次前進的百分比 | Float | 0-1 | Math.random() |
showSpinner | 是否顯示spinner | Boolean | true, false | 是否顯示spinner |