北京做网站开发公司电话,苏州营销型网站制作多少钱,专科计算机哪个专业最吃香,一般建一个外贸网站多少钱1. DOM
1.1 基本概念
DOM#xff0c;全称 Document Object Model#xff0c;即文档对象模型。它是 Web 上最常用的 API 之一#xff0c;是加载在浏览器中的文档模型#xff0c;可以将文档表示为节点树#xff08;或称 DOM 树#xff09;#xff0c;其中每个节点代表文…1. DOM
1.1 基本概念
DOM全称 Document Object Model即文档对象模型。它是 Web 上最常用的 API 之一是加载在浏览器中的文档模型可以将文档表示为节点树或称 DOM 树其中每个节点代表文档的一部分例如元素、文本字符串或注释
它允许在浏览器中运行的代码访问文档中的每个节点并与之交互。可以创建、移动和更改节点还可以将事件监听器添加到节点并在特定事件发生时触发
简单来说DOM就是JS操作网页的接口是JS和网页之间的桥梁。 W3C官方解释DOM是一种编程接口或平台它允许程序或脚本如JavaScript动态地访问和更新文档的内容、结构和样式 1.2 DOM的作用
DOM的主要作用是将网页转为一个JS对象从而可以用JS对网页进行各种操作如
1. 通过DOM使用JS获取、修改、创建、删除文档中得元素、元素属性、文本等内容
2. 通过DOM使用JS修改元素得样式、类名、事件处理程序等来改变页面的外观和行为
3. DOM提供了事件模型允许在页面中注册事件监听器并对用户的交互做出响应 1.3 DOM的形成
DOM的形成过程主要涉及到浏览器对HTML文档的解析和构建
1. 加载HTML文档用户输入URL向服务器请求资源获取到HTML文档
2. 解析HTML文档浏览器按照一定语法、规则解析HTML文档。并将其转换为一个树结构的对象即DOM树
3. 构建DOM树解析HTML文档的过程中浏览器会根据文档中的元素、属性和文本等内容构建DOM树。DOM树的每个节点都代表文档中的一个元素、属性或文本等内容
4. 提供访问接口一旦DOM树构建完成浏览器就会提供一系列的方法和属性来访问和操作DOM树中的节点和对象
提问为什么需要将HTML转成DOM树来提供操作网页的接口
因为HTML文档是字符串类型的而DOM树是可遍历的树结构对象相比于处理超长的字符串对象更为容易处理。 参考浏览器渲染基本原理-CSDN博客 1.4 DOM的节点类型
DOM中总共有12种节点类型它们都继承自一种基本类型。其中最常用的节点类型有
1. Document节点代表整个文档是DOM树的根节点
2. Element节点代表HTML文档中的标签元素如div、span等
3. Text节点代表元素中的文本内容
4. Comment节点代表HTML文档中的注释内容 1.5 JS获取DOM节点
DOM是供JS操作网页元素的API通过其提供的方法可以访问到网页元素对应的DOM树节点
1. ID获取这是获取单个元素节点Element的最快方式因为ID在HTML文档中应该是唯一的
let element document.getElementById(box)
2. 类名获取这会返回一个元素节点集合即HTMLCollection。即使只有一个元素匹配。
let elements document.getElementsByClassName(myClassName)
// 可以通过索引访问如elements[0]
// 也可以通过ID或name访问如element[box]box即元素ID
// 但第二种方法不是所有浏览器都支持3. 标签名获取会返回一个元素节点集合。
let elements document.getElementsByTagName(div)
4. name属性获取会返回一个元素节点集合。并不常用
let element document.getElementsByName(name)
5. css选择器获取
①document.querySelector()返回匹配选择器的第一个节点
let element document.querySelector(.className)
②document.querySelectorAll()返回所有匹配选择器的节点集合NodeList
let element document.querySelectorAll(.className)
注意NodeList和HTMLCollection是存在一定区别的
区别NodeListHTMLCollection节点类型 可包含几乎所有类型的节点。 如元素节点Element、文本节点Text、注释节点Comment等 只能包含元素节点Element实时性 可以是动态的也可以是静态的。 如childNodes属性返回的NodeList是动态的 而querySelectorAll方法返回的通常是静态的 通常也是动态的当文档中的元素发生变化时HTMLCollection会自动更新以反映文档的变化。访问方式通过索引来访问集合中的节点如elements[index] 可通过索引访问节点 还可通过元素的name或id属性值来快速访问元素节点注意不是所有浏览器都支持
6. 事件目标获取在事件处理函数中可以通过事件对象event的target属性来获取触发事件的元素节点。
document.querySelector(.className).addEventListener(click, function (event) {let clickedElement event.target})
7. 除了上述这些方法DOM API还提供了document.forms和document.images等诸多方法属性来获取DOM节点。感兴趣着建议查阅相关官方文档 1.6 JS操作DOM节点
访问到DOM节点后我们可以使用DOM API提供的一些属性和方法来修改节点属性以达到动态的修改网页的内容和结构的效果。下面是常用的DOM节点操作方式
1.61 修改节点属性
1. 修改HTML内容
let element document.querySelector(#box)
element.innerHTML pNew content/p
2. 修改文本内容
let element document.querySelector(#box)
element.textContent New text content
3. 修改属性值如直接修改并覆盖该元素节点的 所有 class 属性值
let element document.querySelector(#box)
element.setAttribute(class, newClassName) 1.62 样式操作
1. 修改CSS样式
let element document.querySelector(#box)
element.style.color red
element.style.fontSize 20px
2. 添加/移除类
let element document.querySelector(#box)
element.classList.add(newClassName)
element.classList.remove(newClassName)
3. 切换类
let element document.querySelector(#box)
element.classList.toggle(className); 1.63 节点的增删
1. 创建新节点
//创建新节点
let newElement document.createElement(div)
newElement.textContent New text content
2. 插入新节点
let element document.querySelector(#box)//作为子节点插入
element.appendChild(newElement)
//作为兄弟节点插入
//element.parentNode 是element节点的父节点
//insertBefore 将newElement插入到 element.nextSibling之前
//element.nextSibling 是element节点的下一个相邻节点如果没有那就是null
element.parentNode.insertBefore(newElement, element.nextSibling)
// 所有如果element 没有下一个相邻节点newElement会被插到parentNode的末尾
3. 删除节点
let element document.querySelector(#box)
// 访问父节点使用removeChild删除子节点
element.parentNode.removeChild(element) 1.64 事件处理
1. 添加事件监听器
let element document.querySelector(#box)
element.addEventListener(click, function () {alert(Element clicked!)
})
2. 移除事件监听器
let element document.querySelector(#box)
function handleClick() {alert(Element clicked!)
}
element.addEventListener(click, handleClick)
element.removeEventListener(click, handleClick) 1.65 综合案例 以下是一个综合示例展示了如何动态创建一个列表并添加点击事件来处理列表项的点击
div idcontainer/div
script// 获取容器 元素节点let container document.getElementById(container)// 创建列表项for (let i 1; i 5; i) {let listItem document.createElement(div)listItem.textContent Item ilistItem.className list-item// 添加点击事件监听器listItem.addEventListener(click, function () {alert(You clicked on: this.textContent)})// 将列表项作为容器子元素添加container.appendChild(listItem)}
/script 2. 事件
2.1 基本概念
早期的互联网受限于网络带宽和服务器处理能力网页的响应速度往往非常慢。为了提高用户体验开发人员尝试将原本需要在服务器端处理的任务部分前移到客户端让客户端通过JS来实现以减少对服务器的依赖。如表单信息的格式验证等。
随着这种客户端处理策略的发展浏览器开始支持越来越多的事件类型。
事件就是用户和网页交互时由浏览器或渲染引擎根据用户的操作如点击、输入、移动鼠标等或某些系统事件如网页加载、调整窗口的等触发的行为。
这些行为通常与函数结合使用当触发这些行为时浏览器就会执行这些 “事件处理函数” 来响应事件由此我们可以概括出事件就是一种 “ 触发——响应 ”的机制。
同时一个完整的事件机制必须满足三个要素举例说明
button idbtubtu/button
let btu window.document.querySelector(#btu)
btu.addEventListener(click, function () {console.log(触发事件处理函数)// ..........
})事件源EventTarget也就是触发对象比如上面的button事件类型type比如上面的单击事件click事件处理程序比如上面的function
事件和DOM的关系
由用户触发的事件通常是注册在DOM节点上的所以本质上这类事件就是由DOM产生的资源。 而由系统触发的事件如resize这种窗口大小改变时触发的事件通常是注册在window对象上的。注意DOM节点被包含在document内而document被包含在window对象内。 2.2 事件绑定
1. 在HTML/XML标签中直接绑定。通常用于简单的场景如onclick、onchange等并直接指定处理函数名称
button onclickalert(你单击了一次)按钮/button
2. 在JS代码中给DOM绑定通过JS访问DOM节点并为其设置事件处理函数。优点是与HTML标签的分离使文档结构更加清晰便于管理和开发。
function handleClick() {alert(单击了一下)
}
document.getElementById(myButton).onclick handleClick
3. 使用事件监听函数注册事件。它提供了更灵活的事件处理机制能够为多个对象注册相同的事件处理函数也可以为同一个对象注册多个事件处理函数还可以在捕获阶段或冒泡阶段详情见下方事件流处理事件并且可以绑定多个事件处理函数。
// 语法
element.addEventListener(String type, Function listener, boolean useCapture)
type事件类型
listener事件处理函数
useCapturetrue指定的listener在捕获阶段触发false指定listener在冒泡阶段触发
-----------------------------------------------------------------------
document.getElementById(myButton).addEventListener(click,function () {alert(单击了一下)},false
)
4. 事件解绑
即移除绑定的事件处理函数防止事件被重复触发或造成内存泄漏等问题。事件解绑通常与事件绑定相对应如通过addEventListener注册的事件可以用removeEventListener来移除对应的侦听器
let btu1 document.getElementById(btu1)
//单击一次触发处理函数后解绑该处理函数注意处理函数不能匿名
btu1.addEventListener(click, function ok() {alert(单击了一下)this.removeEventListener(click, ok, false)
})//当临时注册一个事件时可以在处理完毕之后迅速删除它这样能够节省系统资源
注意事件的处理函数最好不要使用箭头函数 否则处理函数内this不会指向源对象 2.3 事件流
1. 基本概念
事件流就是多个节点对象同一事件进行相应的先后顺序一般有冒泡和捕获两种模式。通常指由于嵌套元素节点注册了相同的事件并由子元素触发时引起其上级元素触发相同事件
div idboxbutton idbtubtu/button
/div
scriptlet btu document.querySelector(#btu)let box document.querySelector(#box)function check(e) {// e.target就是触发该处理函数的节点console.log(trigger by, e.target, and element is, this)}btu.addEventListener(click, check)box.addEventListener(click, check)
/script
当我们点击button时控制台输出 会发现由button触发的事件冒泡到了它的上级元素节点上 2. 事件冒泡
是事件流的默认模式在DOM结构中当一个元素被触发事件时该事件会沿着DOM树向上传播直到根节点或遇到某个节点阻止了事件的传播。这种传播方式称为事件冒泡。如 1.基本概念 中所展示的情况。 2. 事件捕获
与事件冒泡相反事件捕获是事件从根节点向目标元素传播的过程。在事件捕获阶段事件会先触发祖先元素的事件处理程序然后再触发目标元素的事件处理程序。如下
我们将 1.基本概念 中的box注册的单击事件由默认的冒泡模式改为捕获模式
box.addEventListener(click, check, true)
此时再点击button控制台会输出 会发现由button触发的单击事件却是button的上级元素box先一步调用单击事件处理函数。
如果不好理解那么接着往下看 3. 事件处理顺序
事件由某一DOM节点触发经历下面三个阶段
① 捕获阶段事件从文档的根节点document向目标节点传播如果绑定了捕获阶段的事件处理函数则在这个阶段执行。
② 目标阶段事件到达目标节点如果为目标节点绑定了事件处理函数则在这个阶段执行。
③ 冒泡阶段事件从目标节点向文档的根节点传播如果绑定了冒泡阶段的事件处理函数则在这个阶段执行。
所以1.基本概念 中的事件顺序应该是
1btu节点触发了单击事件click浏览器从根节点document开始向btu节点遍历DOM树发现了btu的上级元素box节点 也注册了单击事件但默认了在冒泡阶段触发所以不执行处理函数check
2浏览器找到btu节点开始触发处理函数
3浏览器从btu节点开始向根节点document遍历并执行box节点 注册的冒泡阶段单击事件即执行check函数 4. 事件混合
一句话概括多重嵌套元素节点注册相同事件并分别指定了在冒泡阶段或捕获阶段执行 2.4 事件委托
事件委托是一种利用事件冒泡原理的技术它通过将事件监听器绑定到父元素或祖先元素上而不是直接绑定到目标元素上来实现对多个子元素的事件处理。这种方式可以减少事件监听器的数量提高性能并简化代码结构。 2.5 阻止事件传播
即阻止事件冒泡/或捕获阶段的事件传播。某些场景我们不希望子元素节点触发的事件会传播到上级元素节点这可以通过以下几种方式实现
1. stopPropagation()方法阻止捕获和冒泡阶段中当前事件的进一步传播即传播到父元素。这个方法只会阻止事件的冒泡阶段不会阻止捕获阶段除非在捕获阶段调用
div idboxbutton idbtubtu/button
/div
scriptlet btu document.querySelector(#btu)let box document.querySelector(#box)function check() {event.stopPropagation()console.log(trigger by, event.target, and element is, this)}btu.addEventListener(click, check)//捕获阶段调用box.addEventListener(click, check, true)// 冒泡阶段调用box.addEventListener(click, function () {console.log(this)})
/script
点击点击button只会触发btu的处理函数控制台输出 box注册在冒泡阶段触发的处理函数被btu注册的处理函数阻止事件传播到上级元
box注册在捕获阶段触发的处理函数被box自己注册的处理函数阻止事件传播到这里
注意stopPropagation()方法不能防止任何默认行为的发生例如对链接的点击仍会被处理。 2. preventDefault()方法阻止事件的默认行为。但此事件还是继续传播。它通常用于阻止表单提交submit的默认行为
form idmyFormlabel forusernameUsername:/labelinput typetext idusername nameusername required /button typesubmitSubmit/button
/formlet form document.getElementById(myForm)
form.addEventListener(submit, function (event) {// 阻止表单的默认提交行为event.preventDefault()// ......在这里执行自定义逻辑比如验证表单字段
})
因为JS表单的submit提交事件默认会直接向服务器直接提交数据但通常我们需要在提交之前对表单数据进行简单的格式验证当格式正确后再发送到服务器。 3. event.stopImmediatePropagation()不仅阻止事件的进一步传播还阻止监听同一事件的其他事件监听器被调用
button idbtu/button
scriptconst btu document.querySelector(#btu)btu.addEventListener(click, function () {console.log(button注册的第一个监听函数)})btu.addEventListener(click, function () {console.log(button注册的第二个监听函数)// // 阻止事件冒泡并且阻止btu上绑定的其他 click 事件的事件监听函数的执行。event.stopImmediatePropagation()})btu.addEventListener(click, function () {console.log(button注册的第三个监听函数)// 该监听函数在stopImmediatePropagation后故不会被执行})document.addEventListener(click, function () {console.log(给根节点注册的click监听函数)//btu 的 click 事件没有向上冒泡该函数不会被执行})
/script
注意stopImmediatePropagation的阻止事件进一步传播是按照事件处理顺序来阻止的。
如果将给根节点注册的click事件处理函数设置为在捕获阶段执行那么单击button依旧会执行该处理函数。
document.addEventListener(click,function () {console.log(给根节点注册的click监听函数)//该函数会顺利执行应为事件处理顺序在stopImmediatePropagation之前//....//如果在捕获阶段使用stopImmediatePropagation阻止事件传播//那么后续btu上注册的都不会执行},true) 2.6 事件类型
常见的事件类型包括
事件类型事件名称触发时机作用举例鼠标事件click用户单击元素触发常用于按钮点击、链接跳转等场景dblclick双击元素时触发常用于打开文件、放大图片等操作mouseover当鼠标指针移动到元素上方时触发常用于显示悬停效果、提示信息等mouseout当鼠标指针移出元素时触发常用于处理元素移出时的清理操作等mousemove当鼠标指针在元素上移动时持续触发常用于拖拽操作、鼠标轨迹跟踪等mousedown当按下鼠标按钮时触发常用于处理按钮点击的开始阶段mouseup当释放鼠标按钮时触发常用于处理按钮点击的结束阶段键盘事件keydown按下键盘上的任意键时触发常用于实现键盘快捷键、搜索框自动完成等功能keyup释放键盘上的任意键时触发常用于检测按键释放后的操作表单事件submit当表单提交时触发常用于验证表单数据、阻止默认提交行为、异步提交等change当表单元素的值发生变化时触发如输入框、选择框的值改变常用于实时搜索、过滤数据、更新页面内容等focus当元素获得焦点时触发如输入框被点击或Tab键选中常用于改变输入框的样式、显示/隐藏帮助文本或提示信息等blur当元素失去焦点时触发常用于处理元素失去焦点后的操作如验证输入内容窗口事件load当页面或资源如图片、CSS文件等完全加载完成时触发常用于初始化页面内容、加载数据等unload当页面卸载时触发通常用于清理资源或执行最后的操作常用于清理资源、保存状态等resize当浏览器窗口大小改变时触发常用于响应式设计、调整页面布局等scroll当页面滚动时触发常用于创建滚动效果、懒加载图片等
注意 如果需要在事件监听器addEventListener以外的地方使用如HTML中和JS赋值绑定中2.2事件绑定中的1和2需要使用onevent的格式来声明事件 2.7 自定义事件
2.71 基本概念
JS内置的DOM事件通常是基于Event接口或其子类实现的。Event接口表示在EventTarget如元素文档窗口等上出现的事件。除了这些内置事件如鼠标事件、键盘事件等我们也可以通过事件接口或者说构造函数来自定事件。 2.72 Event
1. Event构造函数用于创建一个新的事件对象 Event。如
let event new Event(type, options)type 事件类型如 click 这样的的字符串
options可选 接受以下字段bubbles可选默认值为 false表示该事件是否冒泡。cancelable可选默认值为 false表示该事件能否被取消即是否可以调用 preventDefault() 来阻止默认行为注意别与移除事件监听器混淆composed可选默认值为 false指示事件是否会在影子 DOM 根节点之外触发侦听器,本篇不作详细介绍
使用举例创建一个支持冒泡且不能被取消的 look 事件。
//创建新的事件
const ev new Event(look, { bubbles: true, cancelable: false })
// 监听自定义事件
btu.addEventListener(look, function () {console.log(btu触发look)
})
document.addEventListener(look, function () {console.log(look冒泡到document)
})
btu.addEventListener(click, function () {btu.dispatchEvent(ev)//自定义的事件使用dispatchEvent来触发
})
//点击button顺序输出btu触发look look冒泡到document
2. Event构造函数作为JS内置对象的一种提供了许多事件相关的属性和方法。而事件对象就利用这是实例属性和方法来储存或操作事件相关的信息包括本次触发事件的事件类型、事件目标、触发元素等。
我们查看1中定义的初始ev对象以及btu触发look事件后的ev对象
console.dir(ev)
btu.addEventListener(look, function () {console.dir(ev)console.log(ev event)//true同一引用
})
控制台:
2.72 event的常用属性/方法
1. 常用属性
属性介绍type事件类型bubblesEvent实例只读属性表示当前事件是否会进行冒泡。只能在event创建时设置cancelableEvent实例只读属性表示当前事件是否能取消。只能在event创建时设置isTrusted只读属性无法修改自定义事件或被重定义的事件为false内置事件为truetarget事件最初发生的元素用以确定用户与哪个元素进行了交互currentTarget当前事件监听器所绑定的元素即使事件是从子元素触发的currentTarget始终指向绑定事件处理函数的元素clientX 和 clientY获取鼠标相对于浏览器窗口左上角的坐标。常用于确定鼠标在窗口中的位置key 在键盘事件中key属性返回按下的具体字符button在鼠标事件中表示按下了哪个鼠标按钮。0左键、1滚轮、2右键key 在键盘事件中key属性返回按下的具体字符defaultPrevented只读属性示当前事件是否调用了preventDefault()方法从而阻止了浏览器的默认行为。
2. 常用方法
方法介绍preventDefault()阻止事件的默认行为。例如点击链接时浏览器会跳转到链接地址使用preventDefault()可以阻止这一行为stopPropagation()阻止事件冒泡即阻止事件从子元素向父元素传递stopImmediatePropagation()除了阻止事件冒泡外还会阻止当前元素上其他同类型事件处理程序的执行 2.73 特殊的自定义事件
观察“2.72 event的常用属性/方法” 和 “2.72 Event 中对ev对象的检查 ”会发现某些属性在ev上并不存在。这是为什么呢
在 “2.71基本概念” 中提到 JS内置的DOM事件通常是基于Event接口或其子类实现的。Event是基层事件接口而它的子类接口继承了Event的部分属性同时新增了自己持有的某属性或方法。
如键盘事件如果我们要自定义一个键盘事件KeyboardEvent构造函数
input typetext idmyInput placeholder在这里输入... /
p idoutput/p
script
//DOMContentLoaded事件文档被加载和解析并且 DOM 被完全构造时触发
//但链接的资源例如图像、样式表和子框架可能尚未被加载document.addEventListener(DOMContentLoaded, (event) {const input document.getElementById(myInput)const output document.getElementById(output)// 监听输入框的键盘事件input.addEventListener(keydown, (event) {output.textContent 你按下了键: ${event.key}})// 创建一个自定义的键盘事件function triggerCustomKeyEvent(key) {const event new KeyboardEvent(keydown, {key: key, // 按键的值例如 a, Enter 等code: key, // 物理按键的代码bubbles: true, // 冒泡cancelable: true // 是否可以调用 preventDefault() 来阻止默认行为})// 触发自定义事件input.dispatchEvent(event)}// 在页面加载后的2秒钟触发一个自定义的 a 键按下事件setTimeout(() {triggerCustomKeyEvent(a) // a}, 2000)})
/script
所以如果你想定义一些特别的自定义事件键盘事件鼠标事件等就需要使用KeyboardEventMouseEvent 等Event的子类构造函数来实现。
对Event的子类有过一点了解后我们对2.72Event自定义事件进行补充
对于我们自己的全新事件类型更加推荐使用Event的子类CustomEvent它与Event技术上基本一样但在第二个参数options中我们可以为添加一个初始化事件时传递的任何信息
h1 idelemHello for John!/h1
script// 事件附带给处理程序的其他详细信息elem.addEventListener(hello, function (event) {alert(event.detail.name)})elem.dispatchEvent(new CustomEvent(hello, {detail: { name: John }}))
/script 请注意随着JavaScript标准的不断发展新的事件属性和方法可能会被引入而一些旧的或不再常用的可能会被废弃或移除。因此对自定义事件相关感兴趣者建议查阅最新的ECMAScript规范或JavaScript文档以获取最准确的信息。 若有错误或描述不当的地方烦请评论或私信指正万分感谢