Loading自定义指令

Loading自定义指令

相关知识查看官方文档:自定义指令)

一、介绍

通过v-loading指令的方式为某个Dom添加Loading动画。如在发送请求时,请求还在响应时某个Dom需要的请求数据还未获取到,此时Dom内容为空,可以通过添加Loading动画解决暂时的Dom空白的问题。
全局注册之后就可以直接通过v-loading的方式添加loading加载动画。

二、自定义指令及使用

1.创建loading组件

<template>
  <div class="loading">
    <div class="loading-content">
      <img src="./loading.gif" width="24" height="24" alt="" />
      <p class="desc">{{ title }}</p>
    </div>
  </div>
</template>

<script setup></script>
<script>
export default {
  data() {
    return {
      title: "正在输入...",
    };
  },
  methods: {
    setTitle(title) {
      this.title = title;
    },
  },
};
</script>

<style lang="less" scoped>
.loading {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  .loading-content {
    text-align: center;
    .desc {
      line-height: 20px;
      font-size: 12px;
      color: black;
    }
  }
}
.g-relative {
  position: relative;
}
</style>

2.自定义指令

import { createApp } from 'vue'
import Loading from './loading.vue'

// g-realtive为一个calssName,定义在全局中,仅有属性position:relative这一个
const relativeCls = 'g-relative'

const loadingDirective = {
    // el:指令绑定到的元素。这可以用于直接操作 DOM。
    mounted(el, binding) {
        const app = createApp(Loading)
        const instance = app.mount(document.createElement('div'))
        // 保存instance后面还会多次使用
        el.instance = instance
        // 添加文字
        const title = binding.arg
        if (typeof title !== 'undefined') {
            // setTitle方位为组件loding中的方法,注意这里的setTitle不能写在setup语法糖中,可能会找不到
            instance.setTitle(title)
        }
        // 如果为binding.value为真,将loading组件挂在到el上
        if (binding.value) {
            append(el)
        }
    },
    updated(el, binding) {
        const title = binding.arg
        if (typeof title !== 'undefined') {
            // setTitle方位为组件loding中的方法
            el.instance.setTitle(title)
        }
        if (binding.value !== binding.oldValue) {
            binding.value ? append(el) : remove(el)
        }
    }
}

// 添加loading
function append(el) {
    // 优化loading让更具通用性。loading组将使用了position:absolute
    const style = getComputedStyle(el)
    // 如果不是以下三个中的一个,添加新的className,添加属性position:relative
    if (['absolute', 'fixed', 'relative'].indexOf(style.position) === -1) {
        // 添加样式
        addClass(el, relativeCls)
    }
    // appendChild方法可向节点的子节点列表的末尾添加新的子节点
    el.appendChild(el.instance.$el)
    // 注意这里的el和el.instance.$el不是同一个,el为需要绑定到的节点,el.instance.$el为loading组件
}
// 移除loading
function remove(el) {
    // 移除样式
    removeClass(el, relativeCls)
    el.removeChild(el.instance.$el)
}
// 添加className
function addClass(el, className) {
    // classList.contains(X):查看元素是否存在类名为x的类
    if (!el.classList.contains(className)) {
        el.classList.add(className)
    }
}
function removeClass(el, className) {
    el.classList.remove(className)
}

export default loadingDirective

3.main.js中全局注册

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
// 全局样式
import './assets/css/global.css'

// 引入自定义指令
import loadingDirective from '@/components/base-ui/loading/directive'

createApp(App).use(store).use(router).directive('loading', loadingDirective).mount('#app')

4.使用

<template>
  <!-- v-loading:[loadingText] 动态指令参数 -->
  <div class="div" v-loading:[loadingText]="isShow"></div>
</template>
<script setup>
import { ref } from "vue";

// import Loading from "@/components/base-ui/loading/loading.vue";
let isShow = ref(true);
setTimeout(() => {
  isShow.value = false;
}, 3000);
let loadingText = "正在加载...";
</script>
<style lang="less">
.div {
  width: 100px;
  height: 100px;
  background-color: red;
}
</style>

三、结果演示

  • 正常情况下:

在这里插入图片描述

  • 没有判断是否添加g-relative时:

在这里插入图片描述

  • 目录结构
    在这里插入图片描述
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值