打赏作者
感谢打赏,创作不易~
  • 微信
  • 支付宝

vue3 setup语法糖下,vue自定义指令的实现,以及指令全局挂载,自定义v-loading的实现

最近一段时间,在做h5的移动端项目,UI组件库使用的vant,vant组件中的loading实在难用,无法包裹某个块进行loading,也无法对非组件的标签进行loading,所以想着自定义写个指令,挂载全局,通过v-loading的方式实现控制加载,好了,话不多说,vue3的自定义指令实现,和vue2还是有区别的,下面进入正题

首先,写个loading组件:

内容根据自己的需求来,可以是loading的图片,或者自己写的loading样式都行,组件怎么写,此处就不详说了,非本篇博文重点

接着,创建一个js文件,loading.js,用于写指令相关的方法内容:

//引入写好的loading组件
import Loading  from '../components/loading.vue';


// 封装,挂载dom节点在  绑定了v-loading的标签dom节点之下的函数
function createLoading(el){
  // 创建div标签
  const loadingDom = document.createElement('div')
  // 添加自定义属性作为标识,避免重复loading
  loadingDom.setAttribute('data-v','loading')
  // 设置样式,父元素相对定位,子元素绝对定位父元素之上
  el.style.position = 'relative'
  loadingDom.style.width = `${el.offsetWidth}px`
  loadingDom.style.height = `${el.offsetHeight}px`
  loadingDom.style.maxHeight = '100vh'
  loadingDom.style.position = `absolute`
  loadingDom.style.background = `black`
  loadingDom.style.display = `flex`
  loadingDom.style.justifyContent = `center`
  loadingDom.style.alignItems = `center`
  loadingDom.style.opacity = '.16'
  loadingDom.style.top = '0'
  loadingDom.style.borderRadius = 'inherit'
  // 创建APP实例,传入loading组件,并且挂载loading组件和创建的标签
  const app = createApp(Loading)
  const instance = app.mount(loadingDom)
  loadingDom.appendChild(instance.$el)
  el.appendChild(loadingDom)
}

// 创建自定义指令
const vLoading = {
  //mounted的时候,v-loading变量值为true时,加载loading
  mounted(el,binding) {
    if(binding.value === true){
      createLoading(el)
    }
  },
  //update的时候
  updated(el,binding){
    //v-loading 的值为false,并且该节点下最后一个元素是loading时,移除节点
    if(binding.value === false && el.lastChild.dataset.v === 'loading'){
      el.removeChild(el.lastChild)
      return
    }
    //v-loading 的值为true,并且该节点下没有loading节点时,调用函数,挂载loading
    if(binding.value === true && el.lastChild.dataset.v !== 'loading'){
      createLoading(el)
    }
  }
}

//导出创建好的指令
export default vLoading

到此,指令已经创建好了,上述代码如果是在setup标签中创建的,那么在该页面中,组件或者标签 通过v-loading绑定即可使用,接下来我们挂载全局

//在main入口文件中,引入刚刚创建好的指令 
import vLoading from './composables/loading'

import {createApp} from "vue";
import "./style.scss";
import App from "./App.vue";
import vLoading from './composables/loading'
import router from "./router";

const app = createApp(App);
app.use(router);
// 调用app.directive,传入自定义指令名,和刚才定义好的指令内容
app.directive('loading',vLoading)

app.mount("#app");

接下来是在组件中的使用,通过变量控制显示与否即可

效果图如下,不会截动图,就这样啦

 

 

posted @ 2023-01-05 16:50  Lanny-Chung  阅读(1696)  评论(0编辑  收藏  举报