如何使用函式來優化效能
DOM.onclick()
事件,我們給一個DOM節點綁定了點選事件,當點選該元素時觸發事件函式的執行,但是當我們頻繁點選該元素時,就會不斷觸發該點選事件,如果該點選事件觸發的事件函式是DOM元素的,就會造成很高的效能消耗,可能會造成頁面的卡頓。
所以此時我們應該限制該事件的觸發頻率,減少頁面的開銷。
2. 原理
連續觸發事件,但是事件函式只在在規定的週期之內只執行一次。
3. 程式碼實現
function throttle(fn, wait = 500) { let lastTime = 0 // 初始化上一次呼叫的事件 return function () { let args = [].slice.call(arguments) // 將類陣列轉化為陣列 let nowTime = new Date().getTime() // 獲取當前時間 if(nowTime - lastTime > wait) { fn.apply(this, args) lastTime = nowTime // 把上一次呼叫時間重新賦值 } } } // 使用 let btn = document.getElementById('btn') let fn = function () { console.log(1) } btn.onclick = throttle(fn, 1000) 複製程式碼
在給按鈕加上點選事件後,即使一直不停的點選按鈕,也只會每隔1000ms
執行一次事件處理函式。
二、防抖函式
1.使用場景
例如我們在百度搜索的輸入框輸入我們想要搜尋的內容,在我們停止輸入後一小段時間(delay
)後就會得你輸入框得內容然後進行搜尋,如果你在輸入後暫停的時間小於規定的時間(delay
),就會重新計算該時間。
2.原理
所謂防抖,就是指觸發事件後在 n 秒內函式只能執行一次,如果在 n 秒內又觸發了事件,則會重新計算函式執行時間。
3. 程式碼實現
function debounce(fn, delay) { let timer = null return function () { let _self = this let args = [].slice.call(arguments) clearTimout(timer) timer = setTimout(function () { fn.apply(_self, args) }, delay) } } // 使用 let inp = document.getElementById('inp') function handler() { console.log(this.value) } inp.oninput = debounce(handler, 500) 複製程式碼
在使用節流函式後,我們在暫停輸入的500ms
後就會輸入輸入框內的值,暫停時間小於500ms
,則不會輸出,將重新計算函式執行時間。
三、分時函式
比如我們在將一個很大的資料渲染成列表的時候,我們要求必須將所有資料渲染完成,不能使用懶載入,所以這樣當我們在短時間內往頁面新增大量的DOM
節點的時候,顯然會造成瀏覽器的卡頓。
let arr = [] for(let a = 0; a < 1000; a++) { arr.push(a) } function render(data) { for(let i = 0; i < arr.length; i++) { let div = document.createElement('div') div.innerHTML = arr[i] document.body.appenChild(div) } } render(arr) 複製程式碼
所以我們我們建立一個函式,然節點的新增分時進行,比如把在1s
新增1000個節點改為每隔200ms
新增20個節點。
let timeChunk = function (data, fn, count = 20, delay = 200) { let obj,timer let start = function () { for(let i = 0; i < Math.min(count, data.length); i++) { let obj = data.shift() fn(obj) } } return function () { timer = setInterval(function () { if(data.length === 0) { return clearInterval(timer) } start() }, delay) } } 複製程式碼
使用分時函式
let arr = [] for (let a = 0; a < 1000; a++) { arr.push(a) } function render(data) { let div = document.createElement('div') div.innerText = data document.body.appendChild(div) } let renderlist = timeChunk(arr, render, 20, 200) renderlist() 複製程式碼
這樣在呼叫分時函式後每隔200ms
建立20個節點。
四、惰性函式
在前端開發中,因為瀏覽器的差異,一些嗅探工作是不可避免的,比如要實現一個在各個瀏覽器中都通用的新增事件函式。常見寫法:
let addEvent = function (element, type, handler) { if(window.addEventListener) { return element.addEventLisenter(type, handler, false) } else if (window.attachEvent) { return element.attachEvent('on'+type, handler) } } 複製程式碼
但是我們每次執行函式的時候都要進行分支判斷,然後當我們在確定了在哪一種瀏覽器中執行該函式的時候,我們只需要在第一次判斷,後面的使用都不用判斷,因為我們是在同一個瀏覽器執行該函式。
所以我們可以使用惰性載入函式,在函式體內往往都會有一些分支判斷,但是在第一次進入分支條件後,在函式內部會重寫這個函式,重寫之後就是我們所期望的函式,在下一次再進入函式的時候不用在進行分支判斷。
let addEvent = function (element, type, handler) { if(window.addEventListener) { addEvemt = function(element, type, handler) { element.addEventLisenter(type, handler, false) } } else if (window.attachEvent) { addEvent = function(element, type, handler) { element.attachEvent('on'+type, handler) } } addEvent(element, type, handler) } 複製程式碼