当前位置: 代码网 > it编程>编程语言>Javascript > vue如何使用element组件自定义v-loading

vue如何使用element组件自定义v-loading

2024年09月05日 Javascript 我要评论
使用element组定义v-loading文件夹目录src文件夹下面的directive.jsimport vue from 'vue';import loading from './loading.

使用element组定义v-loading

文件夹目录

src文件夹下面的directive.js

import vue from 'vue';
import loading from './loading.vue';
import { addclass, removeclass, getstyle } from 'element-ui/src/utils/dom';
import { popupmanager } from 'element-ui/src/utils/popup';
import afterleave from 'element-ui/src/utils/after-leave';
const mask = vue.extend(loading);
// mask 是一个虚拟dom
const loadingdirective = {};
loadingdirective.install = vue => {
  if (vue.prototype.$isserver) return;
  const toggleloading = (el, binding) => {
    if (binding.value) {
      vue.nexttick(() => {
        if (binding.modifiers.fullscreen) {
          el.originalposition = getstyle(document.body, 'position');
          el.originaloverflow = getstyle(document.body, 'overflow');
          el.maskstyle.zindex = popupmanager.nextzindex();

          addclass(el.mask, 'is-fullscreen');
          insertdom(document.body, el, binding);
        } else {
          removeclass(el.mask, 'is-fullscreen');

          if (binding.modifiers.body) {
            el.originalposition = getstyle(document.body, 'position');

            ['top', 'left'].foreach(property => {
              const scroll = property === 'top' ? 'scrolltop' : 'scrollleft';
              el.maskstyle[property] = el.getboundingclientrect()[property] +
                document.body[scroll] +
                document.documentelement[scroll] -
                parseint(getstyle(document.body, `margin-${ property }`), 10) +
                'px';
            });
            ['height', 'width'].foreach(property => {
              el.maskstyle[property] = el.getboundingclientrect()[property] + 'px';
            });

            insertdom(document.body, el, binding);
          } else {
            el.originalposition = getstyle(el, 'position');
            insertdom(el, el, binding);
          }
        }
      });
    } else {
      afterleave(el.instance, () => {
        if (!el.instance.hiding) return;
        el.domvisible = false;
        const target = binding.modifiers.fullscreen || binding.modifiers.body
          ? document.body
          : el;
        removeclass(target, 'el-loading-parent--relative');
        removeclass(target, 'el-loading-parent--hidden');
        el.instance.hiding = false;
      }, 300, true);
      el.instance.visible = false;
      el.instance.hiding = true;
    }
  };
  const insertdom = (parent, el, binding) => {
    if (!el.domvisible && getstyle(el, 'display') !== 'none' && getstyle(el, 'visibility') !== 'hidden') {
      object.keys(el.maskstyle).foreach(property => {
        el.mask.style[property] = el.maskstyle[property];
      });

      if (el.originalposition !== 'absolute' && el.originalposition !== 'fixed') {
        addclass(parent, 'el-loading-parent--relative');
      }
      if (binding.modifiers.fullscreen && binding.modifiers.lock) {
        addclass(parent, 'el-loading-parent--hidden');
      }
      el.domvisible = true;

      parent.appendchild(el.mask);
      vue.nexttick(() => {
        if (el.instance.hiding) {
          el.instance.$emit('after-leave');
        } else {
          el.instance.visible = true;
        }
      });
      el.dominserted = true;
    } else if (el.domvisible && el.instance.hiding === true) {
      el.instance.visible = true;
      el.instance.hiding = false;
    }
  };
  vue.directive('loading', { // 自定义全局指令
    bind: function(el, binding, vnode) {
      const textexr = el.getattribute('element-loading-text');
      const spinnerexr = el.getattribute('element-loading-spinner');
      const backgroundexr = el.getattribute('element-loading-background');
      const customclassexr = el.getattribute('element-loading-custom-class');
      const vm = vnode.context;
      const mask = new mask({
        el: document.createelement('div'),
        data: {
          text: vm && vm[textexr] || textexr,
          spinner: vm && vm[spinnerexr] || spinnerexr,
          background: vm && vm[backgroundexr] || backgroundexr,
          customclass: vm && vm[customclassexr] || customclassexr,
          fullscreen: !!binding.modifiers.fullscreen
        }
      });
      el.instance = mask;
      el.mask = mask.$el;
      el.maskstyle = {};

      binding.value && toggleloading(el, binding);
    },
    update: function(el, binding) {
      el.instance.settext(el.getattribute('element-loading-text'));
      if (binding.oldvalue !== binding.value) {
        toggleloading(el, binding);
      }
    },
    unbind: function(el, binding) {
      if (el.dominserted) {
        el.mask &&
        el.mask.parentnode &&
        el.mask.parentnode.removechild(el.mask);
        toggleloading(el, { value: false, modifiers: binding.modifiers });
      }
      el.instance && el.instance.$destroy();
    }
  });
};

export default loadingdirective;

index.js

import vue from 'vue';
import loadingvue from './loading.vue';
import { addclass, removeclass, getstyle } from 'element-ui/src/utils/dom';
import { popupmanager } from 'element-ui/src/utils/popup';
import afterleave from 'element-ui/src/utils/after-leave';
import merge from 'element-ui/src/utils/merge';

