16個(gè)工程必備的JavaScript代碼片段
作者:_紅領(lǐng)巾
https://juejin.cn/post/7000919400249294862

1. 下載一個(gè)excel文檔
同時(shí)適用于word,ppt等瀏覽器不會(huì)默認(rèn)執(zhí)行預(yù)覽的文檔,也可以用于下載后端接口返回的流數(shù)據(jù),見(jiàn)3
//下載一個(gè)鏈接?
function?download(link,?name)?{
????if(!name){
????????????name=link.slice(link.lastIndexOf('/')?+?1)
????}
????let?eleLink?=?document.createElement('a')
????eleLink.download?=?name
????eleLink.style.display?=?'none'
????eleLink.href?=?link
????document.body.appendChild(eleLink)
????eleLink.click()
????document.body.removeChild(eleLink)
}
//下載excel
download('http://111.229.14.189/file/1.xlsx')
復(fù)制代碼
2. 在瀏覽器中自定義下載一些內(nèi)容
場(chǎng)景:我想下載一些DOM內(nèi)容,我想下載一個(gè)JSON文件
/**
?*?瀏覽器下載靜態(tài)文件
?*?@param?{String}?name?文件名
?*?@param?{String}?content?文件內(nèi)容
?*/
function?downloadFile(name,?content)?{
????if?(typeof?name?==?'undefined')?{
????????throw?new?Error('The?first?parameter?name?is?a?must')
????}
????if?(typeof?content?==?'undefined')?{
????????throw?new?Error('The?second?parameter?content?is?a?must')
????}
????if?(!(content?instanceof?Blob))?{
????????content?=?new?Blob([content])
????}
????const?link?=?URL.createObjectURL(content)
????download(link,?name)
}
//下載一個(gè)鏈接
function?download(link,?name)?{
????if?(!name)?{//如果沒(méi)有提供名字,從給的Link中截取最后一坨
????????name?=??link.slice(link.lastIndexOf('/')?+?1)
????}
????let?eleLink?=?document.createElement('a')
????eleLink.download?=?name
????eleLink.style.display?=?'none'
????eleLink.href?=?link
????document.body.appendChild(eleLink)
????eleLink.click()
????document.body.removeChild(eleLink)
}
復(fù)制代碼
使用方式:
downloadFile('1.txt','lalalallalalla')
downloadFile('1.json',JSON.stringify({name:'hahahha'}))
復(fù)制代碼
3. 下載后端返回的流
數(shù)據(jù)是后端以接口的形式返回的,調(diào)用1中的download方法進(jìn)行下載
?download('http://111.229.14.189/gk-api/util/download?file=1.jpg')
?download('http://111.229.14.189/gk-api/util/download?file=1.mp4')
復(fù)制代碼
4. 提供一個(gè)圖片鏈接,點(diǎn)擊下載
圖片、pdf等文件,瀏覽器會(huì)默認(rèn)執(zhí)行預(yù)覽,不能調(diào)用download方法進(jìn)行下載,需要先把圖片、pdf等文件轉(zhuǎn)成blob,再調(diào)用download方法進(jìn)行下載,轉(zhuǎn)換的方式是使用axios請(qǐng)求對(duì)應(yīng)的鏈接
//可以用來(lái)下載瀏覽器會(huì)默認(rèn)預(yù)覽的文件類型,例如mp4,jpg等
import?axios?from?'axios'
//提供一個(gè)link,完成文件下載,link可以是??http://xxx.com/xxx.xls
function?downloadByLink(link,fileName){
????axios.request({
????????url:?link,
????????responseType:?'blob'?//關(guān)鍵代碼,讓axios把響應(yīng)改成blob
????}).then(res?=>?{
?const?link=URL.createObjectURL(res.data)
????????download(link,?fileName)
????})
}
復(fù)制代碼
注意:會(huì)有同源策略的限制,需要配置轉(zhuǎn)發(fā)
6 防抖
在一定時(shí)間間隔內(nèi),多次調(diào)用一個(gè)方法,只會(huì)執(zhí)行一次.
這個(gè)方法的實(shí)現(xiàn)是從Lodash庫(kù)中copy的
/**
?*
?*?@param?{*}?func?要進(jìn)行debouce的函數(shù)
?*?@param?{*}?wait?等待時(shí)間,默認(rèn)500ms
?*?@param?{*}?immediate?是否立即執(zhí)行
?*/
export?function?debounce(func,?wait=500,?immediate=false)?{
????var?timeout
????return?function()?{
????????var?context?=?this
????????var?args?=?arguments
????????if?(timeout)?clearTimeout(timeout)
????????if?(immediate)?{
????????????//?如果已經(jīng)執(zhí)行過(guò),不再執(zhí)行
????????????var?callNow?=?!timeout
????????????timeout?=?setTimeout(function()?{
????????????????timeout?=?null
????????????},?wait)
????????????if?(callNow)?func.apply(context,?args)
????????}?else?{
????????????timeout?=?setTimeout(function()?{
????????????????func.apply(context,?args)
????????????},?wait)
????????}
????}
}
復(fù)制代碼
使用方式:
<html?lang="en">
????<head>
????????<meta?charset="UTF-8"?/>
????????<meta?http-equiv="X-UA-Compatible"?content="IE=edge"?/>
????????<meta?name="viewport"?content="width=device-width,?initial-scale=1.0"?/>
????????<title>Documenttitle>
????head>
????<body>
????????<input?id="input"?/>
????????<script>
????????????function?onInput()?{
????????????????console.log('1111')
????????????}
????????????const?debounceOnInput?=?debounce(onInput)
????????????document
????????????????.getElementById('input')
????????????????.addEventListener('input',?debounceOnInput)?//在Input中輸入,多次調(diào)用只會(huì)在調(diào)用結(jié)束之后,等待500ms觸發(fā)一次???
????????script>
????body>
html>
復(fù)制代碼
如果第三個(gè)參數(shù)immediate傳true,則會(huì)立即執(zhí)行一次調(diào)用,后續(xù)的調(diào)用不會(huì)在執(zhí)行,可以自己在代碼中試一下
7 節(jié)流
多次調(diào)用方法,按照一定的時(shí)間間隔執(zhí)行
這個(gè)方法的實(shí)現(xiàn)也是從Lodash庫(kù)中copy的
/**
?*?節(jié)流,多次觸發(fā),間隔時(shí)間段執(zhí)行
?*?@param?{Function}?func
?*?@param?{Int}?wait
?*?@param?{Object}?options
?*/
export?function?throttle(func,?wait=500,?options)?{
????//container.onmousemove?=?throttle(getUserAction,?1000);
????var?timeout,?context,?args
????var?previous?=?0
????if?(!options)?options?=?{leading:false,trailing:true}
????var?later?=?function()?{
????????previous?=?options.leading?===?false???0?:?new?Date().getTime()
????????timeout?=?null
????????func.apply(context,?args)
????????if?(!timeout)?context?=?args?=?null
????}
????var?throttled?=?function()?{
????????var?now?=?new?Date().getTime()
????????if?(!previous?&&?options.leading?===?false)?previous?=?now
????????var?remaining?=?wait?-?(now?-?previous)
????????context?=?this
????????args?=?arguments
????????if?(remaining?<=?0?||?remaining?>?wait)?{
????????????if?(timeout)?{
????????????????clearTimeout(timeout)
????????????????timeout?=?null
????????????}
????????????previous?=?now
????????????func.apply(context,?args)
????????????if?(!timeout)?context?=?args?=?null
????????}?else?if?(!timeout?&&?options.trailing?!==?false)?{
????????????timeout?=?setTimeout(later,?remaining)
????????}
????}
????return?throttled
}
復(fù)制代碼
第三個(gè)參數(shù)還有點(diǎn)復(fù)雜,options
leading,函數(shù)在每個(gè)等待時(shí)延的開(kāi)始被調(diào)用,默認(rèn)值為false trailing,函數(shù)在每個(gè)等待時(shí)延的結(jié)束被調(diào)用,默認(rèn)值是true
可以根據(jù)不同的值來(lái)設(shè)置不同的效果:
leading-false,trailing-true:默認(rèn)情況,即在延時(shí)結(jié)束后才會(huì)調(diào)用函數(shù) leading-true,trailing-true:在延時(shí)開(kāi)始時(shí)就調(diào)用,延時(shí)結(jié)束后也會(huì)調(diào)用 leading-true, trailing-false:只在延時(shí)開(kāi)始時(shí)調(diào)用
例子:
<html?lang="en">
????<head>
????????<meta?charset="UTF-8"?/>
????????<meta?http-equiv="X-UA-Compatible"?content="IE=edge"?/>
????????<meta?name="viewport"?content="width=device-width,?initial-scale=1.0"?/>
????????<title>Documenttitle>
????head>
????<body>
????????<input?id="input"?/>
????????<script>
????????????function?onInput()?{
????????????????console.log('1111')
????????????}
????????????const?throttleOnInput?=?throttle(onInput)
????????????document
????????????????.getElementById('input')
????????????????.addEventListener('input',?throttleOnInput)?//在Input中輸入,每隔500ms執(zhí)行一次代碼
????????script>?
????body>
html>
復(fù)制代碼
8. cleanObject
去除對(duì)象中value為空(null,undefined,'')的屬性,舉個(gè)栗子:
let?res=cleanObject({
????name:'',
????pageSize:10,
????page:1
})
console.log("res",?res)?//輸入{page:1,pageSize:10}???name為空字符串,屬性刪掉
復(fù)制代碼
使用場(chǎng)景是:后端列表查詢接口,某個(gè)字段前端不傳,后端就不根據(jù)那個(gè)字段篩選,例如name不傳的話,就只根據(jù)page和pageSize篩選,但是前端查詢參數(shù)的時(shí)候(vue或者react)中,往往會(huì)這樣定義
export?default{
????data(){
????????return?{
????????????query:{
????????????????name:'',
????????????????pageSize:10,
????????????????page:1
????????????}
????????}
????}
}
const?[query,setQuery]=useState({name:'',page:1,pageSize:10})
復(fù)制代碼
給后端發(fā)送數(shù)據(jù)的時(shí)候,要判斷某個(gè)屬性是不是空字符串,然后給后端拼參數(shù),這塊邏輯抽離出來(lái)就是cleanObject,代碼實(shí)現(xiàn)如下
export?const?isFalsy?=?(value)?=>?(value?===?0???false?:?!value);
export?const?isVoid?=?(value)?=>
??value?===?undefined?||?value?===?null?||?value?===?"";
export?const?cleanObject?=?(object)?=>?{
??//?Object.assign({},?object)
??if?(!object)?{
????return?{};
??}
??const?result?=?{?...object?};
??Object.keys(result).forEach((key)?=>?{
????const?value?=?result[key];
????if?(isVoid(value))?{
??????delete?result[key];
????}
??});
??return?result;
};
復(fù)制代碼
let?res=cleanObject({
????name:'',
????pageSize:10,
????page:1
})
console.log("res",?res)?//輸入{page:1,pageSize:10}
復(fù)制代碼
剩下的8個(gè)在這里:
8個(gè)工程必備的JavaScript代碼片段[2]
以上代碼片段都經(jīng)過(guò)項(xiàng)目檢測(cè),可以放心使用在項(xiàng)目中。
往期干貨:
?26個(gè)經(jīng)典微信小程序+35套微信小程序源碼+微信小程序合集源碼下載(免費(fèi))
?干貨~~~2021最新前端學(xué)習(xí)視頻~~速度領(lǐng)取
?前端書籍-前端290本高清pdf電子書打包下載
點(diǎn)贊和在看就是最大的支持??
