OM事件是Web开发中的一个核心概念,它允许JavaScript响应用户与网页交互的各种行为。DOM(文档对象模型)是一个跨平台和语言独立的接口,它让程序能够动态地访问和更新文档的内容、结构和样式。DOM事件是这个模型中的一个关键组成部分,它提供了一种机制来捕捉和响应用户的行为,如点击、滚动、按键等。
DOM事件遵循一个称为“事件流”的过程,该过程定义了从页面中接收事件的顺序。这个流程可以分为三个阶段:
开发者可以选择在捕获阶段或冒泡阶段添加事件监听器,从而控制事件的处理时机。
为了响应事件,开发者需要在DOM元素上注册事件监听器(也称为事件处理程序)。这通常通过addEventListener方法实现。例如,以下代码在一个按钮元素上添加了一个点击事件监听器:
<!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>
<!-- 创建一个按钮 -->
<button id="myButton">点击我</button>
<!-- 引入JavaScript来处理点击事件 -->
<script>
// 获取按钮元素
const button = document.getElementById('myButton');
// 为按钮添加点击事件监听器
button.addEventListener('click', function(event) {
// 当按钮被点击时,显示一个警告框
alert('按钮被点击了!');
});
</script>
</body>
</html>
当用户点击该按钮时,会弹出一个警告框。
当事件发生时,浏览器会创建一个事件对象,这个对象包含了与事件相关的所有信息,如触发事件的元素、事件类型、发生时间等。事件对象会作为参数传递给事件处理函数,允许开发者在函数内部访问这些信息。
button.addEventListener('click', function(event) {
console.log(event.target); // 输出触发事件的元素
});
DOM事件有很多种类型,以下是一些常见的事件类型:
事件委托是一种常用的事件处理模式,它利用了DOM事件的冒泡原理。开发者可以在父元素上设置一个事件监听器来管理所有子元素的相同事件。这种方式可以提高性能,减少内存使用,并简化事件管理。
<!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>
<!-- 创建一个无序列表 -->
<ul id="myList">
<li>列表项 1</li>
<li>列表项 2</li>
<li>列表项 3</li>
<li>列表项 4</li>
</ul>
<!-- 引入JavaScript来处理点击事件 -->
<script>
// 为整个列表添加点击事件监听器
document.getElementById('myList').addEventListener('click', function(event) {
// 检查被点击的元素是否是列表项
if (event.target.tagName === 'LI') {
// 如果是列表项,显示一个警告框
alert('列表项被点击!');
}
});
</script>
</body>
</html>
在这个例子中,点击任何列表项都会触发事件处理函数,尽管监听器是在它们的父元素上注册的。
DOM事件是与用户交互不可或缺的一部分,它们使得前端开发者能够创建动态和响应式的网页。理解事件的工作原理以及如何有效地使用它们是每个前端开发者必备的技能。随着技术的不断进步,DOM事件的API和模型也在不断演变,但其基本原理和实践仍然是构建现代Web应用的基石。
活中犯错误是正常的,没有人不会犯错误,更何况是开发人员呢?今天我们就来卡看看开发人员在编写 HTML 和 CSS 时最常犯的六大错误有哪些。
作者 | Stas Melnikov
译者 | 弯月,责编 | 刘静
出品 | CSDN(ID:CSDNnews)
以下为译文:
用placeholder属性代替label元素
开发人员经常用placeholder属性代替label元素。但是,在这种写法下,使用屏幕阅读器的用户无法填写字段,因为屏幕阅读器无法从placeholder属性中读取文本。
<input type="email" placeholder="Enter your email">
因此,我建议用label元素显示字段名称,而placeholder应该作为例子显示在用户需要填充的数据中。
<label>
<span>Enter your email</span>
<input type="email" placeholder="e.g. example@gmail.com">
</label>
用img元素标记装饰用的图片
我经常看到开发人员混淆装饰图片和内容图片。例如,他们会使用img元素来显示社交图标。
<a href="https://twitter.com" class="social">
<img class="social__icon" src="twitter.svg" alt>
<span class="social__name">Twitter</span>
</a>
然而,社交图标是装饰性图标,其目的是帮助用户迅速理解元素的含义,而无需阅读文本。即便我们删除这些图标,元素的含义也不会消失,所以我们应该使用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属性来禁止textarea调整大小,那么你就破坏了可访问性。因为用户无法舒适地输入数据。
textarea {
width: 100%;
height: 200px;
resize: none;
}
你应该使用min-width、max-width、min-height以及max-height属性,这些属性可以限制元素的大小,而且用户也可以舒舒服服地输入数据。
textarea {
min-width: 100%;
max-width: 100%;
min-height: 200px;
max-height: 400px;
}
同时使用display: block和position: absolute(fixed)
我经常看见开发人员像下面这样使用display和position属性:
.button::before {
content: "";
display: block;
position: absolute;
top: 0;
left: 0;
}
但是,浏览器会默认设置block。因此,你无需为absolute或fixed的元素设置这个值。也就是说,以下代码的结果与上述代码完全相同。
.button::before {
content: "";
position: absolute;
top: 0;
left: 0;
}
Outline属性的none值
无法通过键盘访问网站;链接打不开;无法注册等等。出现这些情况是因为开发人员将outline属性设置成了none值,因此元素无法聚焦。
.button:focus {
outline: none;
}
/* or */
.button:focus {
outline: 0;
}
如果你需要禁用默认的聚焦,那么也别忘了指定取而代之的聚焦状态。
.button:focus {
outline: none;
box-shadow: 0 0 3px 0 blue;
}
空元素
开发人员经常使用HTML空元素来调整元素的样式。例如,利用空div或span元素来显示导航栏菜单。
<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;
}
其实,你可以使用 ::before和 ::after伪元素达成同样的效果。
<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 翻译,转载请注明来源出处。
【END】
来的产品经理,想做一个和qq或者微信聊天一样的,上下拖动动态改变文本内容框和编辑器布局的需求。 其实一开始是一头雾水的,但是通过万能的mdn,以及充满智慧的我,最终还是完成了这个需求。 其中最核心的还是ResizeObserver这个第一次用的类,所以会在这里做一些记录。
entries是一个数组,它由所有的ResizeObserverEntry object组成。通过for (let entry of entries) {}的方式,entry代表一个ResizeObserver object,一个entry由contentRect和target组成。
在resize相关实践中,entry的contentRect对象是最最重要的。
{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发送消息,按下Shift+Enter换行"
:style="{height: dynamicHeight}"
></div>
computed: {
dynamicHeight() {
return `${defaultEditorHeight + this.deltaHeight}px`;
},
},
this.$bus.$on('rerenderViewAndEditor', (deltaHeight) => {
this.deltaHeight = deltaHeight;
});
自动跳到最新一条消息的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
努力成为优秀的前端工程师!
期待和大家交流,共同进步
微信公众号: 大大大前端 / excellent_developers
努力成为优秀前端工程师!
*请认真填写需求信息,我们会在24小时内与您取得联系。