自定义指令 v-loading

1. 在src下创建directive文件夹

2. 在directive文件夹下创建loading文件夹

3. loading文件夹内创建index.js和loading.vue

目录图:

 4. index.js

// src/directive/loading/index.js

import Vue from 'vue'
import Loading from './loading.vue'

/**
 * Vue.extend 接受参数并返回一个构造器,new 该构造器可以返回一个组件实例
 * 当我们 new Mask() 的时候,把该组件实例挂载到一个 div 上
 **/
 const Mask = Vue.extend(Loading)

/**
 * 如果loading.vue组件是模式export default vue.extend({})
 * 则直接用下面的这一行代码就行
 **/
 // const Mask = Loading

// 更新是否显示
const toggleLoading = (el, binding) => {
  if (binding.value) {
    Vue.nextTick(() => {
      // 控制loading组件显示
      el.instance.visible = true
      // 插入到目标元素
      insertDom(el, el, binding)
    })
  } else {
    el.instance.visible = false
  }
}

 //插入到目标元素
const insertDom = (parent, el) => {
  parent.appendChild(el.mask)
}

export default {
  //第一次绑定到元素时调用
  bind: function (el, binding, vnode) {
    console.log("el",el,"binding",binding)
    const mask = new Mask({
      el: document.createElement('div'),
      data () {}
    })
    //用一个变量接住mask实例
    el.instance = mask
    el.mask = mask.$el
    el.maskStyle = {}
    binding.value && toggleLoading(el, binding)
  },
  //所在组件的 VNode 更新时调用--比较更新前后的值
  update: function (el, binding) {
    if (binding.oldValue !== binding.value) {
      toggleLoading(el, binding)
    }
  },
  //指令与元素解绑时调用
  unbind: function (el, binding) {
    el.instance && el.instance.$destroy()
  }
}

5. loading.vue

// src/directive/loading/Loading.vue
<template>
  <div v-show="visible" class="loading-wrap">
    <div class="loading-box">加载中...</div>
  </div>
</template>

<script>
// import Vue from "vue";
// export default Vue.extend({
//   data() {
//     return {
//       visible: true,
//     };
//   },
// });
export default {
  data() {
    return {
      visible: true,
    };
  },
};
</script>
<style lang="scss" scoped>
.loading-wrap {
  position: relative;
  width: 100%;
  height: 100%;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.5);
}
.loading-box {
  position: relative;
  left: 50%;
  top: 50%;
  width: 100px;
  transform: translate(-50%, -50%);
}
</style>

6. directive下的index.js

import Loading from "./loading"
export default {
  install(Vue) {
    Vue.directive("loading", Loading);
  },
};

7. main.js中使用插件

import Directive from './directive'

Vue.use(Directive)

8. 项目中使用

<template>
  <div class="app-container">
    <div class="loading">
        <el-button class="btn" size="mini" @click="loadingClick">loading</el-button>
      <div class="loading-div" v-loading="loading"></div>
    </div>
  </div>
</template>

<script>

export default {
  data() {
    return {
      loading: false,
    };
  },
  methods: {
    loadingClick (){
      this.loading = true;
      setTimeout(() => {
        this.loading =  false
      },2000)
    }
  },
};

</script>

<style lang="scss" scoped>

.loading {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100%;
  height: 50px;
  border: solid gray 1px;
  .btn {
    margin-right: 10px;
  }
  .loading-div {
    display: inline-block;
    border: solid red 1px;
    width: 200px;
    height: 40px;
  }
}

</style>

8. 效果

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

好喝的西北风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值