|
目录
- 使用element组定义v-loading
- 文件夹目录
- loading.vue (这是核心文件也就是在页面怎么展示效果的v-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中引入
注意:一定要注意先后顺序,否责无法实现
效果图片
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持晓枫资讯。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |
晓枫资讯-科技资讯社区-免责声明
免责声明:以上内容为本网站转自其它媒体,相关信息仅为传递更多信息之目的,不代表本网观点,亦不代表本网站赞同其观点或证实其内容的真实性。
1、注册用户在本社区发表、转载的任何作品仅代表其个人观点,不代表本社区认同其观点。
2、管理员及版主有权在不事先通知或不经作者准许的情况下删除其在本社区所发表的文章。
3、本社区的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,举报反馈:  进行删除处理。
4、本社区一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
5、以上声明内容的最终解释权归《晓枫资讯-科技资讯社区》所有。
|