這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助
網站效果演示:ashuai.work:8888/#/myLoad
GitHub倉庫地址代碼:github.com/shuirongshu…
加載中思路分析
實作加載中效果,一般有兩種方式:
- 第一種是:搞一個
load組件,然后使用Vue.extend()方法去繼承一個加載組件去使用,比如筆者的這篇文章:juejin.cn/post/702172… - 第二種是:直接使用指令去在需要加載的
dom上去創建一個加載中的dom元素,并指定相應的樣式即可,本篇文章說的是第二種,
我們先看一下效果圖
v-load效果圖
實作步驟一:加上自定義指令
假設我有一個dom元素,我給其加上一個自定義的指令v-load="loading",系結一個具體的布林值loading,用于控制開啟加載中和關閉加載中
<div v-load="loading">111</div>
loading: true
.box {
width: 160px;
height: 80px;
border: 2px solid #666;
}
接下來,我就要在自定義指令的相關鉤子函式中去操作這個dom元素,
關于自定義指令的入門基礎知識可以看官方檔案,或者參見筆者之前的關于自定義指令的文章:juejin.cn/post/702960…
實作步驟二:給目標元素創建一個子元素dom用于加載
在自定義指令的初始化bind鉤子函式中,我們可以拿到這個dom元素,首先給這個目標元素開始相對定位,讓用于加載中的子元素dom去絕對定位,以這個相對定位的父元素進行參考
bind(el, binding) {
const target = el;
// 父元素相對定位
target.style.position = "relative";
// 子元素遮罩層部分
let loadChild = document.createElement("div");
loadChild.className = "loadClass";
}
上述代碼中給加載中的子元素loadChild指定一個樣式類名loadClass
在這里小伙伴可能有疑問了,這個自定義指令的樣式怎么寫呢?自定義指令中也沒有style標簽啊?
是的,自定義指令中不能直接寫樣式,不過沒關系,我們可以先寫好一個css樣式,然后引入過來使用啊,如下:
// 引入拆分的樣式,便于自定義指令中使用
import './index.css'
bind(el, binding) {
......
loadChild.className = "loadClass";
}
這樣的話,className的樣式,可以在引入的同級目錄下的./index.css檔案中設定了,loadClass樣式如下:
.loadClass {
/* 寬高百分百 */
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
/* 默認背景色和顏色 */
background-color: rgba(255, 255, 255, 0.99);
color: #0b6ed0;
/* 透明度過渡使用搭配display:none; */
opacity: 0.8;
transition: all 0.3s;
/* 居中 */
display: flex;
align-items: center;
justify-content: center;
}
注意,加載中效果開啟和消失,不用使用vue自帶的過渡組件transition,咱們可以使用透明度搭配搭配display:none;去設定
注意,加載中要以父元素為邊界去控制,可不能滿屏加載哦
然后初始化的時候,看看v-load系結的值是true還是false,同時加上一個用于隱藏的類名:load-hide,再把這個加載中的dom元素追加到目標父元素身上,
loadChild.classList.add('load-hide') // 添加類名
target.appendChild(loadChild); // 追加加載中子元素
/* 通過透明度實作過渡影片 */
.load-hide {
opacity: 0;
}
這樣的話,初始化的加載中就做好了,v-load系結的值是false的時,就隱藏之
實作步驟三:當組件更新時,去添加或移除這個load-hide類名
componentUpdated(el, binding, vnode, oldVnode) {
let flag = binding.value
let loadChild = el.querySelector('.loadClass')
if (flag) { // v-load系結的值為true,就移除這個類名,就能看到了
loadChild.style.display = 'flex'
setTimeout(() => {
loadChild.classList.remove('load-hide')
}, 0);
} else { // 系結的值為false時,再添加這個類名,同時隱藏dom
loadChild.classList.add('load-hide')
setTimeout(() => {
loadChild.style.display = 'none'
}, 360);
}
},
注意上述代碼中為啥不直接隱藏,而是使用定時器延長360毫秒再去隱藏,因為筆者設定的加載dom的過渡時間是0.3秒,即要等到透明度過渡完了以后,再隱藏加載中dom,這樣看著就自然一些了,
.loadClass { transition: all 0.3s; }
到這里,咱們的v-load自定義指令的加載中效果,就初步完成了,不過功能有點少,自定義加載中我還想,去動態控制:
- 自定義加載圖示名
- 自定義加載文字
- 自定義加載文字顏色
- 自定義加載背景色
那這樣怎么辦呢?
實作步驟四:優化自定義指令,支持傳入更多的引數
此時,我的v-load自定義指令,就不用系結一個布林值了,可以考慮系結一個物件啊,通過控制這個物件的具體值,來動態控制加載中的效果,
- 原來自定義指令系結:
v-load = loading//typeof loading == 'boolean' - 現在自定義指令系結:
v-load = loading2//typeof loading2 == 'object'
<div v-load="loading2">222</div>
// 如果想要有更多的配置項,就傳一個物件,注意要指定欄位
loading2: {
value: true,
icon: "el-icon-eleme", // 自定義加載圖示名
text: "客官稍等哦...", // 自定義加載文字
color: "red", // 自定義加載文字顏色
bgColor: "#baf", // 自定義加載背景色
}
傳參指定相應欄位,自定義指令中接參,就要在相關的鉤子中去接收并處理這些引數,
如何處理這些引數?
- v-load系結的值的型別的判斷,是布林值,還是物件,執行不同的操作
- 使用原生js的方式去,創造dom元素、給dom元素指定類名(或添加洗掉類名)
- 考慮到性能緣故,可以使用檔案碎片優化
document.createDocumentFragment() - 最后丟入遮罩層dom內部即可
完整代碼
自定義指令樣式檔案index.css
.loadClass {
/* 寬高百分百 */
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
/* 默認背景色和顏色 */
background-color: rgba(255, 255, 255, 0.99);
color: #0b6ed0;
/* 透明度過渡使用搭配display:none; */
opacity: 0.8;
transition: all 0.3s;
/* 禁止文字選擇 */
user-select: none;
display: flex;
align-items: center;
justify-content: center;
}
/* 通過透明度實作過渡影片 */
.load-hide {
opacity: 0;
}
.loadClass>i {
margin-right: 4px;
}
自定義指令的js檔案index.js
注意,自定義指令還需要注冊一下才能使用哦
// 引入拆分的樣式,便于自定義指令中使用
import './index.css'
export default {
// 初始化系結dom鉤子函式
bind(el, binding) {
const target = el;
// 傳參型別判斷變數控制
let flag;
let isObj;
if (typeof binding.value =https://www.cnblogs.com/smileZAZ/archive/2023/03/09/='boolean') {
flag = binding.value
isObj = false
}
if (typeof binding.value =https://www.cnblogs.com/smileZAZ/archive/2023/03/09/='object') {
flag = binding.value.value
isObj = true
}
// 有dom元素才去做操作
if (target) {
// 父元素相對定位
target.style.position = "relative";
// 子元素遮罩層部分
let loadChild = document.createElement("div");
loadChild.className = "loadClass";
// 創建檔案碎片性能稍微優化一點點
let fragment = document.createDocumentFragment()
// 孫子元素1加載圖示部分
let iSun = document.createElement("i");
iSun.className = isObj ? binding.value.icon : "el-icon-loading";
// 孫子元素2文字提示部分
let spanSun = document.createElement("span");
spanSun.innerHTML = isObj ? binding.value.text : '加載中...'
// 使用檔案碎片將iSun和spanSun裝起來
fragment.appendChild(iSun);
fragment.appendChild(spanSun);
// 將檔案碎片丟入子元素遮罩層內
loadChild.appendChild(fragment);
// 樣式判斷設定
if (isObj) {
loadChild.style.color = binding.value.color
loadChild.style.backgroundColor = binding.value.bgColor
}
// 若為false,就隱藏
if (!flag) {
loadChild.classList.add('load-hide')
loadChild.style.display = 'none'
}
// 父元素添加子元素遮罩層使用
target.appendChild(loadChild);
}
},
// dom組件更新操作控制顯示和隱藏
componentUpdated(el, binding, vnode, oldVnode) {
let flag = typeof binding.value =https://www.cnblogs.com/smileZAZ/archive/2023/03/09/='boolean' ? binding.value : binding.value.value
let loadChild = el.querySelector('.loadClass')
if (flag) {
loadChild.style.display = 'flex'
setTimeout(() => {
loadChild.classList.remove('load-hide')
}, 0);
} else {
loadChild.classList.add('load-hide')
setTimeout(() => {
loadChild.style.display = 'none'
}, 360);
}
},
}
使用自定義load指令的地方
<template>
<div>
<h3>指令方式加載中...</h3>
<br />
<button @click="loadFn">點一下</button>
<br />
<br />
<el-table v-load="loading" border :data="https://www.cnblogs.com/smileZAZ/archive/2023/03/09/tableData" style="width: 80%">
<el-table-column prop="name" label="姓名"></el-table-column>
<el-table-column prop="age" label="年齡"></el-table-column>
<el-table-column prop="home" label="家鄉"></el-table-column>
<el-table-column prop="like" label="愛好"></el-table-column>
</el-table>
<br />
<div v-load="loading">111</div>
<br />
<div v-load="loading2">222</div>
</div>
</template>
<script>
export default {
name: "myLoadName",
data() {
return {
// 自定義指令方式,默認系結的值是布林值
loading: true,
// 如果想要有更多的配置項,就傳一個物件,注意要指定欄位
loading2: {
value: true,
icon: "el-icon-eleme", // 自定義加載圖示名
text: "客官稍等哦...", // 自定義加載文字
color: "red", // 自定義加載文字顏色
bgColor: "#baf", // 自定義加載背景色
},
tableData: [
{
name: "孫悟空",
age: 500,
home: "花果山水簾洞",
like: "桃子",
},
{
name: "豬八戒",
age: 88,
home: "高老莊",
like: "肉包子",
},
{
name: "沙和尚",
age: 1000,
home: "通天河",
like: "游泳",
},
],
};
},
methods: {
loadFn() {
this.loading = !this.loading;
this.loading2.value = https://www.cnblogs.com/smileZAZ/archive/2023/03/09/!this.loading2.value;
},
},
};
</script>
<style lang='less' scoped>
.box {
width: 160px;
height: 80px;
border: 2px solid #666;
box-sizing: border-box;
}
</style>
本文轉載于:
https://juejin.cn/post/7182375025368891429
如果對您有所幫助,歡迎您點個關注,我會定時更新技術檔案,大家一起討論學習,一起進步,

轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/546362.html
標籤:其他

