vue3实现一个自定义loading
组件实现
import { h, ref, render, createApp, nextTick } from 'vue'
/* loading svg动画 */
const loadingSvg = <svg xmlns="http://www.w3.org/2000/svg" width="60px" height="60px" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid" class="lds-ellipsis">
<circle cx="84" cy="50" r="0" fill="#cbe86b">
<animate attributeName="r" values="11;0;0;0;0" keyTimes="0;0.25;0.5;0.75;1" keySplines="0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1" calcMode="spline" dur="1s" repeatCount="indefinite" begin="0s"/>
<animate attributeName="cx" values="84;84;84;84;84" keyTimes="0;0.25;0.5;0.75;1" keySplines="0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1" calcMode="spline" dur="1s" repeatCount="indefinite" begin="0s"/>
</circle>
<circle cx="40.0957" cy="50" r="11" fill="#1c140d">
<animate attributeName="r" values="0;11;11;11;0" keyTimes="0;0.25;0.5;0.75;1" keySplines="0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1" calcMode="spline" dur="1s" repeatCount="indefinite" begin="-0.5s"/>
<animate attributeName="cx" values="16;16;50;84;84" keyTimes="0;0.25;0.5;0.75;1" keySplines="0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1" calcMode="spline" dur="1s" repeatCount="indefinite" begin="-0.5s"/>
</circle>
<circle cx="16" cy="50" r="7.79567" fill="#f2e9e1">
<animate attributeName="r" values="0;11;11;11;0" keyTimes="0;0.25;0.5;0.75;1" keySplines="0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1" calcMode="spline" dur="1s" repeatCount="indefinite" begin="-0.25s"/>
<animate attributeName="cx" values="16;16;50;84;84" keyTimes="0;0.25;0.5;0.75;1" keySplines="0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1" calcMode="spline" dur="1s" repeatCount="indefinite" begin="-0.25s"/>
</circle>
<circle cx="84" cy="50" r="3.20433" fill="#600473">
<animate attributeName="r" values="0;11;11;11;0" keyTimes="0;0.25;0.5;0.75;1" keySplines="0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1" calcMode="spline" dur="1s" repeatCount="indefinite" begin="0s"/>
<animate attributeName="cx" values="16;16;50;84;84" keyTimes="0;0.25;0.5;0.75;1" keySplines="0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1" calcMode="spline" dur="1s" repeatCount="indefinite" begin="0s"/>
</circle>
<circle cx="74.0957" cy="50" r="11" fill="#30BCED">
<animate attributeName="r" values="0;0;11;11;11" keyTimes="0;0.25;0.5;0.75;1" keySplines="0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1" calcMode="spline" dur="1s" repeatCount="indefinite" begin="0s"/>
<animate attributeName="cx" values="16;16;16;50;84" keyTimes="0;0.25;0.5;0.75;1" keySplines="0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1;0 0.5 0.5 1" calcMode="spline" dur="1s" repeatCount="indefinite" begin="0s"/>
</circle>
</svg>
/* loading组件封装 */
const renderLoading = {
/* 这里可以自定义一些传进来的参数,我这里没有写,
需要可以自己修改一下,在组件中接受一下传进来的参数 */
props: {
background: String,
text: String
},
setup (props) {
return () => {
return (
<div class="dwloadingmain absolute top-0 left-0 wh-full flex-col flex-center">
<loadingSvg />
</div>
)
}
}
}
/* 创建loading函数 */
const createInstance = async (trigger, binding) => {
const { value, oldValue } = binding
if (oldValue !== value) {
if (value && !oldValue) {
const vnode = h(renderLoading, { background: '#000', text: '加载中' })
const app = createApp(vnode)
const loadingEl = app.mount(document.createElement('div')).$el
loadingEl.setAttribute('id', 'dwLoadingId')
trigger.style.position = 'relative'
trigger.appendChild(loadingEl)
nextTick(() => {
const triggerH = trigger.offsetHeight
if (triggerH < 200) {
trigger.classList.add('!h-320px')
}
})
} else {
const childDiv = trigger.querySelector('#dwLoadingId')
trigger.removeChild(childDiv)
trigger.classList.remove('!h-320px')
}
}
}
/* 导出loading指令 */
export default {
mounted (el, binding) {
if (binding.value) {
createInstance(el, binding)
}
},
updated (el, binding) {
createInstance(el, binding)
},
unmounted (el) {
}
}
/* 导出loading方法 */
export const DwLoading = {
el: null,
service ({ text, background = '#ccc' } = { }) {
const vnode = h(<renderLoading />)
const div = document.createElement('div')
render(vnode, div)
document.body.appendChild(div)
this.el = div
return DwLoading
},
close () {
document.body.removeChild(this.el)
}
}
样式
其它的样式使用的原子化css,自己引入就可使用,如有不懂,可以留言
.dwloadingmain {
background: rgba($color: #f7f5f1, $alpha: 0.6);
z-index: 9999;
}