vue3 实现自定义指令 v-loading(基于 ant design 的 spin 组件实现)

文章描述了如何使用Vue在不干扰原有样式的情况下,通过动态创建`Spin`组件实现加载时的遮罩效果,同时确保在组件挂载和更新时的正确操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

想法: 本来是想简单的通过对指令的绑定节点设置相对定位然后在其子级创建loading组件覆盖原有元素,但考虑到强制改变节点样式可能对原有样式产生干扰,于是有了新的想法。

import { render, h } from 'vue'
import { Spin } from 'ant-design-vue';
const mount = (el: HTMLElement): void => {
  let parent: HTMLElement | null = el.querySelector('#__LOADING_PARENT__')
  if (!parent) {
    parent = document.createElement('div')
    parent.style.position = 'relative'
    parent.style.alignSelf = 'flex-start'
    parent.id = '__LOADING_PARENT__'
    if (el.firstChild) {
      el.insertBefore(parent, el.firstChild)
    } else {
      el.appendChild(parent)
    }
  }
  parent.style.opacity = '1'
  const elStyle = window.getComputedStyle(el, null)
  const style = {
    display: 'flex',
    alignItems: 'center',
    justifyContent: 'center',
    position: 'absolute',
    flexDirection: 'column',
    top: `-${elStyle.paddingTop}`,
    left: `-${elStyle.paddingLeft}`,
    width: `${el.clientWidth}px`,
    height: `${el.clientHeight}px`,
    backgroundColor: 'rgba(209, 238, 245, .8)',
    opacity: 1,
    zIndex: 1000
  }
  render(h(Spin, { class: 'directive-loading', tip: '加载中...', size: 'large', style }), parent)
}
const unmount = (el: HTMLElement) => {
  const loading: HTMLElement | null = el.querySelector('#__LOADING_PARENT__')
  if (loading && loading.parentNode === el) {
    el.removeChild(loading)
  }
}
export default {
  // 在绑定元素的父组件 及他自己的所有子节点都挂载完成后调用
  mounted: (el: HTMLElement, binding: any) => {
    binding.value && mount(el)
  },
  // 在绑定元素的父组件 及他自己的所有子节点都更新后调用
  updated: (el: HTMLElement, binding: any) => {
    setTimeout(() => {
      binding.value ? mount(el) : unmount(el)
    })
  }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值