Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
開發過程中,你可能會經常用到控制臺命令console.log(),但是,其實除了這個命令外,還有一些其他的命令和技巧可供我們使用,讓我們看看它們究竟是什么,會不會為你的調試能力帶來一點新的啟發。
同樣作為開發者,有一點不可否認的是程序員這個群體總是會不斷優化工作流程,使其變得更高效。不過這很容易使我們陷入誤區,讓我們很難突破已經慣有的工作流程,繼而閉耳塞聽得認為沒有比現在更好的工作方法和流程。
一般Web開發者的工作流程是在IDE中寫好代碼并保存,然后到瀏覽器中刷新測試。同時使用瀏覽器的DevTools調整CSS,還可以測試產品在不同分辨率和移動設備上的表現。在需要深入研究的地方可以通過添加 console.log()語句來調試我們的腳本。
如果console.log()在最終產品中被濫用,那么你在網上沖浪時如果一直打開DevTools,你就會在控制臺中看到很多本不該出現在最終產品中的調試信息。
下面讓我為大家介紹一下除了console.log()之外的其他命令,看看它們會不會為各位的工作帶來什么新的啟發吧!
我們可能已經習慣了通過 console.log("參數") 來了解程序中正在發生的事情,一般來說對于字符或數字這種類型的輸出,這種用法就足夠了,不過在輸出些類似像對象、數組類型的數據時卻沒有那么順手。
第一個技巧是在變量上加上大括號,這樣不僅可以打印出它們的值,還可以打印出變量的名稱,這使我們在日志中更方便的定位到什么值來自哪里。
let x = 2;
console.log(x) // 2
console.log({x}) // {x: 2}
格式化日志
你可以在console.log中使用以百分號操作符指代不同格式的記錄值來格式化字符串,以下是操作符類型的定義:
你可以把它們分別放在控制臺試試效果,首先是字符串和整數的示例:
console.log('%ix %s developer', 10, 'console');
// 10x console developer
如果計劃將數字格式化為整型,可以使用如下示例:
console.log('%i', 12.34455241234324234);
// 12
%c操作符可以令你使用CSS樣式定制輸出日志的樣式
console.log('%cPay attention to me','color:firebrick;font-size:40px')
分組日志
你可以使用console.group()來對日志進行分組,以將其顯示為可擴展和可折疊的組。
const label = 'The Millenium Falcon Crew';
console.group(label);
console.log('Leia');
console.log('Han');
console.log('Chewie');
console.log('Ben');
console.groupEnd(label);
你可以嵌套分組,并可以使用 console.groupCollapsed() 在默認情況下不展開它們:
const extendedlabel = 'The Millenium Falcon Crew extended';
const meat = 'Humanoids';
const metal = 'Droids';
console.group(extendedlabel);
console.groupCollapsed(meat);
console.log('Leia');
console.log('Han');
console.log('Chewie');
console.log('Ben');
console.groupEnd(meat);
console.group(metal);
console.log('R2D2');
console.log('C3PO');
console.groupEnd(metal);
console.groupEnd(extendedlabel);
日志控制臺過濾
除了console.log外,你也可以使用 console.info()、console.error()和 console.warning()來代替它。通過這些語句,你可以在控制臺側邊欄或下拉列表中來過濾你在控制臺中看到的消息。這樣一來,你可以更容易地在來自第三方腳本和項目中的其他腳本中找到自己的日志消息。
其他控制臺命令
你可能在debug時曾創建過統計某個方法被調用或被執行次數的變量。這里推薦另一種方法, console.count()和 console.countReset(),通過它們你可以創建任意數量的變量,并通過標簽來區分。
console.count('Chocula'); // Chocula: 1
console.count(); // default: 1
console.count('Chocula'); // Chocula: 2
console.countReset('Chocula');
console.count(); // default: 2
console.count(); // default: 3
console.count('Chocula'); // Chocula: 1
您還可以使用console.time()方法去統計代碼執行的總耗時:
console.time('go');
for(let i = 0; i < 200000; i+=1) {
let x = Math.random()*2000;
}
console.timeEnd('go'); // go: 11.7861328125 ms
使用 console.dir()不僅可以顯示內容,還可以顯示你發送的數據類型。例如,如果你想要一個節點的XML表示,你可以使用console.dirxml()。而console.table()對于顯示JSON數據作為一個可排序的表格顯示效果也很好。
使用 console.log() 來監測那些變化范圍很大的數值時,不僅低效且困難。你可在在開發人員工具中通過點擊“眼睛“圖標來激活Live Expression功能。它可以將你想要關注的數值pin在工具頂端。
例如,你可以先輸入document.activeElement 來試試。該表達式表示當前獲得焦點的元素。
在這有一點需要說明,因為Live Expression并不和某一個站點及域名所關聯,所以它會一直保留在你的DevTools中。因此建議在完成一項調試后及時刪除它們,以免為調試其他站點時帶來不必要的麻煩。
使用控制臺處理當前文檔
開發人員工具中的控制臺不僅僅是用于顯示日志的一種方式。它是一個REPL,可讓您編寫和執行JavaScript并使用自動完成功能了解當前文檔的可用方法和屬性。
你可以試試,在開發人員工具的控制臺,輸入doc并按下tab,它會自動將其轉為document。如果輸入’.’ 你會看到所有document可用的方法和屬性。這是一種學習可用方法和屬性的有趣且簡單的方法之一,這樣可以使你在短時間內寫出大量代碼。
除此之外,控制臺和當前文檔進行交互還有很多快捷方式可供你使用 “控制臺實用程序”。其中一些是:
其中有些方法的功能很強大,但可能我們在并不清楚的前提下自己實現了一系列 console.log() 語句。
例如如下使用場景:
monitorEvents(window, ['resize', 'scroll']);
monitorEvents($0, 'key');
每次窗口滾動或調整大小時都會記錄一條日志。第二個示例比較有意思,因為它記錄了當前選定元素上的任何按鍵行為。
以下代碼列出頁面中的所有a標簽(因為$$('a')是document.querySelectorAll('a')的簡稱),并以可排序的表格形式顯示。作為table方法的第二個參數的數組定義了表格的列。否則,鏈接的每個屬性都會變成一列,那就很難瀏覽了。這個表不僅是可排序的,而且你還可以復制和粘貼它--例如,復制到Excel中。
console.table($$('a'),['href','text'])
與其使用復雜的JavaScript來過濾這些結果,你不如試試CSS選擇器。再比如,你想獲得一個文檔中所有非內嵌圖片的src和alt信息的表格,你可以使用以下方法:
console.table($$('img:not([src^=data])'), ['src','alt'])
另外,當您使用Markdown生成HTML時,大多數頁面生成器都會在標題上創建自動ID,例如 # New Stuff標題會變成<h1 id="new-stuff">New stuff</h1>。如果我需要批量創建許多指向這些錨點的URL,但不想手動去做這些事時,可能需要通過控制臺編寫腳本來為我做這件事:
let out = '';
$$('#main [id]').filter(
elm => {return elm.nodeName.startsWith('H')}
).forEach(elm => {
out += `${elm.innerText}
${document.location.href}#${elm.id}
`
});
copy(out);
結果是一個文本塊,每個標題的文本內容后跟指向該標題的完整URL。
這里展示了$$快捷方式的一個有趣的額外功能。document.querySelectorAll('#main [id]').filter() 會導致一個錯誤,因為返回的值不是一個數組而是一個NodeList。你需要用[...document.querySelectoAll('#main [id]').filter()]或Array.from(document.querySelectoAll('#main [id]').filter())方法把它強制轉換成一個Array,這在相當長的一段時間中困擾著從jQuery轉到JavaScript的開發者,而使用$$,可以直接使用所有的Array方法。
一般來說,你可以通過控制臺來改變瀏覽器頁面中的所有元素。而且你還有一個額外的好處,就是可以使用DevTools的元素選項卡來獲得元素所有的頁面路徑。點擊每個元素旁的...菜單,并通過彈出的上下文菜單中選擇你要復制的路徑。
雖然控制臺本身很好用,但很快你就會發現Console在編寫代碼存在著諸多困難,例如,Console是單行環境,不小心點擊Enter后就會立即執行。不過在這最后為大家介紹一個小技巧,你可以使用Shift + Enter來代替編寫多行腳本。
Sources
總的來說,Console是一個很好的測試環境,但對于編輯體驗來說卻很差。不過還好在Sources面板中也有一個完整的編輯器。在那里,你可以檢查當前頁面的代碼,并編寫更復雜的腳本與之交互。
除了點按上面tab菜單之外,DevTools還有一套快捷鍵Command Menu供你使用,你可以通過按control + shift + P(Windows, Linux)或Command+Shift+P(macOS)來訪問它。或選擇(...或?)菜單,選擇“Run command”。
Snippets 代碼片段
Snippets是保存你曾寫過的能明顯提高開發效率的代碼小片段。在DevTools中點擊Command Menu鍵盤快捷鍵,輸入snip并按下Enter鍵,選擇創建一個新的snippet,這樣就會進入Snippets編輯器,具體如下圖所示:
右邊的窗體包括一個完整的源碼編輯器,具有關鍵詞著色、自動補全、多光標等功能。下面我們開始試試上面的示例:
console.clear();
let out = '';
let problems = [];
$$('a').forEach(a => {
let text = a.innerText.trim();
let prefix = '';
if (!text) {
if (a.querySelector('img')){
text = a.querySelector('img').alt;
prefix = 'Image: ';
}
if (a.getAttribute('aria-label')) {
text = a.getAttribute('aria-label');
prefix = 'Aria Label: ';
}
if (a.getAttribute('aria-labelledby')) {
text = $('#' + a.getAttribute('aria-labelledby')).innerText;
prefix = 'Aria Labelled By: ';
}
}
if (text) {
text = prefix + text
} else {
a.style.border = '1px solid firebrick';
problems.push(a);
}
out += `
${text||'No Link text'}
${a.href}`;
});
if (out === '') {
console.warn('Sorry, no links found');
} else {
copy(out);
console.info('done harvesting links, ready to paste');
if (problems.length > 0) {
console.warn('There were %d issues:', problems.length);
console.groupCollapsed('Links without text');
problems.forEach(a => {console.dirxml(a)});
console.groupEnd('Links without text');
}
}
以下是執行演示:
Overrides
Override是通過修改遠程文件的本地副本,實現本地測試替換服務器文件。例如,你可以在本地編輯完整的復雜樣式表,但無需等待冗長的重新build和部署過程即可看到效果,這也是能在開發階段即可發現問題的一種快捷的方式。
你可以通過安裝Microsoft Edge Tools for VS Code擴展 ,即可在編輯中獲得開發人員工具,通過下圖可以看到基礎用法。
希望通過這篇文章,可以使你能更全面的對DevTools有一些了解,而不僅僅只會使用console.log。另外作為一個開發人員除了上述的這些技巧外,還應多多習慣使用斷點及條件斷點進行調試,希望能夠通過更多的使用和練習來達到熟練的狀態。
文同步本人掘金平臺原創翻譯的文章:https://juejin.cn/post/6844903834246971400
你是否遇到過"callbacks"一詞,但是不知道這意味著什么?別著急。你不是一個人。許多JavaScript的新手發現回調也很難理解。
盡管callbacks可能令人疑惑,但是你仍然需要徹底了解它們,因為它們是JavaScript中的一個重要的概念。如果你不知道callbacks,你不可能走得很遠。
這就是今天的文章(要講的)!你將了解callbacks是什么,為什么它們很重要,以及如何使用它們。
備注:你會在這篇文章中看到ES6箭頭函數。如果你不是很熟悉它們,我建議你在往下讀之前復習一下ES6這篇文章(只了解箭頭函數部分就可以了)。
callback是作為稍后要執行的參數傳遞給另一個函數的函數。(開發人員說你在執行函數時“調用”一個函數,這就是被命名為回調函數的原因)。
它們在JavaScript中很常見,你可能自己潛意識的使用了它們而不知道它們被稱為回調函數。
接受函數回調的一個示例是addEventLisnter:
const button = document.querySelector('button')
button.addEventListener('click', function(e) {
// Adds clicked class to button
this.classList.add('clicked')
})
復制代碼
看不出是回調函數嗎?那么,這種寫法怎樣?
const button = document.querySelector('button')
// Function that adds 'clicked' class to the element
function clicked (e) {
this.classList.add('clicked')
}
// Adds click function as a callback to the event listener
button.addEventListener('click', clicked)
復制代碼
在這里,我們告訴JavaScript監聽按鈕上的click事件。如果檢測到點擊,則JavaScript應觸發clicked函數。因此,在這種情況下,clicked是回調函數,而addEventListener是一個接受回調的函數。
現在,你明白什么是回調函數了嘛?:)
我們來看另外一個例子。這一次,假設你希望通過過濾一組數據來獲取小于5的列表。在這里,你將回調函數傳遞給filter函數:
const numbers = [3, 4, 10, 20]
const lesserThanFive = numbers.filter(num => num < 5)
復制代碼
現在,如果你想通過命名函數執行上面的代碼,則過濾函數將如下所示:
const numbers = [3, 4, 10, 20]
const getLessThanFive = num => num < 5
// Passing getLessThanFive function into filter
const lesserThanFive = numbers.filter(getLessThanFive)
復制代碼
在這種情況下,getLessThanFive是回調函數。Array.filter是一個接受回調的函數。
現在明白為什么了吧?一旦你知道回調函數是什么,它們就無處不在!
下面的示例向你展示如何編寫回調函數和接受回調的函數:
// Create a function that accepts another function as an argument
const callbackAcceptingFunction = (fn) => {
// Calls the function with any required arguments
return fn(1, 2, 3)
}
// Callback gets arguments from the above call
const callback = (arg1, arg2, arg3) => {
return arg1 + arg2 + arg3
}
// Passing a callback into a callback accepting function
const result = callbackAcceptingFunction(callback)
console.log(result) // 6
復制代碼
請注意,當你將回調函數傳遞給另一個函數時,你只傳遞該函數的引用(并沒有執行它,因此沒有括號())
const result = callbackAcceptingFunction(callback)
復制代碼
你只能在callbackAcceptingFunction中喚醒(調用)回調函數。執行此操作時,你可以傳遞回調函數可能需要的任意數量的參數:
const callbackAcceptingFunction = (fn) => {
// Calls the callback with three args
fn(1, 2, 3)
}
復制代碼
這些由callbackAcceptingFunction傳遞給回調函數的參數,然后再通過回調函數(執行):
// Callback gets arguments from callbackAcceptingFunction
const callback = (arg1, arg2, arg3) => {
return arg1 + arg2 + arg3
}
復制代碼
這是回調的解剖。現在,你應該知道addEventListener包含一個event參數:)
// Now you know where this event object comes from! :)
button.addEventListener('click', (event) => {
event.preventDefault()
})
復制代碼
唷!這是callbacks的基本思路!只需要記住其關鍵:將一個函數傳遞給另一個函數,然后,你會想起我上面提到的機制。
旁注:這種傳遞函數的能力是一件很重要的事情。它是如此重要,以至于說JavaScript中的函數是高階函數。高階函數在編程范例中稱為函數編程,是一件很重大的事情。
但這是另一天的話題。現在,我確信你已經開始明白callbacks是什么,以及它們是如何被使用的。但是為什么?你為什么需要callbacks呢?
回調函數以兩種不同的方式使用 -- 在同步函數和異步函數中。
如果你的代碼從上到下,從左到右的方式順序執行,等待上一個代碼執行之后,再執行下一行代碼,則你的代碼是同步的。
讓我們看一個示例,以便更容易理解:
const addOne = (n) => n + 1
addOne(1) // 2
addOne(2) // 3
addOne(3) // 4
addOne(4) // 5
復制代碼
在上面的例子中,addOne(1)首先執行。一旦它執行完,addOne(2)開始執行。一旦addOne(2)執行完,addOne(3)執行。這個過程一直持續到最后一行代碼執行完畢。
當你希望將部分代碼與其它代碼輕松交換時,回調將用于同步函數。
所以,回到上面的Array.filter示例中,盡管我們將數組過濾為包含小于5的數組,但你可以輕松地重用Array.filter來獲取大于10的數字數組:
const numbers = [3, 4, 10, 20]
const getLessThanFive = num => num < 5
const getMoreThanTen = num => num > 10
// Passing getLessThanFive function into filter
const lesserThanFive = numbers.filter(getLessThanFive)
// Passing getMoreThanTen function into filter
const moreThanTen = numbers.filter(getMoreThanTen)
復制代碼
這就是為什么你在同步函數中使用回調函數的原因。現在,讓我們繼續看看為什么我們在異步函數中使用回調。
這里的異步意味著,如果JavaScript需要等待某些事情完成,它將在等待時執行給予它的其余任務。
異步函數的一個示例是setTimeout。它接受一個回調函數以便稍后執行:
// Calls the callback after 1 second
setTimeout(callback, 1000)
復制代碼
如果你給JavaScript另外一個任務需要完成,讓我們看看setTimeout是如何工作的:
const tenSecondsLater = _ = > console.log('10 seconds passed!')
setTimeout(tenSecondsLater, 10000)
console.log('Start!')
復制代碼
在上面的代碼中,JavaScript會執行setTimeout。然后,它會等待10秒,之后打印出"10 seconds passed!"的消息。
同時,在等待setTimeout10秒內完成時,JavaScript執行console.log("Start!")。
所以,如果你(在控制臺上)打印上面的代碼,這就是你會看到的:
// What happens:
// > Start! (almost immediately)
// > 10 seconds passed! (after ten seconds)
復制代碼
啊~異步操作聽起來很復雜,不是嗎?但為什么我們在JavaScript中頻繁使用它呢?
要了解為什么異步操作很重要呢?想象一下JavaScript是你家中的機器人助手。這個助手非常愚蠢。它一次只能做一件事。(此行為被稱為單線程)。
假設你告訴你的機器人助手為你訂購一些披薩。但機器人是如此的愚蠢,在打電話給披薩店之后,機器人坐在你家門前,等待披薩送達。在此期間它無法做任何其它事情。
你不能叫它去熨衣服,拖地或在等待(披薩到來)的時候做任何事情。(可能)你需要等20分鐘,直到披薩到來,它才愿意做其他事情...
此行為稱為阻塞。當你等待某些內容完成時,其他操作將被阻止。
const orderPizza = flavour => {
callPizzaShop(`I want a ${flavour} pizza`)
waits20minsForPizzaToCome() // Nothing else can happen here
bringPizzaToYou()
}
orderPizza('Hawaiian')
// These two only starts after orderPizza is completed
mopFloor()
ironClothes()
復制代碼
而阻止操作是一個無賴。
為什么?
讓我們把愚蠢的機器人助手放到瀏覽器的上下文中。想象一下,當單擊按鈕時,你告訴它更改按鈕的顏色。
這個愚蠢的機器人會做什么?
它專注于按鈕,忽略所有命令,直到按鈕被點擊。同時,用戶無法選擇任何其他內容。看看它都在干嘛了?這就是異步編程在JavaScript中如此重要的原因。
但是,要真正了解異步操作期間發生的事情,我們需要引入另外一個東西 -- 事件循環。
為了設想事件循環,想象一下JavaScript是一個攜帶todo-list的管家。此列表包含你告訴它要做的所有事情。然后,JavaScript將按照你提供的順序逐個遍歷列表。
假設你給JavaScript下面五個命令:
const addOne = (n) => n + 1
addOne(1) // 2
addOne(2) // 3
addOne(3) // 4
addOne(4) // 5
addOne(5) // 6
復制代碼
這是JavaScript的待辦事項列表中出現的內容。
相關命令在JavaScript待辦事項列表中同步出現。
除了todo-list之外,JavaScript還保留一個waiting-list來跟蹤它需要等待的事情。如果你告訴JavaScript訂購披薩,它會打電話給披薩店并在等候列表名單中添加“等待披薩到達”(的指令)。與此同時,它還會做了其他已經在todo-list上的事情。
所以,想象下你有下面代碼:
const orderPizza (flavor, callback) {
callPizzaShop(`I want a ${flavor} pizza`)
// Note: these three lines is pseudo code, not actual JavaScript
whenPizzaComesBack {
callback()
}
}
const layTheTable = _ => console.log('laying the table')
orderPizza('Hawaiian', layTheTable)
mopFloor()
ironClothes()
復制代碼
JavaScript的初始化todo-list如下:
訂披薩,拖地和熨衣服!
然后,在執行orderPizza時,JavaScript知道它需要等待披薩送達。因此,它會在執行其余任務時,將“等待披薩送達”(的指令)添加到waiting list上。
JavaScript等待披薩到達
當披薩到達時,門鈴會通知JavaScript,當它完成其余雜務時。它會做個**心理記錄(mental note)**去執行layTheTable。
JavaScript知道它需要通過在其 mental note 中添加命令來執行layTheTable
然后,一旦完成其他雜務,JavaScript就會執行回調函數layTheTable。
其他所有內容完成后,JavaScript就會去布置桌面(layTheTable)
我的朋友,這個就被稱為事件循環。你可以使用事件循環中的實際關鍵字替換我們的管家,類比來理解所有的內容:
JavaScript的事件循環
如果你有20分鐘的空余時間,我強烈建議你觀看Philip Roberts 在JSconf中談論的事件循環。它將幫助你理解事件循環的細節。
哦~我們在事件循環繞了一大圈。我們回正題吧。
之前,我們提到如果JavaScript專注于按鈕并忽略所有其他命令,那將是不好的。是吧?
通過異步回調,我們可以提前提供JavaScript指令而無需停止整個操作。
現在,當你要求JavaScript查看點擊按鈕時,它會將“監聽按鈕”(指令)放入waiting list中并繼續進行雜務。當按鈕最終獲得點擊時,JavaScript會激活回調,然后繼續執行。
以下是回調中的一些常見用法,用于告訴JavaScript要做什么...
// Callbacks in event listeners
document.addEventListener(button, highlightTheButton)
document.removeEventListener(button, highlightTheButton)
// Callbacks in jQuery's ajax method
$.ajax('some-url', {
success (data) { /* success callback */ },
error (err) { /* error callback */}
});
// Callbacks in Node
fs.readFile('pathToDirectory', (err, data) => {
if (err) throw err
console.log(data)
})
// Callbacks in ExpressJS
app.get('/', (req, res) => res.sendFile(index.html))
復制代碼
這就是它(異步)的回調!
希望你清楚callbacks是什么以及現在如何使用它們。在開始的時候,你不會創建很多回調,所以要專注于學習如何使用可用的回調函數。
現在,在我們結束(本文)之前,讓我們看一下開發人員(使用)回調的第一個問題 -- 回調地獄。
回調地獄是一種多次回調相互嵌套的現象。當你執行依賴于先前異步活動的異步活動時,可能會發生這種情況。這些嵌套的回調使代碼更難閱讀。
根據我的經驗,你只會在Node中看到回調地獄。在使用前端JavaScript時,你幾乎從不會遇到回調地獄。
下面是一個回調地獄的例子:
// Look at three layers of callback in this code!
app.get('/', function (req, res) {
Users.findOne({ _id:req.body.id }, function (err, user) {
if (user) {
user.update({/* params to update */}, function (err, document) {
res.json({user: document})
})
} else {
user.create(req.body, function(err, document) {
res.json({user: document})
})
}
})
})
復制代碼
而現在,你有個挑戰 -- 嘗試一目了然地破譯上面的代碼。很難,不是嗎?難怪開發者在看到嵌套回調時會不寒而栗。
克服回調地獄的一個解決方案是將回調函數分解為更小的部分以減少嵌套代碼的數量:
const updateUser = (req, res) => {
user.update({/* params to update */}, function () {
if (err) throw err;
return res.json(user)
})
}
const createUser = (req, res, err, user) => {
user.create(req.body, function(err, user) {
res.json(user)
})
}
app.get('/', function (req, res) {
Users.findOne({ _id:req.body.id }, (err, user) => {
if (err) throw err
if (user) {
updateUser(req, res)
} else {
createUser(req, res)
}
})
})
復制代碼
更容易閱讀了,是吧?
還有其他解決方案來對抗新版JavaScript中的回調地獄 -- 比如promises和async / await。但是,解釋它們是我們另一天的話題。
今天,你了解到了回調是什么,為什么它們在JavaScript中如此重要以及如何使用它們。你還學會了回調地獄和對抗它的方法。現在,希望callbakcs不再嚇到你了。
你對回調還有任何疑問嗎?如果你有,請隨時在下面發表評論,我會盡快回復你的。【PS:本文譯文,若需作者解答疑問,請移步原作者文章下評論】
感謝閱讀。這篇文章是否幫助到你?如果有,我希望你考慮分享它。你可能會幫助到其他人。非常感謝!
事件委托是前端開發中常用的一種優化性能和代碼可維護性的方法,它基于DOM的事件冒泡機制。當一個元素觸發事件時,這個事件會按照從頂層到底層的順序傳播,直到最底層的元素(通常是文檔的根節點)。事件委托利用了這個特性,通過在父元素上設置事件處理程序來監聽子元素的事件,從而減少不必要的事件處理程序的數量。
1. 事件委托的定義與作用:
事件委托允許我們將事件監聽器添加到其父元素上,這樣只有當這些子元素觸發事件時,才會執行相應的處理程序。這樣做的好處是減少了不必要的事件監聽器的創建,因為不需要為每個可能觸發事件的子元素都添加一個監聽器。此外,它還可以減少內存占用和提高頁面渲染性能,因為減少了綁定到子元素上的事件處理函數的數量。
2. 使用事件委托的編程場景以及它如何提升性能:
事件委托通常用于以下場景:
通過事件委托,我們可以避免為每個獨立的子元素重復編寫相同的事件處理邏輯,從而提高了代碼的復用性和可維護性。同時,由于減少了綁定到每個子元素的事件處理函數的數量,因此可以減輕瀏覽器的負擔,提高頁面的性能。
私信【學習】即可獲取前端資料 都整理好啦!!!
*請認真填寫需求信息,我們會在24小時內與您取得聯系。