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. 效果