vue中实现v-loading自定义指令

项目目录结构

src/
├── assets/
│   └── css/
│       └── loading.css       # 加载动画样式文件 (新增)
├── directives/               # 自定义指令目录 (新增)
│   └── loading.js            # v-loading 指令逻辑 (新增)
├── plugins/                  # 插件目录 (可选)
│   └── directives.js         # 全局指令注册入口 (可选)
├── main.js                   # 项目入口文件
└── components/               # 组件目录

 1. 样式文件 (src/assets/css/loading.css)

/* 加载层样式 */
.loading-wrapper {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: rgba(255, 255, 255, 0.7);
  display: flex;
  justify-content: center;
  align-items: center;
  pointer-events: none;
}

/* 加载动画 */
.loading-spinner {
  width: 30px;
  height: 30px;
  border: 3px solid #f3f3f3;
  border-radius: 50%;
  border-top-color: #3498db;
  animation: rotating 1s linear infinite;
}

@keyframes rotating {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}


 2. 指令逻辑 (src/directives/loading.js)

const toggleLoading = (el, binding) => {
  if (binding.value) {
    // 确保父元素有定位属性
    if (window.getComputedStyle(el).position === 'static') {
      el.style.position = 'relative'
    }
    
    // 添加加载层
    if (!el.contains(el.loadingElement)) {
      el.appendChild(el.loadingElement)
    }
  } else {
    // 移除加载层
    if (el.contains(el.loadingElement)) {
      el.removeChild(el.loadingElement)
    }
  }
}

export default {
  inserted(el, binding) {
    // 创建加载层
    const loadingDiv = document.createElement('div')
    loadingDiv.className = 'loading-wrapper'
    
    // 创建加载动画
    const spinner = document.createElement('div')
    spinner.className = 'loading-spinner'
    loadingDiv.appendChild(spinner)

    el.loadingElement = loadingDiv
    toggleLoading(el, binding)
  },

  update(el, binding) {
    if (binding.value !== binding.oldValue) {
      toggleLoading(el, binding)
    }
  },

  unbind(el) {
    if (el.loadingElement && el.contains(el.loadingElement)) {
      el.removeChild(el.loadingElement)
    }
    el.loadingElement = null
  }
}


3. 全局注册 (src/plugins/directives.js) - 可选

import loadingDirective from '@/directives/loading'

export default {
  install(Vue) {
    Vue.directive('loading', loadingDirective)
  }
}

 4. 在入口文件注册 (src/main.js)

import Vue from 'vue'
import App from './App.vue'
import DirectivesPlugin from './plugins/directives'  // 导入指令插件
import '@/assets/css/loading.css'                  // 导入样式

Vue.use(DirectivesPlugin)  // 注册全局指令

new Vue({
  render: h => h(App)
}).$mount('#app')

使用方式
在任意组件中直接使用:

<template>
  <div v-loading="isLoading" class="content-box">
    <!-- 你的内容 -->
  </div>
</template>

<script>
export default {
  data() {
    return { isLoading: true }
  }
}
</script>


项目结构优势说明:
1. 模块化分离:将指令逻辑、样式和注册逻辑分离
2. 可维护性:每个指令独立文件,方便后续扩展
3. 全局可用:通过入口文件注册后全项目可用
4. 样式统一管理:CSS 文件集中存放便于维护

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值