-
2021-05-21 10:52:14
前言:需要获取后端接口数据到页面上进行显示,所以在请求发起至数据渲染页面的这段时间,为页面提供一个 loading 加载是极为必要的。
1.区域加载
以 table 表格为例,使用 v-loading,为其绑定一个布尔值(true/false),代码如下:<template> <div id="index"> <!-- 表格 --> <el-table :data="tableData" v-loading="loading"> <el-table-column type="selection"></el-table-column> <el-table-column sortable prop="name" label="姓名"></el-table-column> <el-table-column sortable prop="number" label="代号"></el-table-column> <el-table-column sortable prop="age" label="年龄"></el-table-column> <el-table-column sortable prop="sex" label="性别"> <template slot-scope="scope"> <el-tag :type="scope.row.sex === '1' ? 'primary' : 'success'" disable-transitions> {{scope.row.sex==='1'? '男': '女'}}</el-tag> </template> </el-table-column> </el-table> </div> </template> <script> export default { name: "index", data () { return { loading: false, // 默认为false不显示加载 tableData:[] // 数据 } }, created() { // 调用获取数据方法 this.getdata() }, methods: { // 获取数据方法 getdata() { this.loading = true // 模拟获取接口数据 setTimeout(() => { this.tableData = [ // 模拟数据 { name: 'wangfu', number: '001', age: '24', sex: '1' }, { name: 'wangfu', number: '001', age: '24', sex: '1' } ], this.loading = false }, 1000) } } }
2.自定义加载
添加 element-loading-text 属性为加载文字显示在加载图标的下方, element-loading-spinner 属性为设定图标的类名,element-loading-background 属性为背景色值,代码如下:<el-table :data="tableData" v-loading="loading" element-loading-text="拼命加载中" element-loading-spinner="el-icon-loading" element-loading-background="rgba(0, 0, 0, 0.8)"></el-table> ` 3.整页加载 使用指令方式来实现整页加载时,全屏遮罩需要添加fullscreen修饰符(遮罩会插入至 body 上),此时若需要锁定屏幕的滚动,可以使用lock修饰符,代码如下: ```javascript v-loading.fullscreen.lock="loading"
更多相关内容 -
解析elementui 中的v-loading指令
2021-05-26 10:48:15剖析v-loading源码 在工作中主要做pc端的后台系统,使用的ui库为elementui,相信使用vue的小伙伴对其并不陌生,下面我就对其中的v-loding的源码进行剖析 loading.vue <template> <transition name="el-loading-fade...钩子函数
一个指令定义对象可以提供如下几个钩子函数 (均为可选):- bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
- inserted:被绑定元素插入父节点时调用
(仅保证父节点存在,但不一定已被插入文档中)。 - update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode
更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 (详细的钩子函数参数见下)。
我们会在稍后讨论渲染函数时介绍更多 VNodes 的细节。
- componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。
- unbind:只调用一次,指令与元素解绑时调用。
接下来我们来看一下钩子函数的参数 (即 el、binding、vnode 和 oldVnode)。
钩子函数参数
- el:指令所绑定的元素,可以用来直接操作 DOM。
- binding:一个对象,包含以下 property:
- name:指令名,不包括 v- 前缀。
- value:指令的绑定值,例如:v-my-directive=“1 + 1” 中,绑定值为 2。
- oldValue:指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
- expression:字符串形式的指令表达式。例如 v-my-directive=“1 + 1” 中,表达式为 “1 + 1”。
- arg:传给指令的参数,可选。例如 v-my-directive:foo 中,参数为 “foo”。
- modifiers:一个包含修饰符的对象。例如:v-my-directive.foo.bar 中,修饰符对象为 { foo: true,
bar: true }。 - vnode:Vue 编译生成的虚拟节点。移步 VNode API 来了解更多详情。
- oldVnode:上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。
剖析v-loading源码
在工作中主要做pc端的后台系统,使用的ui库为elementui,相信使用vue的小伙伴对其并不陌生,下面我就对其中的v-loding的源码进行剖析loading.vue
<template> <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> </div> </transition> </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>
directive.js
import Vue from 'vue'; import Loading from './loading.vue'; // addClass为对应元素添加类名,removeClass删除对应的类名 getStyle获取对应的行内属性 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'; // 使用loading组件配置项创建vue子类构造函数 const Mask = Vue.extend(Loading); const loadingDirective = {}; loadingDirective.install = Vue => { // 是服务端渲染直接返回 if (Vue.prototype.$isServer) return; const toggleLoading = (el, binding) => { if (binding.value) { Vue.nextTick(() => { // 一个包含修饰符的对象 eg:v-loading.fullscreen.lock="fullscreenLoading" 获取是否使用fullscreen操作符 // 当使用指令方式时,全屏遮罩需要添加fullscreen修饰符(遮罩会插入至 body 上) 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'); // Loading 遮罩会插入到绑定元素的子节点,通过添加body修饰符,可以使遮罩插入至 DOM 中的 body 上 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; // 表示loading组件是否隐藏 el.instance.hiding = true; } }; // 将对应的 loading组件渲染出来的dom插入到parent对应的dom上 const insertDom = (parent, el, binding) => { // 若在前一个全屏 Loading 关闭前再次调用全屏 Loading,并不会创建一个新的 Loading 实例,而是返回现有全屏 Loading 的实例(当el.domVisible为true时说明loading组件已经插入到页面上了) if (!el.domVisible && getStyle(el, 'display') !== 'none' && getStyle(el, 'visibility') !== 'hidden') { // 将行内样式赋值到loading组件渲染出的dom上 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; } }); // 表示已经将对应的dom插入到页面中了 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) { // 获取绑定指令元素对应元素的属性值,传入到loading组件的data中 // 在绑定了v-loading指令的元素上添加element-loading-text属性,其值会被渲染为加载文案,并显示在加载图标的下方。类似地,element-loading-spinner和element-loading-background属性分别用来设定图标类名和背景色值 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 } }); // 将实例放到对应元素dom的instance上 el.instance = mask; // 将实例loading组件渲染出来的dom放到mask属性上 el.mask = mask.$el; // 存放loading渲染出来的dom属性的行内样式 el.maskStyle = {}; // 当值为true时调用 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) { // domInserted是否插入到页面的标识,在insertDom方法中被赋值为true 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;
-
v-loading
2019-10-29 17:32:37element-ui 内置的 v-loading 指令非常友好,只需要提供一个 Boolean 值就能实现加载动画的一个指令。 具体的使用方法归纳为:接口请求到数据之前,显示加载中。接口请求到数据之后,消失。 项目案例截图: 具体的...element-ui 内置的 v-loading 指令非常友好,只需要提供一个 Boolean 值就能实现加载动画的一个指令。
具体的使用方法归纳为:接口请求到数据之前,显示加载中。接口请求到数据之后,消失。项目案例截图:
具体的功能为当我点击“查询”按钮之后,对应的查询清单list会呈现出来
首先在需要加载的dom中加入v-loading=“loading”
在data 中定义初始化, loading: false,同时在mounted()中将 this.loading设置为true,再去请求接口。
同时在接口的回调函数中,将 this.loading 设为false,到达效果。
-
自定义指令 v-loading
2021-12-17 14:06:05v-loading,自定义指令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. 效果
-
手写 vue 自定义指令(directive) v-loading 加载, 项目实战
2021-10-11 15:56:35手写 vue 自定义指令 v-loading 目标效果: 在vue项目的标签里面使用 v-loading="true" ,如同element-ui里面使用v-loading一样 会展示loading 效果。 在这里我做两个laoding效果: 一个全屏的loading效果,用于... -
element-plus dialog v-loading不生效
2022-01-23 19:31:57el-dialog的v-loading 这样使用没反应。 解决 定义ref 并使用 ElLoading.service setup定义 const me = ref(null) ElLoading.service({ target: me.value.dialogRef }) 结束语 为什么v-loading不生效,有人知道... -
vue自定义指令之手写v-loading指令
2021-06-07 16:37:10自定义加载效果的loading指令 为什么不创建一个组件来加载loading效果: 麻烦你得先引入组件,注册挂载组件,然后在通过v-if在空子显示隐藏 为什么要用自定义loading指令: 由于项目中很多地方需要用到,在... -
记录 element-ui v-loading 指令 instance.close() 报错问题
2022-03-31 21:58:58记录 element-ui v-loading 指令 instance.close() 报错问题 背景 解决 sentry issues 时看到一个这样的报错 TypeError: Cannot read properties of undefined (reading ‘close’) 报错的代码来自 element-plus ... -
vue2.x自定义v-loading指令
2021-12-26 22:36:24(vue3.x自定义v-loading思路类似) directive.js import Loading from './loading'; import Vue from 'vue'; const loadingDirective = { inserted(el, binding){ const loading = Vue.extend(Loading); el.... -
vue 给页面增加自定义指令 v-loading
2021-11-26 15:59:54新建一个loading文件夹(新建index.js、loading.js、loading.vue) index.js import loading from './loading' export default { install (Vue) { Vue.directive('loading', loading) } } loading.js // ... -
vue自定义指令v-loading
2021-07-14 13:28:491.在 src目录下创建一个directiveLoading文件夹,然后这个文件夹下创建1个loading文件夹和index.js文件,loading文件夹下分别创建Loading.vue和index.js文件。 directiveLoading的index.js文件用来暴露安装插件接口... -
element-ui的v-loading不生效
2021-08-25 14:06:07按照官方文档引入Loading后,全局引入位置加 Vue.use(Loading.directive); -
Vue3.0 + Ts 项目使用element-plus 自动按需导入 使用v-loading报错
2022-04-18 23:01:48使用v-loading报错 无法找到样式 element-plus/es/components/loading-directive/style/css 解决办法: element-plus版本: "element-plus": "^2.1.9" "unplugin-auto-import": "^0.7.1", "unplugin-vue-... -
element v-loading 文字描述 icon颜色 字体颜色
2021-12-27 12:02:36element-loading-text="数据加载中..." class="loading-map" icon颜色和字体颜色 <style> /* 地图上的loading样式 */ .loading-map .el-loading-mask { z-index: 0 !important; background-color: rgba(0... -
解决uni-app创建的H5项目只使用v-loading,避免引入element-ui过于笨重问题
2021-12-15 12:30:011、准备loading.js import Vue from 'vue' /** * 插入loading */ const insertDom = (el) =>...div class="el-loading-mask"> <div class="el-loading-spinner"> <svg viewBox="25 25 50 50" cl -
element v-loading 局部加载带滚动条时文字始终居中
2022-03-25 17:25:14<div> <div v-show="loadingVisible" ... element-loading-background="rgba(2, 25, 51, 0.3)" element-loading-text="匹配中" > </div> <div> //主体内容 </div> < -
vue v-loading指令
2019-11-14 20:06:48<template> .course-wrapper(v-loading='Object.keys(resource).length <= 0') </template> v-loading的作用:在请求到数据...(如果)v-loading写在template的顶层元素上,不会触发全局loading。... -
分享-简单实现一个vue3 v-loading自定义指令
2021-06-08 15:55:39./components/loading/loading.vue ...div class="loading-content"> <img width="24" height="24" src="./loading.gif" /> <p class="desc">{{ title }}</p> </div> < -
Vue + elementUi:v-loading使用
2021-05-18 10:47:13记录一下v-loading="tableloading"使用 在table数据渲染时使用,HTML中添加: v-loading=“tableloading” <el-table ref="dynamictable" :data="form.coldata" v-loading="tableloading" tooltip-effect=... -
vue加载动画element ui V-loading属性 踩坑记录
2021-12-14 15:46:59根据需求,由预览按钮打开弹窗,且弹窗需要渲染的数据较多,渲染的速度比较慢,所以要加一个加载中的效果,element ui的 v-loading属性就正好可以解决这一需求,但是当加入这一属性之后发现,是实现了加载功能,但是... -
v-loading修改z-index
2021-01-09 01:02:16<template> <div :id="id" :class="className" :style="{height:height,width:width}" v-loading="loading" ... element-loading-spinner="el-icon-loading"/> </template> <script&g. -
element之v-loading以及颜色修改
2021-01-13 11:04:00当你已经发送了请求,但是数据还没有请求回来的时候,呈现一个数据正在加载的状态,可以通过v-loading指令来展示加载状态。 只需要把v-loading的值绑定为true或false即可。 <el-table v-loading="loading" :data=... -
v-loading在可变高度元素上使用
2021-09-06 14:33:51v-loading在可变高度元素上使用时,元素出现竖向滚动条时,loading无法全覆盖此时可用v-loading.body指令即可 -
vue3自定义v-loading指令directives
2021-11-19 16:54:04vue3自定义v-loading指令directives 1.在项目的src下创建一个directives...div class="loading-container"> <Loading size="300" /> </div> </template> <script lang="ts"> import { -
elementUI v-loading不显示问题
2021-03-04 17:55:30elementUI v-loading不显示问题问题描述:解决办法:**分析:** 问题描述: 1. data(){listLoading:true}中已经声明了 2.el-table中绑定了这个属性 3.methods:{}中请求接口中也写了赋值操作(为什么不显示?)... -
v-loading的customClass使用方法
2021-12-07 18:52:08<div class="tool-container" v-loading="loading" element-loading-text="数据加载中,请稍后……" ... element-loading-custom-class="loading-icon" > </div> 绑定的类loading-ico -
vue使用gif图修改v-loading的图标
2021-06-22 11:27:38.el-loading-spinner .circular{ width: 42px; height: 42px; animation: loading-rotate 2s linear infinite; display: none; } .el-loading-spinner{ background: url(./assets/img/loading-1.gif) no-repeat... -
element ui自带的v-loading的使用方法以及背景变透明
2021-12-03 13:50:47el-card v-loading="loading" shadow="hover" element-loading-background="rgba(0, 0, 0, 0)" > 在data里定义loading变量,初始值为true。在请求后台的前面写loading=true,后面写loading=false。 加载的时候会...