JS實(shí)用技巧實(shí)現(xiàn)loading加載示例詳解
防抖節(jié)流自定義指令
一、問題現(xiàn)象
操作系統(tǒng)流程時(shí),網(wǎng)速過慢,點(diǎn)擊【按鈕】,頁面沒有及時(shí)反應(yīng);用戶感知不到,再次點(diǎn)擊按鈕,系統(tǒng)流程報(bào)錯(cuò)。
二、想法
控制按鈕操作時(shí)的頻繁接口調(diào)用,通過防抖操作進(jìn)行處理
三、實(shí)現(xiàn)
第一步:封裝自定義指令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); // 三秒之內(nèi)點(diǎn)擊不會觸發(fā)接口調(diào)用 } }); }, });
第二步:在main.js文件中引入文件
import '@/utils/directives.js';
第三步:項(xiàng)目的template中使用
<el-button type="primary" class="change-btns" @click="sendCode()" v-debounce>發(fā)送驗(yàn)證碼</el-button>
loading加載
考慮到項(xiàng)目本身可能已經(jīng)進(jìn)入尾聲,再應(yīng)用自定義指令的話,需要耗費(fèi)時(shí)間,逐一排查按鈕操作,費(fèi)時(shí)費(fèi)力。
一、想法
想要減少時(shí)間,肯定需要統(tǒng)一配置處理,考慮到控制接口的頻繁調(diào)用和操作頻繁等問題,或許通過頁面整體不可點(diǎn)擊的方式進(jìn)行處理,那就是接口調(diào)用時(shí)控制頁面加載。
二、實(shí)現(xiàn)
- 首先寫一個(gè)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" 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; /* 新版本語法: Chrome 21+ */ display: -webkit-box !important; /* 老版本語法: Safari, iOS, Android browser, older WebKit browsers. */ display: -moz-box !important; /* 老版本語法: Firefox (buggy) */ display: -ms-flexbox !important; /* 混合版本語法: IE 10 */ 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'; //先創(chuàng)建一個(gè)空實(shí)例 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) { //構(gòu)造器 /子類 let MyLoading = Vue.extend(Loading); instance = new MyLoading({ //創(chuàng)建一個(gè)div,并掛載上去 el: document.createElement('div'), }); document.body.appendChild(instance.$el); } //自定義一些方法,操作loading的顯示與隱藏關(guān) 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方法已被占用'); } }, };
3.在main.js中掛載到全局Vue的原型上
import $loading from '@/components/loading/loading.js'; Vue.use($loading);
- 在request.js接口請求和響應(yīng)攔截時(shí)做處理
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, // 跨域請求時(shí)是否需要使用憑證 withCredentials: false, // 請求 1000s 超時(shí) timeout: 1000 * 60 * 60, }); let loadingSum = 0; let isRefreshing = false; // 標(biāo)記是否正在刷新 token, 防止多次刷新token let requests = []; // 存儲待重發(fā)請求的數(shù)組(同時(shí)發(fā)起多個(gè)請求的處理) // 請求攔截器 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: '服務(wù)異常!', type: 'error', showClose: true, duration: 0, }); return Promise.resolve(error); }, ); // 響應(yīng)攔截器 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') { //這部分屬于強(qiáng)制登錄的邏輯狀態(tài)處理 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 刷新后將數(shù)組的方法重新執(zhí)行 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 { // 返回未執(zhí)行 resolve 的 Promise return new Promise((resolve) => { // 用函數(shù)形式將 resolve 存入,等待刷新后再執(zhí)行 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); }), ); }); } }, };
總結(jié)
axios攔截應(yīng)用loading的時(shí)機(jī):
1.請求攔截時(shí)統(tǒng)計(jì)所有接口請求的次數(shù),逐次累計(jì);接口可能一次調(diào)很多個(gè),但是僅首次調(diào)用時(shí)出現(xiàn)loading,后面再有接口調(diào)用時(shí),就不再出現(xiàn)。
2.響應(yīng)攔截時(shí)統(tǒng)一也會統(tǒng)計(jì)所有接口請求次數(shù),逐次累減;直到最終接口不再調(diào)用時(shí),停止loading效果。
3.單純響應(yīng)攔截過程中存在累計(jì)和累減;801登錄態(tài)強(qiáng)制更新時(shí)也同樣存在累計(jì)和累減。
以上就是JS實(shí)用技巧實(shí)現(xiàn)loading加載示例詳解的詳細(xì)內(nèi)容,更多關(guān)于JS loading加載技巧的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
本地存儲localStorage設(shè)置過期時(shí)間示例詳解
這篇文章主要為大家介紹了本地存儲localStorage設(shè)置過期時(shí)間示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01Vue.js React與Angular流行前端框架優(yōu)勢對比
這篇文章主要為大家介紹了Vue.js React與Angular流行前端框架優(yōu)勢對比,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03js默認(rèn)文本框粘貼事件完美實(shí)現(xiàn)詳解
這篇文章主要為大家介紹了js默認(rèn)文本框粘貼事件完美實(shí)現(xiàn)詳解,2023-01-01微信小程序 input表單與redio及下拉列表的使用實(shí)例
這篇文章主要介紹了微信小程序 input表單與redio及下拉列表的使用實(shí)例的相關(guān)資料,希望通過本文能幫助到大家,需要的朋友可以參考下2017-09-09JS常用正則表達(dá)式超全集(密碼強(qiáng)度校驗(yàn),金額校驗(yàn),IE版本,IPv4,IPv6校驗(yàn))
網(wǎng)上有很多關(guān)于JS常用正則表達(dá)式的文章很全但今天為大家分享一些最新,且非常有用的正則表達(dá)式其中有密碼強(qiáng)度校驗(yàn),金額校驗(yàn),IE版本,IPv4,IPv6校驗(yàn)等2020-02-02