JS怎么实现loading加载
这篇文章主要讲解了“JS怎么实现loading加载”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“JS怎么实现loading加载”吧!
防抖节流自定义指令
一、问题现象
操作系统流程时,网速过慢,点击【按钮】,页面没有及时反应;用户感知不到,再次点击按钮,系统流程报错。
二、想法
控制按钮操作时的频繁接口调用,通过防抖操作进行处理
三、实现
封装自定义指令v-debounce
import Vue from 'vue';//按钮防抖动指令Vue.directive('debounce', { inserted(el, binding) { el.addEventListener('click', () => { if (!el.disabled) { el.disabled = true; setTimeout(() => { el.disabled = false; }, binding.value || 3 * 1000); // 三秒之内点击不会触发接口调用 } }); },});
在main.js文件中引入文件
import '@/utils/directives.js';
项目的template中使用
<el-button type="primary" class="change-btns" @click="sendCode()" v-debounce>发送验证码</el-button>
loading加载
考虑到项目本身可能已经进入尾声,再应用自定义指令的话,需要耗费时间,逐一排查按钮操作,费时费力。
一、想法
想要减少时间,肯定需要统一配置处理,考虑到控制接口的频繁调用和操作频繁等问题,或许通过页面整体不可点击的方式进行处理,那就是接口调用时控制页面加载。
二、实现
首先写一个loading.vue组件
<!-- * @Author: Winter_Bear * @Date: 2023-03-25 16:18:16 * @LastEditors: zh * @LastEditTime: 2023-03-25 16:55:18 * @Description: loading组件--><template> <div v-if="visable" class="loaidng"> <transition name="animation"> <div class="load"> <img alt="" class="img" class="lazy" data-src="@/assets/image/loading.png" /> </div> </transition> </div></template><script>export default { data() { return { visable: false, }; },};</script><style scoped>.loaidng { width: 100% !important; height: 100% !important; display: -webkit-flex !important; display: -webkit-box !important; display: -moz-box !important; display: -ms-flexbox !important; display: flex !important; justify-content: center !important; align-items: center !important; position: fixed !important; top: 0 !important; right: 0 !important; bottom: 0 !important; left: 0 !important; background: rgba(0, 0, 0, 0); color: #282828; font-size: 20px; z-index: 999999;}.load { background-clip: text; -webkit-position: relative !important; position: relative !important;}.img { width: 75px; animation: rotation 5s linear infinite; animation: rotation 2s linear infinite; -moz-user-select: -moz-none; -khtml-user-select: none; -webkit-user-select: none; -o-user-select: none; user-select: none;}.no-scroll { height: 100vh;}.no-scroll > * { position: sticky; top: 0;}@keyframes rotation { 0% { -webkit-transform: rotate(0deg); } 100% { -webkit-transform: rotate(360deg); }}</style>
封装loading.js文件
import Loading from './index.vue';//先创建一个空实例let instance = null;let winX = null;let winY = null;window.addEventListener('scroll', function () { if (winX !== null && winY !== null) { window.scrollTo(winX, winY); }});function disableWindowScroll() { winX = window.scrollX; winY = window.scrollY;}function enableWindowScroll() { winX = null; winY = null;}export default { install(Vue) { if (!instance) { //构造器 /子类 let MyLoading = Vue.extend(Loading); instance = new MyLoading({ //创建一个div,并挂载上去 el: document.createElement('div'), }); document.body.appendChild(instance.$el); } //自定义一些方法,操作loading的显示与隐藏关 let customMethods = { async start() { console.log(instance); instance.visable = true; disableWindowScroll(); var mo = function (e) { passive: false; }; }, finish() { instance.visable = false; enableWindowScroll(); var mo = function (e) { passive: false; }; }, }; //挂载到自定义方法vue示例上 if (!Vue.$loading) { Vue.$loading = customMethods; //挂载到原型上 Vue.prototype.$loading = Vue.$loading; } else { console.log('$loading方法已被占用'); } },};
在main.js中挂载到全局Vue的原型上
import $loading from '@/components/loading/loading.js';Vue.use($loading);
在request.js接口请求和响应拦截时做处理
import Vue from 'vue';import axios from 'axios';import store from '@/store';import router from '@/router';import messageup from './resetMessage.js';import commonService from '@/api/common.js';import storage from '@/utils/storage';import { setToken, setRefreshToken } from '@/utils/auth.js';const service = axios.create({ baseURL: process.env.VUE_APP_appBaseUrl, // 跨域请求时是否需要使用凭证 withCredentials: false, // 请求 1000s 超时 timeout: 1000 * 60 * 60,});let loadingSum = 0;let isRefreshing = false; // 标记是否正在刷新 token, 防止多次刷新tokenlet requests = []; // 存储待重发请求的数组(同时发起多个请求的处理)// 请求拦截器service.interceptors.request.use( (config) => { loadingSum++; if (loadingSum == 1) { Vue.$loading.start(); } let EnterpriseToken = ''; storage.get('CLIENTID', (data) => { EnterpriseToken = data; }); if (EnterpriseToken) { config.headers.EnterpriseToken = EnterpriseToken; } return config; }, (error) => { messageup({ message: '服务异常!', type: 'error', showClose: true, duration: 0, }); return Promise.resolve(error); },);// 响应拦截器service.interceptors.response.use( (response) => { let config = response.config; let url = response.config.url; const code = response.data.code; loadingSum--; if (loadingSum == 0) { Vue.$loading.finish(); } if (['701', '702'].includes(code)) { storage.removeAll(); router.replace('/sign').catch((err) => err); messageup({ message: response.data.message, type: 'error', }); return; } else if (code == '801') { //这部分属于强制登录的逻辑状态处理 if (!isRefreshing) { loadingSum++; if (loadingSum == 1) { Vue.$loading.start(); } isRefreshing = true; let getRefreshToken = ''; storage.get('REFCLIENTID', (data) => { getRefreshToken = data; }); if (getRefreshToken) { return new Promise((resolve, reject) => { let data = { refreshToken: getRefreshToken, }; commonService .refreshToken(data) .then((res) => { if (res && res.data && res.data.code == '200') { const { clientid, refreshid } = res.data.data; setToken(clientid); setRefreshToken(refreshid); config.headers.EnterpriseToken = clientid; // token 刷新后将数组的方法重新执行 requests.forEach((cb) => cb(clientid)); requests = []; // 重新请求完清空 resolve(service(config)); } else { requests = []; storage.removeAll(); router.replace('/sign').catch((err) => err); } }) .catch((err) => { return Promise.reject(err); }) .finally(() => { isRefreshing = false; loadingSum--; if (loadingSum == 0) { Vue.$loading.finish(); } }); }); } else { loadingSum--; if (loadingSum == 0) { Vue.$loading.finish(); } } } else { // 返回未执行 resolve 的 Promise return new Promise((resolve) => { // 用函数形式将 resolve 存入,等待刷新后再执行 requests.push((token) => { config.headers.EnterpriseToken = token; resolve(service(config)); }); }); } } else { return response; } }, (error) => { loadingSum--; if (loadingSum == 0) { Vue.$loading.finish(); } messageup({ message: error.message, type: 'error', showClose: true, duration: 0, }); return Promise.reject(error); },);export default { post(url, data = {}, headers = {}) { return new Promise((resolve, reject) => { service.post(url, data, headers).then( (response) => { resolve(response); }, (err) => { reject(err); }, ); }); }, get(url, params = {}, headers = {}) { return new Promise((resolve, reject) => { service .get(url, { params: params, headers: headers, }) .then((response) => { resolve(response); }) .catch((err) => { reject(err); }); }); }, when(arry = []) { if (arry.length <= 1) { return arry[0]; } else { let arr = []; let length = arry.length; for (let i = 0; i < length; i++) { arr.push('res' + i); } return new Promise((resolve, reject) => { axios.all(arry).then( axios.spread((...arr) => { resolve(arr); }), ); }); } },};
感谢各位的阅读,以上就是“JS怎么实现loading加载”的内容了,经过本文的学习后,相信大家对JS怎么实现loading加载这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341