01 Prefácio
BOM (Browser Object Model) e DOM (Document Object Model) são dois conceitos indispensáveis no desenvolvimento front-end. O BOM fornece funcionalidade como acessar a janela do navegador e documentos dentro da janela, enquanto o DOM fornece interfaces para manipular documentos HTML e XML. Uma compreensão sólida do BOM e do DOM é fundamental para o desenvolvimento de aplicativos da Web eficientes e de alta qualidade.
Este artigo abordará algumas operações específicas sobre BOM e DOM acima, ou seja, um resumo das técnicas comuns. Explique detalhadamente como usar BOM e DOM, incluindo, entre outros, objetos BOM, eventos BOM, nós DOM e eventos DOM. Seja você iniciante ou um desenvolvedor experiente, este artigo fornecerá uma referência abrangente.
02 DOM
Quando uma página da web é carregada, o navegador cria o Document Object Model (Modelo de objeto de documento) da página.
Por meio desse modelo de objeto, o JavaScript obtém todo o poder para criar HTML dinâmico:
- JavaScript pode alterar todos os elementos HTML na página
- JavaScript pode alterar todos os atributos HTML na página
- JavaScript pode alterar todos os estilos CSS na página
- O JavaScript pode remover elementos e atributos HTML existentes
- JavaScript pode adicionar novos elementos e atributos HTML
- O JavaScript pode reagir a todos os eventos HTML existentes na página
- JavaScript pode criar novos eventos HTML na página
Em outras palavras: HTML DOM é um padrão sobre como obter, alterar, adicionar ou remover elementos HTML.
2.1 Encontrando elementos
Métodos comumente usados para encontrar elementos, aqui está um suplemento e uma dica para o acima.
método | descrever |
---|---|
document.getElementById(id) | Encontre elementos por id de elemento. |
document.getElementsByTagName(nome) | Encontre elementos por nome de tag. |
document.getElementsByClassName(nome) | Encontre elementos por nome de classe. |
document.querySelector (seletor de CSS) | Selecione um elemento por meio de um seletor CSS. |
document.querySelectorAll (seletor de CSS) | Selecione vários elementos por meio de seletores CSS. |
2.2 Lendo HTML
método | descrever |
---|---|
elemento node.innerText | Obtenha o texto interno do elemento HTML. |
elemento node.innerHTML | Obtenha o HTML interno do elemento HTML. |
elemento node.attribute | Obtenha o valor do atributo de um elemento HTML. |
elemento node.getAttribute(attribute) | Obtenha o valor do atributo de um elemento HTML. |
elemento nó.estilo.estilo | Obtém o valor de estilo embutido de um elemento HTML. |
Outras adições:
operar | descrever |
---|---|
document.getElementById(id) | Retorna o objeto de elemento com o ID especificado. |
document.getElementsByTagName(nome) | Retorna uma matriz de objetos de elemento com os nomes de marca especificados. |
element.innerHTML | Obtém ou define o conteúdo HTML do elemento. |
elemento.estilo.propriedade | Obtém ou define o atributo de estilo do elemento. |
element.setAttribute(nome, valor) | Define o valor do atributo do elemento. |
elemento.getAttribute(nome) | Retorna o valor do atributo do elemento. |
element.appendChild(nó) | Adiciona o nó especificado ao final da lista de nós filhos do elemento. |
element.removeChild(nó) | Remove o nó filho especificado da lista de nós filhos do elemento. |
element.addEventListener(evento, função) | Adicione ouvintes de eventos. |
element.classList.add(class) | Adicione o nome da classe ao atributo de classe do elemento. |
element.classList.remove(class) | Remove o nome da classe do atributo de classe do elemento. |
element.classList.toggle(classe) | Alterna o nome da classe no atributo de classe do elemento. |
element.classList.contains(class) | Verifica se o nome de classe especificado está contido no atributo de classe do elemento. |
Essas operações DOM podem ser usadas para acessar e manipular elementos e conteúdo em documentos HTML, permitindo que os desenvolvedores atualizem e alterem dinamicamente o conteúdo e o estilo das páginas HTML.
2.2.1 O navegador lê o estilo padrão
Observação: tanto definir como ler o atributo de estilo sãoestilos embutidos, o estilo na folha de estilo ou o estilo que está sendo aplicado não pode ser lido . Se quisermos ler o atributo de estilo que está sendo aplicado, podemos usá-lo
元素.currentStyle.样式名
para obter o estilo exibido atualmente do elemento, que pode ser usado para ler o atributo atualmente estilo exibido do elemento Style, se o elemento atual não definir o estilo, obtenha seu valor padrão, mas currentStyleSuportado apenas pelo navegador IE, outros navegadores não o suportam.
Este método pode ser usado em outros navegadores getComputedStyle()
para obter o estilo atual do elemento, este método é um método de janela e pode ser usado diretamente, mas requer dois parâmetros:
- O primeiro parâmetro: o elemento para obter o estilo
- O segundo parâmetro: um pseudo-elemento pode ser passado, geralmente nulo
Este método retornará um objeto que encapsula o estilo correspondente ao elemento atual. Você pode ler o estilo 对象.样式名
através de . Se o estilo adquirido não estiver definido, você obterá o valor real em vez do valor padrão.
Por exemplo: se a largura não for definida, não será automático, mas um comprimento, mas este método não suporta navegadores IE8 e anteriores.
Os estilos lidos por currentStyle e getComputedStyle() são somente leitura e não podem ser modificados. Se você deseja modificá-los, deve passar o atributo style. Portanto, podemos escrever um método para ler estilos de elemento que se adapte a cada navegador.
Apresentação do caso:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
/*样式表的样式*/
#box {
width: 200px;
height: 200px;
background-color: green;
}
</style>
</head>
<body>
<div style="width: 100px;height: 100px;" id="box"></div>
<!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
<script>
/*通用的获取元素样式的方法*/
function getStyle(obj, name) {
if (window.getComputedStyle) {
//正常浏览器的方式,具有getComputedStyle()方法
return getComputedStyle(obj, null)[name];
} else {
//IE8的方式,没有getComputedStyle()方法
return obj.currentStyle[name];
}
}
var box = document.getElementById("box");
console.log(getStyle(box, "width"));
console.log(getStyle(box, "height"));
console.log(getStyle(box, "background-color"));
</script>
</body>
</html>
2.2.2 Obter o conteúdo de texto de qualquer rótulo
Suponha que tenhamos uma página HTML com um elemento div com um atributo ID e um elemento p com um atributo class. Podemos usar o DOM para obter o conteúdo de texto desses elementos.
A seguir, uma demonstração de caso para obter o conteúdo de texto de qualquer rótulo:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<a href="https://www.baidu.com" id="a">打开百度,你就知道!</a>
<!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
<script>
var a = document.getElementById("a");
console.log(getInnerText(a));
/*获取任意标签的内容*/
function getInnerText(element) {
// 判断浏览器是否支持textContent,如果支持,则使用textContent获取内容,否则使用innerText获取内容。
if(typeof element.textContent == "undefined") {
return element.innerText;
} else {
return element.textContent;
}
}
</script>
</body>
</html>
O código acima primeiro usa getElementById
o método para obter o elemento a e usa textContent
o atributo ou getInnerText
obtém seu conteúdo de texto e, em seguida, o imprime no console. Dessa forma, podemos usar o DOM para obter o conteúdo de texto de qualquer rótulo.
2.3 Modificar HTML
método | descrever |
---|---|
elemento node.innerText = novo conteúdo de texto | Altere o Texto interno do elemento. |
elemento node.innerHTML = novo conteúdo html | Altere o HTML interno de um elemento. |
elemento node.attribute = novo valor | Altere o valor do atributo de um elemento HTML. |
elemento node.setAttribute(atributo, valor) | Altere o valor do atributo de um elemento HTML. |
elemento node.style.style = novo estilo | Altere o valor do estilo embutido de um elemento HTML. |
Observação: Somente .style pode ser usado para alterar o estilo, outros métodos subsequentes são para ler o estilo ou modificar o HTML
2.3.1 insertAdjacentHTML
e insertAdjacentText
modificação da implementação do método
Nota: Além do innerHTML e do innerText comumente usados para modificar o conteúdo do nó, também existem métodos
insertAdjacentHTML
einsertAdjacentText
, que podem inserir conteúdo no local especificado.insertAdjacentText
O métodoinsertAdjacentHTML
é semelhante ao método, exceto que o texto simples é inserido, com os mesmos parâmetros.
Precauções:
- Esses dois métodos devem ser executados após o carregamento do documento, caso contrário ocorrerá um erro.
- insertAdjacentText só pode inserir texto comum e insertAdjacentHTML insere código html.
- Ao usar o método insertAdjacentHTML para inserir um arquivo de script, o atributo defer deve ser definido no elemento script.
- Depois de usar o método insertAdjacentHTML para inserir o código html,A coleção de elementos na página mudará。
- insertAdjacentHTML方法不适用于单个的空的元素标签(如img,input等)。
参数说明:
参数一:where:
- beforeBegin:插入到开始标签的前面
- beforeEnd:插入到结束标签的前面
- afterBegin:插入到开始标签的后面
- afterEnd:插入到结束标签的后面
参数二:
- html:一段html代码
- text:一段文本值
代码示例:
<!DOCTYPE html>
<html>
<head>
<title>DOM示例</title>
</head>
<body>
<p class="myPara">这是一个示例p元素。</p>
<div id="myDiv">这是一个示例div元素。</div>
<script>
// 使用insertAdjacentHTML添加狐妖小红娘的优酷视频超链接
document.body.insertAdjacentHTML('beforeend', '<p><a href="https://v.youku.com/v_show/id_XMTMzNzgyMzY5Ng==.html?spm=a2h1n.8251845.0.0" target="_blank">狐妖小红娘的优酷视频</a></p>');
// 使用insertAdjacentText添加狐妖小红娘的简介
var myPara = document.getElementsByClassName('myPara')[0];
myPara.insertAdjacentText('afterEnd', '以下是狐妖小红娘的简介:');
// 使用insertAdjacentElement添加狐妖小红娘的简介
var myDiv = document.getElementById('myDiv');
var introPara = document.createElement('p');
var introText = document.createTextNode('《狐妖小红娘》是一部描写狐妖与人类之间的爱情故事的动漫作品。');
introPara.appendChild(introText);
myDiv.insertAdjacentElement('beforeBegin', introPara);
</script>
</body>
</html>
2.3.2 编写一段兼容性代码,用来设置任意标签的文本内容
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<a href="https://www.baidu.com" id="a">打开百度,你就知道!</a>
<!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
<script>
var a = document.getElementById("a");
setInnerText(a, "你要打开百度吗?");
console.log(getInnerText(a));
/*获取任意标签的内容*/
function getInnerText(element) {
// 判断浏览器是否支持textContent,如果支持,则使用textContent获取内容,否则使用innerText获取内容。
if (typeof element.textContent == "undefined") {
return element.innerText;
} else {
return element.textContent;
}
}
/*设置任意标签的内容*/
function setInnerText(element, text) {
// 判断浏览器是否支持textContent,如果支持,则使用textContent设置内容,否则使用innerText设置内容。
if (typeof element.textContent == "undefined") {
return element.innerText = text;
} else {
return element.textContent = text;
}
}
</script>
</body>
</html>
2.4 修改元素样式
方法 | 描述 |
---|---|
document.createElement(element) | 创建 HTML 元素节点。 |
document.createAttribute(attribute) | 创建 HTML 属性节点。 |
document.createTextNode(text) | 创建 HTML 文本节点。 |
元素节点.removeChild(element) | 删除 HTML 元素。 |
元素节点.appendChild(element) | 添加 HTML 元素。 |
元素节点.replaceChild(element) | 替换 HTML 元素。 |
元素节点.insertBefore(element) | 在指定的子节点前面插入新的子节点。 |
2.4.1兼容性修改样式
动态判断、添加、删除、切换样式,支持IE5-IE11,谷歌浏览器、火狐浏览器等
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
.b1 {
width: 100px;
height: 100px;
background-color: red;
}
.b2 {
width: 300px;
height: 300px;
background-color: yellow;
}
</style>
</head>
<body>
<button id="btn0">判断b2样式</button>
<button id="btn1">添加b2样式</button>
<button id="btn2">删除b2样式</button>
<button id="btn3">切换b2样式</button>
<br>
<br>
<div id="box" class="b1"></div>
<!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
<script>
var btn0 = document.getElementById("btn0");
var btn1 = document.getElementById("btn1");
var btn2 = document.getElementById("btn2");
var btn3 = document.getElementById("btn3");
var box = document.getElementById("box");
btn0.onclick = function () {
alert(hasClass(box, "b2"));
};
btn1.onclick = function () {
addClass(box, "b2");
};
btn2.onclick = function () {
removeClass(box, "b2");
};
btn3.onclick = function () {
toggleClass(box, "b2");
};
/*
* 判断一个元素中是否含有指定的class属性值
* 如果有该class,则返回true,没有则返回false
*/
function hasClass(obj, cn) {
var reg = new RegExp("\\b" + cn + "\\b");
return reg.test(obj.className);
}
/*
* 向一个元素中添加指定的class属性值
* 参数:
* obj 要添加class属性的元素
* cn 要添加的class值
*/
function addClass(obj, cn) {
// 检查obj中是否含有cn
if (!hasClass(obj, cn)) {
obj.className += " " + cn;
}
}
/*
* 删除一个元素中的指定的class属性
*/
function removeClass(obj, cn) {
var reg = new RegExp("\\b" + cn + "\\b");
obj.className = obj.className.replace(reg, "");
}
/*
* toggleClass可以用来切换一个类
* 如果元素中具有该类,则删除
* 如果元素中没有该类,则添加
*/
function toggleClass(obj, cn) {
// 判断obj中是否含有cn
if (hasClass(obj, cn)) {
// 存在,则删除
removeClass(obj, cn);
} else {
// 没有,则添加
addClass(obj, cn);
}
}
</script>
</body>
</html>
2.5 查找父子节点
下面是利用 DOM 树查找各种节点的常用函数和方法以及它们的返回值和用途的表格展示:
查找函数/方法 | 返回值 | 用途 |
---|---|---|
元素节点 getElementById | 单个元素 | 通过 ID 获取元素 |
getElementsByClassName | 元素集合 | 通过类名获取元素 |
getElementsByTagName | 元素集合 | 通过标签名获取元素 |
querySelector | 单个元素 | 通过选择器获取元素 |
querySelectorAll | 元素集合 | 通过选择器获取元素 |
文本节点 createTextNode | 文本节点 | 创建文本节点 |
nodeValue | 字符串 | 获取/设置节点的文本内容 |
属性节点 getAttribute | 字符串 | 获取元素的属性值 |
setAttribute | 无返回值 | 设置元素的属性值 |
removeAttribute | 无返回值 | 移除元素的属性 |
父节点 parentNode | 元素节点 | 获取元素的父元素 |
parentElement | 元素节点 | 获取元素的父元素 |
子节点 childNodes | 子节点集合 | 获取元素的所有子节点 |
children | 元素节点集合 | 获取元素的所有子元素 |
firstChild | 子节点 | 获取元素的第一个子节点 |
firstElementChild | 元素节点 | 获取元素的第一个子元素 |
lastChild | 子节点 | 获取元素的最后一个子节点 |
lastElementChild | 元素节点 | 获取元素的最后一个子元素 |
nextSibling | 兄弟节点 | 获取元素的下一个兄弟节点 |
nextElementSibling | 元素节点 | 获取元素的下一个兄弟元素 |
previousSibling | 兄弟节点 | 获取元素的上一个兄弟节点 |
previousElementSibling | 元素节点 | 获取元素的上一个兄弟元素 |
创建节点 createElement | 元素节点 | 创建新的元素节点 |
createAttribute | 属性节点 | 创建新的属性节点 |
createComment | 注释节点 | 创建新的注释节点 |
createDocumentFragment | 文档片段节点 | 创建新的文档片段节点 |
插入节点 appendChild | 子节点 | 将新的子节点添加到元素的子节点列表的末尾 |
insertBefore | 子节点 | 将新的子节点插入到指定位置之前 |
删除节点 removeChild | 子节点 | 从元素的子节点列表中删除一个子节点 |
replaceChild | 子节点 | 替换元素的子节点 |
remove | 无返回值 | 从其父元素中删除当前节点 |
使用这些函数和方法,我们可以在 DOM 树中找到并操作各种类型的节点。
2.5.1 兼容性方法
/*获取任意一个父级元素的第一个子元素*/
function getfirstElementChild(element) {
if(element.firstElementChild) {
return element.firstElementChild;
} else {
var node = element.firstChild;
while(node && node.nodeType != 1) {
node = node.nextSibling;
}
return node;
}
}
/*获取任意一个父级元素的最后一个子元素*/
function getLastElementChild(element) {
if(element.lastElementChild) {
return element.lastElementChild;
} else {
var node = element.lastChild;
while(node && node.nodeType != 1) {
node = node.previousSibling;
}
return node;
}
}
/*获取任意一个子元素的前一个兄弟元素*/
function getPreviousElementSibling(element) {
if(element.previousElementSibling) {
return element.previousElementSibling;
} else {
var node = element.previousSibling;
while(node && node.nodeType != 1) {
node = node.previousSibling;
}
return node;
}
}
/*获取任意一个子元素的后一个兄弟元素*/
function getNextElementSibling(element) {
if(element.nextElementSibling) {
return element.nextElementSibling;
} else {
var node = element.nextSibling;
while(node && node.nodeType != 1) {
node = node.nextSibling;
}
return node;
}
}
案例演示:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div id="container">
<p>前面的P标签</p>
<b>加粗文本</b>
<a href="https://www.baidu.com" id="a">百度一下</a>
<i>斜体文本</i>
<p>最后的P标签</p>
</div>
<!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
<script>
/*第一个子元素*/
var firstNode = getfirstElementChild(document.getElementById("container"));
console.log(firstNode.innerHTML);
/*最后一个子元素*/
var lastNode = getLastElementChild(document.getElementById("container"));
console.log(lastNode.innerHTML);
/*指定元素的前一个子元素*/
var node1 = getPreviousElementSibling(document.getElementById("a"));
console.log(node1.innerHTML);
/*指定元素的后一个子元素*/
var node2 = getNextElementSibling(document.getElementById("a"));
console.log(node2.innerHTML);
/*获取任意一个父级元素的第一个子元素*/
function getfirstElementChild(element) {
if (element.firstElementChild) {
return element.firstElementChild;
} else {
var node = element.firstChild;
while (node && node.nodeType != 1) {
node = node.nextSibling;
}
return node;
}
}
/*获取任意一个父级元素的最后一个子元素*/
function getLastElementChild(element) {
if (element.lastElementChild) {
return element.lastElementChild;
} else {
var node = element.lastChild;
while (node && node.nodeType != 1) {
node = node.previousSibling;
}
return node;
}
}
/*获取任意一个子元素的前一个兄弟元素*/
function getPreviousElementSibling(element) {
if (element.previousElementSibling) {
return element.previousElementSibling;
} else {
var node = element.previousSibling;
while (node && node.nodeType != 1) {
node = node.previousSibling;
}
return node;
}
}
/*获取任意一个子元素的后一个兄弟元素*/
function getNextElementSibling(element) {
if (element.nextElementSibling) {
return element.nextElementSibling;
} else {
var node = element.nextSibling;
while (node && node.nodeType != 1) {
node = node.nextSibling;
}
return node;
}
}
</script>
</body>
</html>
03 dom文档事件流
3.1 事件简述
DOM 事件模型是指当网页中发生某些特定的事件时,浏览器会自动创建一个事件对象,并将该事件对象传递给相关的 JavaScript 代码,以便处理该事件。事件模型分为三个阶段:捕获阶段、目标阶段和冒泡阶段。
- 常见的 DOM 事件包括:
- 鼠标事件:click、dblclick、mousedown、mouseup、mousemove、mouseover、mouseout、mouseenter、mouseleave 等;
- 键盘事件:keydown、keyup、keypress 等;
- 表单事件:submit、reset、focus、blur、change 等;
- 窗口事件:load、unload、resize、scroll 等;
- 手机事件:touchstart、touchmove、touchend 等。
- DOM 事件处理的方式有两种:传统的事件处理方式和现代的事件处理方式。
传统的事件处理方式是在 HTML 元素中通过属性绑定事件处理函数,如:
<button onclick="alert('Hello World!')">点击我</button>
这种方式的缺点是不易于维护和扩展,因为代码和 HTML 元素紧密耦合在一起。
现代的事件处理方式是通过 JavaScript 代码动态地绑定事件处理函数,如:
const button = document.querySelector('button');
button.addEventListener('click', function() {
alert('Hello World!');
});
这种方式可以让代码和 HTML 元素分离,更易于维护和扩展。
- 事件处理函数的基本语法如下:
element.addEventListener(event, function, useCapture);
其中,element 是要绑定事件处理函数的 HTML 元素;event 是要绑定的事件名称,如 click、mousemove 等;function 是事件处理函数,可以是已经定义的函数或匿名函数;useCapture 是一个可选的布尔值,表示事件处理是否在捕获阶段执行,默认为 false,即在冒泡阶段执行。
事件处理函数中的 this 关键字指向触发事件的 HTML 元素,event 对象包含有关事件的详细信息,如事件类型、事件目标、事件发生的时间等。可以通过 event 对象的属性和方法获取这些信息,如 event.type、event.target、event.timeStamp 等。
- 除了使用
addEventListener
方法绑定事件处理函数之外,还可以使用removeEventListener
方法取消事件处理函数的绑定,如:
button.removeEventListener('click', handleClick);
其中,handleClick 是要取消绑定的事件处理函数。需要注意的是,在使用 removeEventListener 方法取消绑定时,要确保传入的事件处理函数和之前绑定的事件处理函数是同一个函数,否则无法取消绑定。
3.2 窗口事件
由窗口触发该事件 (同样适用于 标签):
属性 | 描述 |
---|---|
onblur | 当窗口失去焦点时运行脚本。 |
onfocus | 当窗口获得焦点时运行脚本。 |
onload | 当文档加载之后运行脚本。 |
onresize | 当调整窗口大小时运行脚本。 |
onstorage | 当 Web Storage 区域更新时(存储空间中的数据发生变化时)运行脚本。 |
3.2.1 标签失去焦点
案例演示:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>示例页面</title>
</head>
<body>
<h1>欢迎访问示例页面</h1>
<p>请输入您的姓名:</p>
<input type="text" id="myInput">
<script>
const myInput = document.getElementById('myInput');
myInput.addEventListener('blur', function() {
alert('您已离开该目标');
});
</script>
</body>
</html>
3.3 表单事件
表单事件在HTML表单中触发 (适用于所有 HTML 元素,但该HTML元素需在form表单内):
属性 | 描述 |
---|---|
onblur | 当元素失去焦点时运行脚本。 |
onfocus | 当元素获得焦点时运行脚本。 |
onchange | 当元素改变时运行脚本。 |
oninput | 当元素获得用户输入时运行脚本。 |
oninvalid | 当元素无效时运行脚本。 |
onselect | 当选取元素时运行脚本。 |
onsubmit | 当提交表单时运行脚本。 |
如果单击“submit”,则不填写文本字段,将发生警报消息。案例演示:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<form>
<input type="text" id="text" required>
<input type="submit" value="submit">
</form>
<!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
<script>
var textInput = document.getElementById("text");
/* 如果单击“submit”,则不填写文本字段,将发生警报消息 */
textInput.oninvalid = function () {
console.log("请您完善表单内容!");
};
</script>
</body>
</html>
3.4 键盘事件
属性 | 描述 |
---|---|
onkeydown | 当按下按键时运行脚本。 |
onkeyup | 当松开按键时运行脚本。 |
onkeypress | 当按下并松开按键时运行脚本。 |
补充:
事件名称 | 触发条件 | 相关事件属性 |
---|---|---|
keydown | 按下任意键时触发 | event.key、event.code、event.keyCode、event.shiftKey、event.ctrlKey、event.altKey |
keyup | 松开任意键时触发 | event.key、event.code、event.keyCode、event.shiftKey、event.ctrlKey、event.altKey |
keypress | 按下并松开某个键时触发 | event.key、event.code、event.charCode |
其中,event.key 表示按下或松开的键的名称(例如,a、Shift、Enter),event.code 表示按下或松开的键的标准键码(例如,KeyA、ShiftLeft、Enter),event.keyCode 表示按下或松开的键的 ASCII 码(仅适用于部分键),event.shiftKey、event.ctrlKey、event.altKey 分别表示 Shift、Ctrl 和 Alt 键是否被按下。
注意:event.keyCode 已经被废弃,推荐使用 event.key 或 event.code。
以上是常用的键盘事件代码和相关事件属性。在实际应用中,可以根据需求选择相应的事件类型和事件属性来处理键盘事件。
3.4.1 键盘实现元素块的移动
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div id="box" style="width: 100px;height: 100px;background: red;position: absolute;"></div>
<!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
<script>
var box = document.getElementById("box");
//为document绑定一个按键按下的事件
document.onkeydown = function (event) {
event = event || window.event;
// 定义移动速度
var speed = 10;
// 选择移动方向
switch (event.keyCode) {
case 37:
box.style.left = box.offsetLeft - speed + "px";
break;
case 39:
box.style.left = box.offsetLeft + speed + "px";
break;
case 38:
box.style.top = box.offsetTop - speed + "px";
break;
case 40:
box.style.top = box.offsetTop + speed + "px";
break;
}
};
</script>
</body>
</html>
3.5 鼠标事件
属性 | 描述 |
---|---|
onclick | 当单击鼠标时运行脚本。 |
ondblclick | 当双击鼠标时运行脚本。 |
onmousedown | 当按下鼠标按钮时运行脚本。 |
onmouseup | 当松开鼠标按钮时运行脚本。 |
onmousemove | 当鼠标指针移动时运行脚本。 |
onmouseover | 当鼠标指针移至元素之上时运行脚本,不可以阻止冒泡。 |
onmouseout | 当鼠标指针移出元素时运行脚本,不可以阻止冒泡。 |
onmouseenter | 当鼠标指针移至元素之上时运行脚本,可以阻止冒泡。 |
onmouseleave | 当鼠标指针移出元素时运行脚本,可以阻止冒泡。 |
onmousewheel | 当转动鼠标滚轮时运行脚本。 |
onscroll | 当滚动元素的滚动条时运行脚本。 |
3.5.1 鼠标实现拖曳元素快
案例演示2:编写一个通用的拖拽元素函数,创建两个div,进行拖拽演示,要求兼容IE8、火狐、谷歌等主流浏览器
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div id="box1" style="width: 100px;height: 100px;background: red;position: absolute;"></div>
<div id="box2" style="width: 100px;height: 100px;background: green;position: absolute;"></div>
<!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
<script>
var box1 = document.getElementById("box1");
var box2 = document.getElementById("box2");
drag(box1);
drag(box2);
/*
* 提取一个专门用来设置拖拽的函数
* 参数:开启拖拽的元素
*/
function drag(obj) {
//当鼠标在被拖拽元素上按下时,开始拖拽
obj.onmousedown = function (event) {
// 解决事件的兼容性问题
event = event || window.event;
// 设置obj捕获所有鼠标按下的事件
/**
* setCapture():
* 只有IE支持,但是在火狐中调用时不会报错,
* 而如果使用chrome调用,它也会报错
*/
obj.setCapture && obj.setCapture();
// obj的偏移量 鼠标.clentX - 元素.offsetLeft
// obj的偏移量 鼠标.clentY - 元素.offsetTop
var ol = event.clientX - obj.offsetLeft;
var ot = event.clientY - obj.offsetTop;
// 为document绑定一个鼠标移动事件
document.onmousemove = function (event) {
// 解决事件的兼容性问题
event = event || window.event;
// 当鼠标移动时被拖拽元素跟随鼠标移动
// 获取鼠标的坐标
var left = event.clientX - ol;
var top = event.clientY - ot;
// 修改obj的位置
obj.style.left = left + "px";
obj.style.top = top + "px";
};
// 为document绑定一个鼠标松开事件
document.onmouseup = function () {
// 取消document的onmousemove事件
document.onmousemove = null;
// 取消document的onmouseup事件
document.onmouseup = null;
// 当鼠标松开时,取消对事件的捕获
obj.releaseCapture && obj.releaseCapture();
};
/*
* 当我们拖拽一个网页中的内容时,浏览器会默认去搜索引擎中搜索内容,
* 此时会导致拖拽功能的异常,这个是浏览器提供的默认行为,
* 如果不希望发生这个行为,则可以通过return false来取消默认行为,
* 但是这招对IE8不起作用
*/
return false;
};
}
</script>
</body>
</html>
3.5.2 拖曳元素进行身份验证
实现拖拽验证身份信息的思路是,将需要拖拽的元素设置为可拖拽(draggable),然后在拖拽开始、拖拽过程和拖拽结束三个阶段分别监听相关事件,处理事件响应。具体步骤如下:
在 HTML 中定义需要拖拽的元素和放置元素;其中,id 为 draggable 的 div 元素是需要被拖拽的元素,设置 draggable 属性为 true 表示该元素可拖拽;id 为 droppable 的 div 元素是需要放置的元素。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>拖拽验证身份信息</title>
<style>
#draggable {
width: 100px;
height: 100px;
background-color: #6aa84f;
color: #fff;
text-align: center;
line-height: 100px;
cursor: move;
}
#droppable {
width: 200px;
height: 200px;
border: 2px dashed #ccc;
margin-top: 20px;
}
#droppable.droppable-hover {
background-color: #ddd;
}
#message {
display: none;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: #6aa84f;
color: #fff;
text-align: center;
padding: 20px;
font-size: 18px;
border-radius: 10px;
box-shadow: 2px 2px 2px #ccc;
}
</style>
</head>
<body>
<div id="draggable" draggable="true">拖拽我</div>
<div id="droppable">放置在此处</div>
<div id="message">身份验证成功!</div>
<script>
const draggable = document.getElementById('draggable');
const droppable = document.getElementById('droppable');
const message = document.getElementById('message');
let isDragging = false;
draggable.addEventListener('dragstart', function(event) {
isDragging = true;
event.dataTransfer.setData('text/plain', 'identity');
});
droppable.addEventListener('dragenter', function(event) {
if (isDragging) {
droppable.classList.add('droppable-hover');
}
});
droppable.addEventListener('dragover', function(event) {
event.preventDefault();
});
droppable.addEventListener('dragleave', function(event) {
droppable.classList.remove('droppable-hover');
});
droppable.addEventListener('drop', function(event) {
event.preventDefault();
droppable.classList.remove('droppable-hover');
const draggedItem = event.dataTransfer.getData('text/plain');
if (draggedItem === 'identity') {
message.style.display = 'block';
}
});
</script>
</body>
</html>
其中,dragstart、drag、dragend 分别表示拖拽开始、拖拽过程和拖拽结束;dragenter、dragover、dragleave 和 drop 分别表示拖拽元素进入放置区域、在放置区域中移动、离开放置区域和放置拖拽元素到目标元素中。
需要注意的是,在 dragover 事件中需要调用 event.preventDefault(),防止浏览器默认行为,使得拖拽操作可以被放置到目标元素中。
3.6 媒体事件
通过视频(videos),图像(images)或音频(audio) 触发该事件。
属性 | 描述 |
---|---|
onabort | 当发生中止事件时运行脚本。 |
oncanplay | 当媒介能够开始播放但可能因缓冲而需要停止时运行脚本。 |
oncanplaythrough | 当媒介能够无需因缓冲而停止即可播放至结尾时运行脚本。 |
ondurationchange | 当媒介长度改变时运行脚本。 |
onemptied | 当媒介资源元素突然为空时(网络错误、加载错误等)运行脚本。 |
onended | 当媒介已抵达结尾时运行脚本。 |
onerror | 当在元素加载期间发生错误时运行脚本。 |
onloadeddata | 当加载媒介数据时运行脚本。 |
onloadedmetadata | 当媒介元素的持续时间以及其它媒介数据已加载时运行脚本。 |
onloadstart | 当浏览器开始加载媒介数据时运行脚本。 |
onpause | 当媒介数据暂停时运行脚本。 |
onplay | 当媒介数据将要开始播放时运行脚本。 |
onplaying | 当媒介数据已开始播放时运行脚本。 |
onprogress | 当浏览器正在取媒介数据时运行脚本。 |
onratechange | 当媒介数据的播放速率改变时运行脚本。 |
onreadystatechange | 当就绪状态(ready-state)改变时运行脚本。 |
onseeked | 当媒介元素的定位属性不再为真且定位已结束时运行脚本。 |
onseeking | 当媒介元素的定位属性为真且定位已开始时运行脚本。 |
onstalled | 当取回媒介数据过程中(延迟)存在错误时运行脚本。 |
onsuspend | 当浏览器已在取媒介数据但在取回整个媒介文件之前停止时运行脚本。 |
ontimeupdate | 当媒介改变其播放位置时运行脚本。 |
onvolumechange | 当媒介改变音量亦或当音量被设置为静音时运行脚本。 |
onwaiting | 当媒介已停止播放但打算继续播放时运行脚本。 |
3.7 其它事件以及概念补充
属性 | 描述 |
---|---|
onshow | 当<menu> 元素在上下文显示时触发。 |
ontoggle | 当用户打开或关闭 <details> 元素时触发。 |
事件是 Web 应用程序中最重要的交互机制之一。当用户与网页进行交互时(比如点击按钮、拖拽元素、滚动页面等),浏览器会触发相应的事件,并将事件传递给网页的 JavaScript 代码处理。事件的处理方式包括事件绑定、事件委派、事件解绑等。下面是一些与事件处理相关的常用概念的解释:
- 事件捕获(Event Capturing):事件从文档根节点开始往下传递到目标元素之前,会先经过文档根节点、HTML 元素、body 元素、父元素等节点,这个过程称为事件捕获。事件捕获的处理函数会在目标元素的事件处理函数之前被触发。
- 事件目标(Event Target):事件目标是指用户与之交互的元素。例如,当用户点击一个按钮时,该按钮就是事件目标。
- 事件冒泡(Event Bubbling):事件从目标元素开始往上冒泡到文档根节点之前,会经过目标元素的父元素、body 元素、HTML 元素、文档根节点等节点,这个过程称为事件冒泡。
事件冒泡的处理函数会在目标元素的事件处理函数之后被触发。
- 事件委派(Event Delegation):事件委派是一种利用事件冒泡机制,在父元素上绑定事件处理函数,而不是在子元素上绑定事件处理函数。当子元素触发事件时,事件会冒泡到父元素,由父元素上的事件处理函数处理。这种方式可以减少事件处理函数的数量,提高页面性能。
- 事件绑定(Event Binding):事件绑定是指将事件处理函数绑定到一个元素上,当该元素触发相应的事件时,该事件处理函数会被执行。事件绑定通常使用
addEventListener()
方法实现。 - 事件传播(Event Propagation):事件传播是指事件从目标元素开始往上冒泡到文档根节点或者往下传递到子元素。事件传播包括事件捕获、事件目标、事件冒泡三个阶段。
- 微软公司认为事件应该是由内向外传播,也就是当事件触发时,应该先触发当前元素上的事件,然后再向当前元素的祖先元素上传播,也就说事件应该在冒泡阶段执行。
- 网景公司认为事件应该是由外向内传播的,也就是当前事件触发时,应该先触发当前元素的最外层的祖先元素的事件,然后在向内传播给后代元素。
- 事件解绑(Event Unbinding):事件解绑是指将事件处理函数从一个元素上移除,该元素不再响应相应的事件。事件解绑通常使用
removeEventListener()
方法实现。
以上是与事件处理相关的一些常用概念的解释。在实际应用中,根据需要选择不同的事件处理方式可以使页面交互更加灵活和高效。
3.7.1 阻止超链接跳转
代码演示:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
#div1 {
width: 200px;
height: 200px;
background: pink;
}
#div2 {
width: 100px;
height: 100px;
background: coral;
}
</style>
</head>
<body>
<a href="https://www.baidu.com" id="a">打开百度,你就知道!</a>
<!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
<script>
var a = document.getElementById("a");
// 为a绑定单击事件
a.onclick = function () {
stopDefault();
};
// 阻止浏览器的默认行为
function stopDefault(event) {
if (event && event.preventDefault) {
// 阻止默认浏览器动作(W3C)
event.preventDefault();
} else {
// IE中阻止函数器默认动作的方式
window.event.returnValue = false;
}
return false;
}
</script>
</body>
</html>
04 BOM树
4.1 BOM模型
浏览器对象模型(BOM)可以使我们通过JS来操作浏览器,在BOM中为我们提供了一组对象,用来完成对浏览器的操作,常见的BOM对象如下:
- Window:代表的是整个浏览器的窗口,同时window也是网页中的全局对象
- Navigator:代表的当前浏览器的信息,通过该对象可以来识别不同的浏览器
- Location:代表当前浏览器的地址栏信息,通过Location可以获取地址栏信息,或者操作浏览器跳转页面
- History:代表浏览器的历史记录,可以通过该对象来操作浏览器的历史记录,由于隐私原因,该对象不能获取到具体的历史记录,只能操作浏览器向前或向后翻页,而且该操作只在当次访问时有效
- Screen:代表用户的屏幕的信息,通过该对象可以获取到用户的显示器的相关的信息
4.2 常用的一些脚本操作
操作 | 描述 |
---|---|
window.open() | 打开新窗口或标签页。 |
window.close() | 关闭当前窗口或标签页。 |
window.location.href | 获取或设置当前窗口的 URL。 |
window.history.back() | 返回上一页。 |
window.history.forward() | 前往下一页。 |
window.navigator.userAgent | 获取用户代理信息。 |
window.navigator.cookieEnabled | 判断浏览器是否启用 cookie。 |
window.screen.width | 获取屏幕宽度。 |
window.screen.height | 获取屏幕高度。 |
window.document.cookie | 获取或设置当前窗口的 cookie。 |
注意:上述表格中仅列出了常用的一些操作,具体的应用还需要根据具体需求进行选择。剩下的平时也不太用的上,这里不做赘述。