OM事件是Web開發(fā)中的一個(gè)核心概念,它允許JavaScript響應(yīng)用戶與網(wǎng)頁(yè)交互的各種行為。DOM(文檔對(duì)象模型)是一個(gè)跨平臺(tái)和語(yǔ)言獨(dú)立的接口,它讓程序能夠動(dòng)態(tài)地訪問(wèn)和更新文檔的內(nèi)容、結(jié)構(gòu)和樣式。DOM事件是這個(gè)模型中的一個(gè)關(guān)鍵組成部分,它提供了一種機(jī)制來(lái)捕捉和響應(yīng)用戶的行為,如點(diǎn)擊、滾動(dòng)、按鍵等。
DOM事件遵循一個(gè)稱為“事件流”的過(guò)程,該過(guò)程定義了從頁(yè)面中接收事件的順序。這個(gè)流程可以分為三個(gè)階段:
開發(fā)者可以選擇在捕獲階段或冒泡階段添加事件監(jiān)聽器,從而控制事件的處理時(shí)機(jī)。
為了響應(yīng)事件,開發(fā)者需要在DOM元素上注冊(cè)事件監(jiān)聽器(也稱為事件處理程序)。這通常通過(guò)addEventListener方法實(shí)現(xiàn)。例如,以下代碼在一個(gè)按鈕元素上添加了一個(gè)點(diǎn)擊事件監(jiān)聽器:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Button Click Example</title>
</head>
<body>
<!-- 創(chuàng)建一個(gè)按鈕 -->
<button id="myButton">點(diǎn)擊我</button>
<!-- 引入JavaScript來(lái)處理點(diǎn)擊事件 -->
<script>
// 獲取按鈕元素
const button = document.getElementById('myButton');
// 為按鈕添加點(diǎn)擊事件監(jiān)聽器
button.addEventListener('click', function(event) {
// 當(dāng)按鈕被點(diǎn)擊時(shí),顯示一個(gè)警告框
alert('按鈕被點(diǎn)擊了!');
});
</script>
</body>
</html>
當(dāng)用戶點(diǎn)擊該按鈕時(shí),會(huì)彈出一個(gè)警告框。
當(dāng)事件發(fā)生時(shí),瀏覽器會(huì)創(chuàng)建一個(gè)事件對(duì)象,這個(gè)對(duì)象包含了與事件相關(guān)的所有信息,如觸發(fā)事件的元素、事件類型、發(fā)生時(shí)間等。事件對(duì)象會(huì)作為參數(shù)傳遞給事件處理函數(shù),允許開發(fā)者在函數(shù)內(nèi)部訪問(wèn)這些信息。
button.addEventListener('click', function(event) {
console.log(event.target); // 輸出觸發(fā)事件的元素
});
DOM事件有很多種類型,以下是一些常見的事件類型:
事件委托是一種常用的事件處理模式,它利用了DOM事件的冒泡原理。開發(fā)者可以在父元素上設(shè)置一個(gè)事件監(jiān)聽器來(lái)管理所有子元素的相同事件。這種方式可以提高性能,減少內(nèi)存使用,并簡(jiǎn)化事件管理。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>List Item Click Example</title>
</head>
<body>
<!-- 創(chuàng)建一個(gè)無(wú)序列表 -->
<ul id="myList">
<li>列表項(xiàng) 1</li>
<li>列表項(xiàng) 2</li>
<li>列表項(xiàng) 3</li>
<li>列表項(xiàng) 4</li>
</ul>
<!-- 引入JavaScript來(lái)處理點(diǎn)擊事件 -->
<script>
// 為整個(gè)列表添加點(diǎn)擊事件監(jiān)聽器
document.getElementById('myList').addEventListener('click', function(event) {
// 檢查被點(diǎn)擊的元素是否是列表項(xiàng)
if (event.target.tagName === 'LI') {
// 如果是列表項(xiàng),顯示一個(gè)警告框
alert('列表項(xiàng)被點(diǎn)擊!');
}
});
</script>
</body>
</html>
在這個(gè)例子中,點(diǎn)擊任何列表項(xiàng)都會(huì)觸發(fā)事件處理函數(shù),盡管監(jiān)聽器是在它們的父元素上注冊(cè)的。
DOM事件是與用戶交互不可或缺的一部分,它們使得前端開發(fā)者能夠創(chuàng)建動(dòng)態(tài)和響應(yīng)式的網(wǎng)頁(yè)。理解事件的工作原理以及如何有效地使用它們是每個(gè)前端開發(fā)者必備的技能。隨著技術(shù)的不斷進(jìn)步,DOM事件的API和模型也在不斷演變,但其基本原理和實(shí)踐仍然是構(gòu)建現(xiàn)代Web應(yīng)用的基石。
活中犯錯(cuò)誤是正常的,沒(méi)有人不會(huì)犯錯(cuò)誤,更何況是開發(fā)人員呢?今天我們就來(lái)卡看看開發(fā)人員在編寫 HTML 和 CSS 時(shí)最常犯的六大錯(cuò)誤有哪些。
作者 | Stas Melnikov
譯者 | 彎月,責(zé)編 | 劉靜
出品 | CSDN(ID:CSDNnews)
以下為譯文:
用placeholder屬性代替label元素
開發(fā)人員經(jīng)常用placeholder屬性代替label元素。但是,在這種寫法下,使用屏幕閱讀器的用戶無(wú)法填寫字段,因?yàn)槠聊婚喿x器無(wú)法從placeholder屬性中讀取文本。
<input type="email" placeholder="Enter your email">
因此,我建議用label元素顯示字段名稱,而placeholder應(yīng)該作為例子顯示在用戶需要填充的數(shù)據(jù)中。
<label>
<span>Enter your email</span>
<input type="email" placeholder="e.g. example@gmail.com">
</label>
用img元素標(biāo)記裝飾用的圖片
我經(jīng)??吹介_發(fā)人員混淆裝飾圖片和內(nèi)容圖片。例如,他們會(huì)使用img元素來(lái)顯示社交圖標(biāo)。
<a href="https://twitter.com" class="social">
<img class="social__icon" src="twitter.svg" alt>
<span class="social__name">Twitter</span>
</a>
然而,社交圖標(biāo)是裝飾性圖標(biāo),其目的是幫助用戶迅速理解元素的含義,而無(wú)需閱讀文本。即便我們刪除這些圖標(biāo),元素的含義也不會(huì)消失,所以我們應(yīng)該使用background-image屬性。
<a href="https://twitter.com" class="social">
<span class="social__name">Twitter</span>
</a>
.social::before {
background-image: url("twitter.svg");
}
使用resize屬性
如果利用resize屬性來(lái)禁止textarea調(diào)整大小,那么你就破壞了可訪問(wèn)性。因?yàn)橛脩魺o(wú)法舒適地輸入數(shù)據(jù)。
textarea {
width: 100%;
height: 200px;
resize: none;
}
你應(yīng)該使用min-width、max-width、min-height以及max-height屬性,這些屬性可以限制元素的大小,而且用戶也可以舒舒服服地輸入數(shù)據(jù)。
textarea {
min-width: 100%;
max-width: 100%;
min-height: 200px;
max-height: 400px;
}
同時(shí)使用display: block和position: absolute(fixed)
我經(jīng)常看見開發(fā)人員像下面這樣使用display和position屬性:
.button::before {
content: "";
display: block;
position: absolute;
top: 0;
left: 0;
}
但是,瀏覽器會(huì)默認(rèn)設(shè)置block。因此,你無(wú)需為absolute或fixed的元素設(shè)置這個(gè)值。也就是說(shuō),以下代碼的結(jié)果與上述代碼完全相同。
.button::before {
content: "";
position: absolute;
top: 0;
left: 0;
}
Outline屬性的none值
無(wú)法通過(guò)鍵盤訪問(wèn)網(wǎng)站;鏈接打不開;無(wú)法注冊(cè)等等。出現(xiàn)這些情況是因?yàn)殚_發(fā)人員將outline屬性設(shè)置成了none值,因此元素?zé)o法聚焦。
.button:focus {
outline: none;
}
/* or */
.button:focus {
outline: 0;
}
如果你需要禁用默認(rèn)的聚焦,那么也別忘了指定取而代之的聚焦?fàn)顟B(tài)。
.button:focus {
outline: none;
box-shadow: 0 0 3px 0 blue;
}
空元素
開發(fā)人員經(jīng)常使用HTML空元素來(lái)調(diào)整元素的樣式。例如,利用空div或span元素來(lái)顯示導(dǎo)航欄菜單。
<button class="hamburger">
<span></span>
<span></span>
<span></span>
</button>
.hamburger {
width: 60px;
height: 45px;
position: relative;
}
.hamburger span {
width: 100%;
height: 9px;
background-color: #d3531a;
border-radius: 9px;
position: absolute;
left: 0;
}
.hamburger span:nth-child(1) {
top: 0;
}
.hamburger span:nth-child(2) {
top: 18px;
}
.hamburger span:nth-child(3) {
top: 36px;
}
其實(shí),你可以使用 ::before和 ::after偽元素達(dá)成同樣的效果。
<button class="hamburger">
<span class="hamburger__text">
<span class="visually-hidden">Open menu</span>
</span>
</button>
.hamburger {
width: 60px;
height: 45px;
position: relative;
}
.hamburger::before,
.hamburger::after,
.hamburger__text::before {
content: "";
width: 100%;
height: 9px;
background-color: #d3531a;
border-radius: 9px;
position: absolute;
left: 0;
}
.hamburger::before {
top: 0;
}
.hamburger::after {
top: 18px;
}
.hamburger__text::before {
top: 36px;
}
.visually-hidden {
position: absolute !important;
clip: rect(1px, 1px, 1px, 1px);
width: 1px !important;
height: 1px !important;
overflow: hidden;
}
原文:https://dev.to/melnik909/the-6-most-common-mistakes-developers-when-writing-html-and-css-f92
本文為 CSDN 翻譯,轉(zhuǎn)載請(qǐng)注明來(lái)源出處。
【END】
來(lái)的產(chǎn)品經(jīng)理,想做一個(gè)和qq或者微信聊天一樣的,上下拖動(dòng)動(dòng)態(tài)改變文本內(nèi)容框和編輯器布局的需求。 其實(shí)一開始是一頭霧水的,但是通過(guò)萬(wàn)能的mdn,以及充滿智慧的我,最終還是完成了這個(gè)需求。 其中最核心的還是ResizeObserver這個(gè)第一次用的類,所以會(huì)在這里做一些記錄。
entries是一個(gè)數(shù)組,它由所有的ResizeObserverEntry object組成。通過(guò)for (let entry of entries) {}的方式,entry代表一個(gè)ResizeObserver object,一個(gè)entry由contentRect和target組成。
在resize相關(guān)實(shí)踐中,entry的contentRect對(duì)象是最最重要的。
{target: div, contentRect: DOMRectReadOnly}
contentRect: DOMRectReadOnly
bottom: 312.3125
height: 292.3125
left: 20
right: 626
top: 20
width: 606
x: 20
y: 20
__proto__: DOMRectReadOnly
target: div
__proto__: ResizeObserverEntry
<div class="main" :style="{minHeight: dynamicMainHeight}">
<chatView></chatView>
</div>
.main {
resize: vertical;
overflow: auto;
}
observeChatView() {
if (window.ResizeObserver) {
const viewElem = document.querySelector('.main');
const resizeObserver = new ResizeObserver((entries) => {
for (const entry of entries) {
if (!this.initialHeight) {
this.initialHeight = entry.contentRect.height;
}
if (this.initialHeight) {
const deltaHeight = this.initialHeight - entry.contentRect.height;
this.$bus.$emit('rerenderViewAndEditor', deltaHeight);
}
}
});
resizeObserver.observe(viewElem);
} else {
this.$Message.warning('不支持ResizeObserver');
}
},
},
<div
class="rich-text-editor"
contenteditable
data-placeholder="按下Enter發(fā)送消息,按下Shift+Enter換行"
:style="{height: dynamicHeight}"
></div>
computed: {
dynamicHeight() {
return `${defaultEditorHeight + this.deltaHeight}px`;
},
},
this.$bus.$on('rerenderViewAndEditor', (deltaHeight) => {
this.deltaHeight = deltaHeight;
});
自動(dòng)跳到最新一條消息的chatView組件需要減去deltaHeight,從而增大scrollHeight的高度。
this.$bus.$on('rerenderViewAndEditor', (deltaHeight) => {
this.visiableHeight = document.body.clientHeight - deltaHeight;
this.deltaHeight = deltaHeight;
});
scrollToBottom() {
this.$nextTick(() => {
this.scrollTop = this.scrollHeight - this.deltaHeight;
});
},
https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver/ResizeObserver https://github.com/mdn/dom-examples/blob/master/resize-observer/resize-observer-text.html
努力成為優(yōu)秀的前端工程師!
期待和大家交流,共同進(jìn)步
微信公眾號(hào): 大大大前端 / excellent_developers
努力成為優(yōu)秀前端工程師!
*請(qǐng)認(rèn)真填寫需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。