Vue3自定义指令和hooks,loading展示

实现了 全屏loading hooks 和 元素内部loading

1.准备loading组件 loading.vue

<template>
  <transition name="fade">
    <div v-if="visible">
      <div class="loading-mask" :style="getStyle">
        <svg class="circular" viewBox="25 25 50 50">
          <circle class="path" cx="50" cy="50" r="20" fill="none"/>
        </svg>
        <span style="color: #409eff;font-size: 14px;margin-top: 4px">loading...</span>
      </div>
    </div>
  </transition>
</template>

<script>
import { ref, computed } from 'vue'
export default {
  name:'Loading',
  setup(props, { emit }) {
    let visible = ref(false)
    const isFixed = ref(true)

    const getStyle = computed(() => {
      return isFixed.value ? 'position: fixed' : 'position: absolute'
    })

    return {
      visible,
      show: () => visible.value = true,
      close: () => visible.value = false,
      changeFix: (v) => isFixed.value = v,
      getStyle,
      isFixed
    }
  },
}
</script>

<style lang="scss">
.fade-enter-active, .fade-leave-active {
  transition: all .5s;
}

.fade-enter-from, .fade-leave-to {
  opacity: 0;
  scale: 0;
}

.fade-enter-to, .fade-leave-from {
  opacity: 1;
  scale: 1;
}

.loading-mask {
  z-index: 2000;
  background-color: rgba(33,33,33,.4);
  margin: 0;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  transition: opacity .3s;
  .circular {
    height: 42px;
    width: 42px;
   animation: loading-rotate 2s linear infinite;
  }
  .path {
    animation: loading-dash 1.5s ease-in-out infinite;
    stroke-dasharray: 90,150;
    stroke-dashoffset: 0;
    stroke-width: 2;
    stroke: #409eff;
    stroke-linecap: round;
  }
}

@keyframes loading-rotate{to{transform:rotate(1turn)}}
@keyframes loading-dash {
  0% {
    stroke-dasharray: 1,200;
    stroke-dashoffset: 0;
  }

  50% {
    stroke-dasharray: 90,150;
    stroke-dashoffset: -40px;
  }
  100% {
    stroke-dasharray: 90,150;
    stroke-dashoffset: -120px;
  }
}
</style>

2.实现全屏hooks (其实就是absolute,并且装载到body里)

useLoading.ts

import Loading from "../components/Loading.vue"
import {createVNode, render} from "vue";

export default function useLoading() {
    let element;
    const oldEle = document.getElementById("#loading-zzz")
    if(oldEle) {
        element = oldEle;
    } else {
        element = document.createElement("div");
        element.setAttribute("id", "#loading-zzz")
        document.body.appendChild(element);
    }
    element.setAttribute("time", new Date().getTime() + '')
    const Vloading = createVNode(Loading, {});
    render(Vloading, element);
    let instance = Vloading.component.ctx;
    return {
        show() {
            instance.show();
        },
        close() {
            instance && instance.close()
        }
    }
}

使用

import useLoading from "../hooks/useLoading";

const {show, close} = useLoading()


function handleShow() {
  show()
  // close
  //setTimeout(close, 3000)
}

2.定义指令 loading.ts

import {App, createVNode, render} from "vue";
import Loading from '../components/Loading.vue'

export default function(app: App<Element>) {
    app.directive("loading", {
        mounted(el, binding) {
            el.style.position = 'relative'
            const Vloading = createVNode(Loading, {})
            render(Vloading, el)
            el.instance = Vloading.component.ctx
            el.instance.changeFix(false)
            console.log(el.instance)
            !!binding.value && el.instance.show()
        },
        updated(el, binding) {
            const instance = el.instance
            if(binding.oldValue !== binding.value) {
                !!binding.value ? el.instance.show() : el.instance.close()
            }
        }
    })
}

使用(记得注册)我采用的 app.use

<div v-loading="loading"
     style="width: 300px;height: 300px;background-color: #ff1212"></div>

  • 8
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue.js中,自定义指令是用于扩展模板语法的一种方式。它允许开发者在DOM元素上添加一些特定的行为或交互逻辑。引用中提到,Vue2和Vue3的自定义指令参数是一样的,包括el、binding、vnode和preVNode(oldVNode),这些参数用于指令的操作和交互。具体的用法可以查看官方文档。 然而,Vue2和Vue3在自定义指令的注册方式上有一些区别。在Vue2中,我们使用Vue.directive()方法来注册全局自定义指令,或者在组件中使用directives选项来注册局部自定义指令。而在Vue3中,我们使用app.directive()方法来注册全局自定义指令,或者在组件的setup()函数中使用directive()方法来注册局部自定义指令。这是因为Vue3将全局API移动到了应用实例(app)上,以提高代码的可读性和维护性。引用提供的例子展示Vue2和Vue3中注册自定义指令的区别。 总结来说,Vue2和Vue3的自定义指令在参数方面是一样的,但在注册方式上有一些区别。Vue2使用Vue.directive()来注册全局和局部自定义指令,而Vue3则使用app.directive()来注册全局自定义指令,或者在组件的setup()函数中使用directive()来注册局部自定义指令。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [vue2和vue3自定义指令区别?](https://blog.csdn.net/m0_53273062/article/details/126201620)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [vue2.0和vue3.0中自定义指令(directive)的区别](https://blog.csdn.net/m0_46846526/article/details/118911913)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值