Vue 封装 loading 自定义指令

3,965 阅读1分钟

Vue 封装loading自定义指令

一、前言

在项目中,免不了要请求一些数据,一般都会在数据请求时加上loading效果,提高用户体验,而且这个可以用在项目的需求地方,所以为了减少代码重复,就可以封装成自定义指令,在需要使用的地方加上就行。

二、实现

1. 编写loading组件
<template>
  <div class="loading-wrap">
    <img src="../assets/loading.gif" alt="加载...">
  </div>
</template><script>
export default {
  name: 'Loading'
}
</script><style scoped>
.loading-wrap {
  position: absolute;
  top: 50%;
  width: 100%;
  transform: translateY(-50%);
}
​
.loading-wrap img {
  width: 100px;
  height: 100px;
}
</style>
2. 定义loading指令
import Vue from 'vue'
// 引入 loading 组件
import Loading from '../components/Loading.vue'
​
// 定义 loading 指令
const loadingDirective = {
  inserted: function(el, binding) {
    // 创建 loading 组件构造函数
    const LoadingCtor = Vue.extend(Loading)
    // new 一个 loading组件实例
    const loadingInstance = new LoadingCtor()
    // 组件挂载
    el.instance = loadingInstance.$mount()
    // 传入值为 true 时才展示
    if (binding.value) {
      // 将组件挂载到绑定指令的元素上
      append(el)
    }
  },
  update(el, binding) {
    // 值更新时进行操作
    if (binding.value !== binding.oldValue) {
      binding.value ? append(el) : remove(el)
    }
  }
}
​
function append(el) {
  el.appendChild(el.instance.$el)
}
​
function remove(el) {
  el.removeChild(el.instance.$el)
}
​
export default loadingDirective
3. 注册loading自定义指令
import Vue from 'vue'
import App from './App.vue'
// 引入 loading 自定义指令
import loadingDirective from './directive/loading.js'Vue.config.productionTip = falseVue.directive('loading', loadingDirective)
​
new Vue({
  render: h => h(App),
}).$mount('#app')
​
4. 使用loading指令
<template>
  <div id="app"  v-loading="loading">
    <img alt="Vue logo" src="./assets/logo.png">
    <HelloWorld msg="Welcome to Your Vue.js App"/>
  </div>
</template><script>
import HelloWorld from './components/HelloWorld.vue'export default {
  name: 'App',
  components: {
    HelloWorld
  },
  data() {
    return {
      fetchData: []
    }
  },
  mounted() {
    setTimeout(() => {
      this.fetchData = [1, 2, 3, 4, 5]
    }, 5000)
  },
  computed: {
    loading() {
      return !this.fetchData.length
    }
  }
}
</script><style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>