JavaScript函數(shù)中的防抖與節(jié)流原生實(shí)現(xiàn)及第三方庫(kù)的使用
前言
在開發(fā)中,我們經(jīng)常會(huì)遇到需要頻繁觸發(fā)某個(gè)函數(shù)的情況,比如:
- 監(jiān)聽滾動(dòng)條的變化,當(dāng)滾動(dòng)條的位置發(fā)生變化時(shí),需要執(zhí)行某個(gè)函數(shù)
- 監(jiān)聽鼠標(biāo)的移動(dòng),當(dāng)鼠標(biāo)的位置發(fā)生變化時(shí),需要執(zhí)行某個(gè)函數(shù)
- 監(jiān)聽鍵盤的按鍵,當(dāng)鍵盤的某個(gè)按鍵被按下時(shí),需要執(zhí)行某個(gè)函數(shù)
當(dāng)用戶頻繁的與UI
界面操作交互時(shí),例如:窗口調(diào)整
(觸發(fā)resize),頁(yè)面滾動(dòng)
,上拉加載
(觸發(fā)scroll),表單的按鈕提交,商城搶購(gòu)瘋狂的點(diǎn)擊(觸發(fā)mousedown
),而實(shí)時(shí)的搜索(keyup
,input
),拖拽等
當(dāng)你頻繁的觸發(fā)用戶界面時(shí),會(huì)不停的觸發(fā)事件處理函數(shù),換而言之,當(dāng)出現(xiàn)連續(xù)點(diǎn)擊,上拉加載,實(shí)時(shí)搜索,對(duì)DOM元素頻繁操作,請(qǐng)求資源加載等耗性能的操作,可能導(dǎo)致界面卡頓,瀏覽器奔潰,頁(yè)面空白等情況
而解決這一問(wèn)題的,正是函數(shù)節(jié)流與函數(shù)防抖
函數(shù)節(jié)流
定義: 節(jié)約(減少)觸發(fā)事件處理函數(shù)的頻率,連續(xù)每隔一定的時(shí)間觸發(fā)執(zhí)行的函數(shù),它是優(yōu)化高頻率執(zhí)行一段js代碼的一種手段 特點(diǎn): 不管事件觸發(fā)有多頻繁,都會(huì)保證在規(guī)定的間隔時(shí)間內(nèi)真正的執(zhí)行一次事件處理函數(shù),只會(huì)讓一個(gè)函數(shù)在某個(gè)時(shí)間窗口內(nèi)執(zhí)行一次,若在時(shí)間窗口內(nèi)再次觸發(fā),則重新計(jì)算時(shí)間
應(yīng)用場(chǎng)景: 常用于鼠標(biāo)連續(xù)多次點(diǎn)擊click
事件,鼠標(biāo)移動(dòng)mousemove
,拖拽
,窗口尺寸改動(dòng)
(resize),鼠標(biāo)滾輪頁(yè)面上拉
(onScroll),上拉刷新懶加載
原理: 通過(guò)判斷是否達(dá)到一定的時(shí)間來(lái)觸發(fā)函數(shù),若沒(méi)有規(guī)定時(shí)間則使用計(jì)時(shí)器進(jìn)行延遲,而下一次事件則會(huì)重新設(shè)定計(jì)時(shí)器,它是間隔時(shí)間執(zhí)行
通常與用戶界面高頻的操作有:
- 鼠標(biāo)滾輪頁(yè)面上拉(onScroll),下拉刷新懶加載
- 窗口尺寸改動(dòng)(onresize)
- 拖拽
若是高頻操作,若不進(jìn)行一定的處理,必然會(huì)造成多次數(shù)據(jù)的請(qǐng)求,服務(wù)器的壓力,這樣代碼的性能是非常低效的,影響性能,降低這種頻繁操作的一個(gè)重要的手段,就是降低頻率,通過(guò)節(jié)流控制,也就是讓核心功能代碼在一定的時(shí)間,隔多長(zhǎng)時(shí)間內(nèi)執(zhí)行一次
節(jié)流就是保證一段時(shí)間內(nèi)只執(zhí)行一次核心代碼
你可以聯(lián)想生活中節(jié)約用水(三峽大壩設(shè)置很多水閘)的例子:
高頻事件就像是一個(gè)大開的水龍頭,水流源源不斷的大量流出,就像代碼在不斷的執(zhí)行,若不加以控制,就會(huì)造成資源的一種浪費(fèi) 對(duì)應(yīng)頁(yè)面中的,若是表單中連續(xù)點(diǎn)擊提交按鈕,監(jiān)聽滾動(dòng)事件,連續(xù)下拉加載等請(qǐng)求服務(wù)器的資源
要節(jié)流,擰緊水龍頭,要它的流水頻率降低,每隔一段時(shí)間滴一滴水的,從而節(jié)省資源
在代碼中的體現(xiàn)就是:設(shè)置一定時(shí)器,讓核心功能代碼,隔間段的去執(zhí)行
下面是一個(gè)鼠標(biāo)滾輪,節(jié)流操作實(shí)現(xiàn):類似連續(xù)操作的,都是如此,連續(xù)點(diǎn)擊按鈕,上拉加載
節(jié)流方式一:時(shí)間戳+定時(shí)器
/* throttle1函數(shù),節(jié)流實(shí)現(xiàn)方式1:時(shí)間戳+定時(shí)器 * @params method,duration 第一個(gè)參數(shù)為事件觸發(fā)時(shí)的真正要執(zhí)行的函數(shù) * 第二個(gè)參數(shù)duration表示為定義的間隔時(shí)間 * * 原理:通過(guò)判斷是否達(dá)到一定的時(shí)間來(lái)觸發(fā)函數(shù),若沒(méi)有規(guī)定時(shí)間則使用計(jì)時(shí)器進(jìn)行延遲,而下一次事件則會(huì)重新設(shè)定計(jì)時(shí)器,它是間隔時(shí)間執(zhí)行,不管事件觸發(fā)有多頻繁,都會(huì)保證在規(guī)定內(nèi)的事件一定會(huì)執(zhí)行一次真正事件處理函數(shù) * * */ function throttle1(method, duration) { var timer = null; var prevTime = new Date(); // 之前的時(shí)間 return function() { var that = this, currentTime = new Date(), // 獲取系統(tǒng)當(dāng)前時(shí)間 resTime = currentTime - prevTime; // 時(shí)間戳 // 打印本次當(dāng)前的世間和上次世間間隔的時(shí)間差 console.log("時(shí)間差", resTime); // 當(dāng)前距離上次執(zhí)行時(shí)間小于設(shè)置的時(shí)間間隔 if(resTime < duration) { // 清除上次的定時(shí)器,取消上次調(diào)用的隊(duì)列任務(wù),重新設(shè)置定時(shí)器。這樣就可以保證500毫秒秒內(nèi)函數(shù)只會(huì)被觸發(fā)一次,達(dá)到了函數(shù)節(jié)流的目的 clearTimeout(timer); timer = setTimeout(function(){ prevTime = currentTime; method.apply(that); }, duration) }else { // 當(dāng)前距離上次執(zhí)行的時(shí)間大于等于設(shè)置的時(shí)間時(shí),直接執(zhí)行函數(shù) // 記錄執(zhí)行方法的時(shí)間 prevTime = currentTime; method.apply(that); } } } // 事件觸發(fā)的方法(函數(shù)),函數(shù)節(jié)流1 function handleJieLiu1(){ console.log("節(jié)流方式1"); } var handleJieLiu1 = throttle1(handleJieLiu1, 500); document.addEventListener('mousewheel', handleJieLiu1);
節(jié)流方式二:重置一個(gè)開關(guān)變量+定時(shí)器:
/* * throttle2函數(shù)節(jié)流實(shí)現(xiàn)方式2:重置一個(gè)開關(guān)變量+定時(shí)器 * @params method,duration形參數(shù)與上面的含義一致 * @return 返回的是一個(gè)事件處理函數(shù) * * 在throttle2執(zhí)行時(shí)定義了runFlag的初始值,通過(guò)閉包返回一個(gè)匿名函數(shù)作為事件處理函數(shù), * * 在返回的函數(shù)內(nèi)部判斷runFlag的狀態(tài)并確定執(zhí)行真正的函數(shù)method還是跳出, 每次執(zhí)行method后會(huì)更改runFlag的狀態(tài),通過(guò)定時(shí)器在durtion該規(guī)定的間隔時(shí)間內(nèi)重置runFlag鎖的狀態(tài) * */ function throttle2(method, duration){ // 當(dāng)前時(shí)間間隔內(nèi)是否有方法執(zhí)行,設(shè)置一個(gè)開關(guān)標(biāo)識(shí) var runFlag = false; // 返回一個(gè)事件處理函數(shù) return function(e) { // 判斷當(dāng)前是否有方法執(zhí)行,有則什么都不做,若為true,則跳出 if(runFlag){ return false; } // 開始執(zhí)行 runFlag = true; // 添加定時(shí)器,在到達(dá)時(shí)間間隔時(shí)重置鎖的狀態(tài) setTimeout(function(){ method(e); // 執(zhí)行完畢后,聲明當(dāng)前沒(méi)有正在執(zhí)行的方法,方便下一個(gè)時(shí)間調(diào)用 runFlag = false; }, duration) } } // 事件觸發(fā)的方法(函數(shù)),函數(shù)節(jié)流2 function handleJieLiu2(){ console.log("節(jié)流方式2"); } var handleJieLiu2 = throttle2(handleJieLiu2, 500); document.addEventListener('mousewheel', handleJieLiu2);
上面兩種實(shí)現(xiàn)函數(shù)節(jié)流的方式都可以達(dá)到防止用戶頻繁操作而引起重復(fù)請(qǐng)求資源的
當(dāng)鼠標(biāo)滾輪不斷滾動(dòng)時(shí),事件處理函數(shù)的執(zhí)行順序不一樣
當(dāng)給一個(gè)大范圍的時(shí)間內(nèi),比如:1小時(shí)內(nèi),每幾分鐘執(zhí)行一次,超過(guò)一小時(shí)不在執(zhí)行,推薦使用第一種函數(shù)節(jié)流的方式
如果僅僅要求間隔一定時(shí)間執(zhí)行一次,推薦使用第二種函數(shù)節(jié)流的方式
函數(shù)防抖
定義:防止抖動(dòng),重復(fù)的觸發(fā),頻繁操作,核心在于,延遲事件處理函數(shù)的執(zhí)行,一定時(shí)間間隔內(nèi)只執(zhí)行最后一次操作,就是當(dāng)函數(shù)被觸發(fā)后,只有在上一次函數(shù)執(zhí)行完,一段時(shí)間后,才會(huì)再次觸發(fā)函數(shù)。 例如:表單多次提交,推薦使用防抖
換句話說(shuō),也就是當(dāng)連續(xù)觸發(fā)事件時(shí)并沒(méi)有執(zhí)行事件處理函數(shù),只有在某一階段連續(xù)觸發(fā)的最后一次才執(zhí)行,它遵循兩個(gè)條件
必須要等待一段時(shí)間
上一次觸發(fā)的時(shí)間間隔要大于設(shè)定值才執(zhí)行
特點(diǎn): 某段時(shí)間內(nèi)只執(zhí)行一次
在生活中,你可以想象公交司機(jī)等人上車后,才出站一樣
應(yīng)用場(chǎng)景: 常應(yīng)用于輸入框事件keydown
,keyup
,搜索聯(lián)想查詢,只有在用戶停止鍵盤輸入時(shí),才發(fā)送Ajax請(qǐng)求
原理: 它是維護(hù)一個(gè)計(jì)時(shí)器,規(guī)定在duration
(延遲)時(shí)間后出過(guò)事事件處理函數(shù),但是在duration
時(shí)間內(nèi)再次觸發(fā)的話,都會(huì)清除當(dāng)前的timer
重新計(jì)時(shí),這樣一來(lái),只有最后一次操作事件處理函數(shù)才被真正的觸發(fā)
具體代碼如下所示:
/* * 函數(shù)防抖 * 例如:假定時(shí)間間隔時(shí)500ms,頻繁不同的操作5s,且每?jī)纱螆?zhí)行時(shí)間小于等于間隔500ms * 那么最后只執(zhí)行了1次,也就是每一次執(zhí)行時(shí)都結(jié)束上一次的執(zhí)行 * @params method,duration,與上面一致 * * 原理:它是維護(hù)一個(gè)計(jì)時(shí)器,規(guī)定在duration時(shí)間后出發(fā)時(shí)間處理函數(shù),但是在duration時(shí)間內(nèi)再次出發(fā)的化,都會(huì)清除當(dāng)前的timer重新計(jì)時(shí),這樣一來(lái),只有最后一次操作事件處理函數(shù)才被真正的觸發(fā) * * 一般用于輸入框事件,常用場(chǎng)景就是表單的搜索或者聯(lián)想查詢,如果不使用防抖會(huì)連續(xù)發(fā)送請(qǐng)求,增加服務(wù)器的壓力,使用防抖后,會(huì)在用戶輸入要查詢的關(guān)鍵詞后才發(fā)送請(qǐng)求,百度搜索就是這么實(shí)現(xiàn)的 * * */ function debounce(method, duration) { var timer = null; return function(){ var that = this, args = arguments; // 在本次調(diào)用之間的一個(gè)間隔時(shí)間內(nèi)若有方法在執(zhí)行,則終止該方法的執(zhí)行 if(timer) { clearTimeout(timer); } // 開始執(zhí)行本次調(diào)用 timer = setTimeout(function(){ method.apply(that,args); }, duration) } } // 事件觸發(fā)的方法(函數(shù)),防抖 function handleFangDou(){ console.log("函數(shù)的防抖",new Date()); } var handleFangDou = debounce(handleFangDou, 500); var oInput = document.querySelector("#input"); // 獲取input元素 oInput.addEventListener('keyup',handleFangDou);
如上輸入框效果所示,每當(dāng)輸入框輸入后,鍵盤彈起時(shí),執(zhí)行事件處理函數(shù),而不應(yīng)該是鍵入內(nèi)容時(shí)都觸發(fā)一次事件處理函數(shù)
同理,搜索引擎,表單聯(lián)想查詢功能時(shí),不是根據(jù)用戶鍵入的字母,數(shù)字,內(nèi)容同時(shí)進(jìn)行Ajax數(shù)據(jù)請(qǐng)求的,如果每鍵入一個(gè)字母都觸發(fā)一次數(shù)據(jù)請(qǐng)求,那就耗性能了的 應(yīng)當(dāng)是用戶停止輸入的時(shí)候才去觸發(fā)查詢請(qǐng)求,這個(gè)時(shí)候就用到函數(shù)防抖了的
表單的多次提交,百度搜索等都是用的防抖實(shí)現(xiàn)的
小結(jié):
共同點(diǎn): 都是解決頻繁操作觸發(fā)事件處理函數(shù),引起頁(yè)面卡頓,不流暢等性能問(wèn)題,都是通過(guò)設(shè)置延時(shí)計(jì)時(shí)器邏輯來(lái)提升性能,以減少http請(qǐng)求次數(shù),節(jié)約請(qǐng)求資源
不同點(diǎn):函數(shù)節(jié)流,間隔時(shí)間內(nèi)執(zhí)行事件處理函數(shù),而函數(shù)防抖,一定時(shí)間間隔內(nèi)只執(zhí)行最后一次操作
直接引入lodash庫(kù)
如果自己不原生手動(dòng)實(shí)現(xiàn),可以直接安裝yarn add lodash
,然后引入
// 函數(shù)接口 npm i -S lodash.throttle; import throttle from 'lodash.throttle'; // 引入lodash.throttle庫(kù) // 事件觸發(fā)的方法(函數(shù)),節(jié)流 function handleThrottle(){ console.log("函數(shù)的節(jié)流",new Date()); } throttle(handleThrottle, 500); // 將觸發(fā)事件處理函數(shù)作為第一個(gè)參數(shù)傳入,第二個(gè)參數(shù)為間隔的時(shí)間,這里是500毫秒
下面是函數(shù)防抖的實(shí)現(xiàn)
在終端下通過(guò)npm
或者cnpm
或yarn
的方式安裝第三方庫(kù)
npm i -S loadsh.debounce 或者 cnpm install -S loadsh.debounce
在組件中使用
import debounce from 'lodash.debounce'; // 函數(shù)防抖 function handleDebounce() { console.log("函數(shù)的防抖", new Date()); } debounce(handleDebounce, 500);
自己原生實(shí)現(xiàn)函數(shù)防抖
// 自己封裝一個(gè)debounce函數(shù)用于防抖 debounce(method, duration) { var timer = null; /*return function(){ var that = this, args = arguments; // 在本次調(diào)用之間的一個(gè)間隔時(shí)間內(nèi)若有方法在執(zhí)行,則終止該方法的執(zhí)行 if(timer) { clearTimeout(timer); } // 開始執(zhí)行本次調(diào)用 timer = setTimeout(function(){ method.apply(that,args); }, duration) }*/ // 上面的return匿名函數(shù)可以用Es6的箭頭函數(shù),以下寫法與上面等價(jià),最簡(jiǎn)潔的寫法,但是沒(méi)有上面的代碼好理解 return (...args) => { clearTimeout(timer); timer = setTimeout(() => method(...args), duration) } }
當(dāng)然對(duì)于上面的代碼,還是可以優(yōu)化一下的,對(duì)于回調(diào)函數(shù),在Es6中,常用于箭頭函數(shù)來(lái)處理,這樣會(huì)省去不少麻煩
例如:this的指向問(wèn)題
如下所示:debouce
函數(shù)最簡(jiǎn)易的封裝
你也可以把上面的定時(shí)器初始值放在debouce函數(shù)作為第三個(gè)形參數(shù)設(shè)置,也是可以的
debounce(method, duration, timer = null) { return (...args) => { clearTimeout(timer); timer = setTimeout(() => { method(...args) }, duration) } }
如果自己封裝throttle
和debounce
函數(shù),可以單獨(dú)封裝到一個(gè)文件對(duì)外暴露就可以了,在需要用它們的地方,通過(guò)import
引入即可,在代碼中直接調(diào)用就可以
在根目錄下(以你自己的為準(zhǔn))創(chuàng)建一個(gè)throttle.js
通過(guò)export default
暴露出去
/* * @authors 川川 (itclancode@163.com) * @ID suibichuanji * @date 2023-10-19 @desc 封裝節(jié)流函數(shù) * @param method,duration:method事件處理函數(shù),duration:間隔的時(shí)間 * @return 匿名函數(shù) * 原理: 通過(guò)判斷是否達(dá)到一定的時(shí)間來(lái)觸發(fā)函數(shù), * 若沒(méi)有規(guī)定時(shí)間則使用計(jì)時(shí)器進(jìn)行延遲,而下一次事件則會(huì)重新設(shè)定計(jì)時(shí)器 * 它是間隔時(shí)間執(zhí)行,不管事件觸發(fā)有多頻繁 * 都會(huì)保證在規(guī)定內(nèi)的事件一定會(huì)執(zhí)行一次真正事件處理函數(shù) * */ function throttle(method, duration) { var timer = null; var prevTime = new Date(); // 之前的時(shí)間 return function() { var that = this, currentTime = new Date(), // 獲取系統(tǒng)當(dāng)前時(shí)間 resTime = currentTime - prevTime; // 時(shí)間戳 // 打印本次當(dāng)前的世間和上次世間間隔的時(shí)間差 console.log("時(shí)間差", resTime); // 當(dāng)前距離上次執(zhí)行時(shí)間小于設(shè)置的時(shí)間間隔 if (resTime < duration) { // 清除上次的定時(shí)器,取消上次調(diào)用的隊(duì)列任務(wù),重新設(shè)置定時(shí)器。這樣就可以保證500毫秒秒內(nèi)函數(shù)只會(huì)被觸發(fā)一次,達(dá)到了函數(shù)節(jié)流的目的 clearTimeout(timer); timer = setTimeout(function() { prevTime = currentTime; method.apply(that); }, duration) } else { // 當(dāng)前距離上次執(zhí)行的時(shí)間大于等于設(shè)置的時(shí)間時(shí),直接執(zhí)行函數(shù) // 記錄執(zhí)行方法的時(shí)間 prevTime = currentTime; method.apply(that); } } } export default throttle;
然后在需要使用函數(shù)節(jié)流文件中引入
import throttle from './throttle'; throttle(事件觸發(fā)處理函數(shù), 1000);
同理,若是自己封裝debounce
函數(shù)的防抖,把它單獨(dú)的抽離出去封裝成一個(gè)函數(shù),通過(guò)export
對(duì)外暴露,供其他地方調(diào)用
/** * * @authors 川川 (itclancode@163.com) * @ID suibichuanji * @date 2023-10-19 * @version $Id$ * @description 函數(shù)防抖 * @param { method, duration} [method是事件處理函數(shù),duration是延遲時(shí)間] * 原理 * 原理:它是維護(hù)一個(gè)計(jì)時(shí)器,規(guī)定在duration時(shí)間后出發(fā)時(shí)間處理函數(shù) * 但是在duration時(shí)間內(nèi)再次出發(fā)的化,都會(huì)清除當(dāng)前的timer重新計(jì)時(shí) * 這樣一來(lái),只有最后一次操作事件處理函數(shù)才被真正的觸發(fā) * * 一般用于輸入框事件,常用場(chǎng)景就是表單的搜索或者聯(lián)想查詢, * 如果不使用防抖會(huì)連續(xù)發(fā)送請(qǐng)求,增加服務(wù)器的壓力 * 使用防抖后,會(huì)在用戶輸入要查詢的關(guān)鍵詞后才發(fā)送請(qǐng)求,百度搜索就是這么實(shí)現(xiàn)的 */ function debounce(method, duration) { var timer = null; return function(){ var that = this, args = arguments; // 在本次調(diào)用之間的一個(gè)間隔時(shí)間內(nèi)若有方法在執(zhí)行,則終止該方法的執(zhí)行 if(timer) { clearTimeout(timer); } // 開始執(zhí)行本次調(diào)用 timer = setTimeout(function(){ method.apply(that,args); }, duration) } } export default debounce;
如何阻止函數(shù)調(diào)用太快(函數(shù)節(jié)流,兩種方式)或者太多次(函數(shù)防抖),分別用原生JS以第三方庫(kù)實(shí)現(xiàn)
對(duì)于函數(shù)的節(jié)流與防抖是前端提升性能的手段,雖然就幾行代碼,但是面試時(shí),常問(wèn)不衰,讓你手寫,很多時(shí)候,拍拍胸脯,不借助搜索,你還真不一定能寫得出來(lái)
在實(shí)際的開發(fā)中,函數(shù)的節(jié)流與函數(shù)防抖也是比較頻繁的,可見它的重要性不言而喻
以上就是JavaScript函數(shù)中的防抖與節(jié)流原生實(shí)現(xiàn)及第三方庫(kù)的使用的詳細(xì)內(nèi)容,更多關(guān)于JavaScript函數(shù)的防抖與節(jié)流的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
javascript通過(guò)獲取html標(biāo)簽屬性class實(shí)現(xiàn)多選項(xiàng)卡的方法
這篇文章主要介紹了javascript通過(guò)獲取html標(biāo)簽屬性class實(shí)現(xiàn)多選項(xiàng)卡的方法,涉及javascript針對(duì)頁(yè)面元素屬性與事件的相關(guān)操作技巧,需要的朋友可以參考下2015-07-07js編寫一個(gè)簡(jiǎn)單的產(chǎn)品放大效果代碼
這篇文章主要為大家分享了js編寫一個(gè)簡(jiǎn)單的產(chǎn)品放大效果代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-06-06原生JS與CSS實(shí)現(xiàn)軟件卸載對(duì)話框功能
今天給大家分享一個(gè)特別有意思的軟件卸載對(duì)話框功能,本段代碼是基于js 與css實(shí)現(xiàn)的,感興趣的朋友跟隨小編一起看看吧2019-12-12thinkjs微信中控之微信鑒權(quán)登陸的實(shí)現(xiàn)代碼
這篇文章主要介紹了thinkjs微信中控之微信鑒權(quán)登陸的實(shí)現(xiàn)代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08JavaScript對(duì)象字面量和構(gòu)造函數(shù)原理與用法詳解
這篇文章主要介紹了JavaScript對(duì)象字面量和構(gòu)造函數(shù),結(jié)合實(shí)例形式分析了JavaScript對(duì)象字面量和構(gòu)造函數(shù)相關(guān)概念、原理、用法及操作注意事項(xiàng),需要的朋友可以參考下2020-04-04JavaScript實(shí)現(xiàn)自動(dòng)切換圖片代碼
本文給大家分享一段js代碼實(shí)現(xiàn)自動(dòng)切換圖片的代碼,代碼非常簡(jiǎn)單,應(yīng)用領(lǐng)域非常廣泛,感興趣的朋友一起看看吧2016-10-10基于javascript實(shí)現(xiàn)的搜索時(shí)自動(dòng)提示功能
這篇文章主要介紹了基于javascript實(shí)現(xiàn)的搜索時(shí)自動(dòng)提示功能,非常實(shí)用,推薦給需要的小伙伴參考下。2014-12-12