const loadingconstructor = vue.extend(loadingvue);

const defaults = {
  text: null,
  fullscreen: true,
  body: false,
  lock: false,
  customclass: ''
};

let fullscreenloading;

loadingconstructor.prototype.originalposition = '';
loadingconstructor.prototype.originaloverflow = '';

loadingconstructor.prototype.close = function() {
  if (this.fullscreen) {
    fullscreenloading = undefined;
  }
  afterleave(this, () => {
    const target = this.fullscreen || this.body
      ? document.body
      : this.target;
    removeclass(target, 'el-loading-parent--relative');
    removeclass(target, 'el-loading-parent--hidden');
    if (this.$el && this.$el.parentnode) {
      this.$el.parentnode.removechild(this.$el);
    }
    this.$destroy();
  }, 300);
  this.visible = false;
};

const addstyle = (options, parent, instance) => {
  let maskstyle = {};
  if (options.fullscreen) {
    instance.originalposition = getstyle(document.body, 'position');
    instance.originaloverflow = getstyle(document.body, 'overflow');
    maskstyle.zindex = popupmanager.nextzindex();
  } else if (options.body) {
    instance.originalposition = getstyle(document.body, 'position');
    ['top', 'left'].foreach(property => {
      let scroll = property === 'top' ? 'scrolltop' : 'scrollleft';
      maskstyle[property] = options.target.getboundingclientrect()[property] +
        document.body[scroll] +
        document.documentelement[scroll] +
        'px';
    });
    ['height', 'width'].foreach(property => {
      maskstyle[property] = options.target.getboundingclientrect()[property] + 'px';
    });
  } else {
    instance.originalposition = getstyle(parent, 'position');
  }
  object.keys(maskstyle).foreach(property => {
    instance.$el.style[property] = maskstyle[property];
  });
};
const loading = (options = {}) => {
  if (vue.prototype.$isserver) return;
  options = merge({}, defaults, options);
  if (typeof options.target === 'string') {
    options.target = document.queryselector(options.target);
  }
  options.target = options.target || document.body;
  if (options.target !== document.body) {
    options.fullscreen = false;
  } else {
    options.body = true;
  }
  if (options.fullscreen && fullscreenloading) {
    return fullscreenloading;
  }

  let parent = options.body ? document.body : options.target;
  let instance = new loadingconstructor({
    el: document.createelement('div'),
    data: options
  });
  addstyle(options, parent, instance);
  if (instance.originalposition !== 'absolute' && instance.originalposition !== 'fixed') {
    addclass(parent, 'el-loading-parent--relative');
  }
  if (options.fullscreen && options.lock) {
    addclass(parent, 'el-loading-parent--hidden');
  }
  parent.appendchild(instance.$el);
  vue.nexttick(() => {
    instance.visible = true;
  });
  if (options.fullscreen) {
    fullscreenloading = instance;
  }
  return instance;
};
export default loading;

loading.vue (这是核心文件也就是在页面怎么展示效果的v-loading)

<template>
  <div class="loading-index">
    <transition name="el-loading-fade" @after-leave="handleafterleave">
      <div
        v-show="visible"
        class="el-loading-mask"
        :style="{ backgroundcolor: background || '' }"
        :class="[customclass, { 'is-fullscreen': fullscreen }]"
      >
        <div class="el-loading-spinner">
          <!-- <svg v-if="!spinner" class="circular" viewbox="25 25 50 50">
          <circle class="path" cx="50" cy="50" r="20" fill="none"/>
        </svg>
        <i v-else :class="spinner"></i>
        <p v-if="text" class="el-loading-text">{{ text }}</p> -->
          <div class="number">
            <span
              v-for="(item, index) in 'loading...'"
              :style="
                'animation: totop 1.5s ' + 0.1 * index + 's infinite ease-out'
              "
              :key="index"
            >
              {{ item }}
            </span>
          </div>
        </div>
      </div>
    </transition>
  </div>
</template>
<script>
export default {
  data() {
    return {
      text: null,
      spinner: null,
      background: null,
      fullscreen: true,
      visible: false,
      customclass: "",
    };
  },

  methods: {
    handleafterleave() {
      this.$emit("after-leave");
    },
    settext(text) {
      this.text = text;
    },
  },
};
</script>
<style lang="less">
.loading-index {
  .number {
    line-height: 250px;
    font-size: 24px;
    color: #000;
    text-align: center;
    span {
      position: relative;
      margin-right: -6px;
    }
  }
  @keyframes totop {
    0% {
      top: 0;
    }
    24% {
      top: 0;
    }
    33% {
      top: -7px;
    }
    39% {
      top: -7px;
    }
    45% {
      top: 0;
    }
    100% {
      top: 0;
    }
  }
}
</style>

在跟loading文件夹建立index.js(一定要跟src同级)

import directive from './src/directive';
import service from './src/index';
export default {
  install(vue) {
    vue.use(directive);
    vue.prototype.$loading = service;
  },
  directive,
  service
};

在main.js中引入

注意:一定要注意先后顺序,否责无法实现

效果图片

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com