一.Web APIs先容
Web APIs 是浏览器扩展的功能。
ECMAScript 运行在浏览器中然后再团结 Web APIs 才是真正的 JavaScript,Web APIs 的核心是 DOM 和 BOM。
二.DOM
1.DOM先容
DOM通过js操作html--网页特效和交互
DOM(Document Object Model)是将整个 HTML 文档的每一个标签元素视为一个对象,这个对象下包罗了许多的属性和方法,通过操作这些属性或者调用这些方法实现对 HTML 的动态更新,为实现网页特效以及用户交互提供技术支持。
简言之 DOM 是用来动态修改 HTML 的,其目的是开发网页特效及用户交互。
DOM 树
如下图所示,将 HTML 文档以树状结构直观的表现出来,我们称之为文档树或 DOM 树,文档树直观的表现了标签与标签之间的关系。
DOM 节点
节点是文档树的构成部门,每一个节点都是一个 DOM 对象,主要分为元素节点、属性节点、文本节点等。
【元素节点】其实就是 HTML 标签,如上图中 head、div、body 等都属于元素节点。
【属性节点】是指 HTML 标签中的属性,如上图中 a 标签的 href 属性、div 标签的 class 属性。
【文本节点】是指 HTML 标签的文字内容,如 title 标签中的文字。
【根节点】特指 html 标签。
其它...
document
document 是 JavaScript 内置的专门用于 DOM 的对象,该对象包罗了多少的属性和方法,document 是学习 DOM 的核心。
- <script>
- // document 是内置的对象
- // console.log(typeof document);
-
- // 1. 通过 document 获取根节点
- console.log(document.documentElement); // 对应 html 标签
-
- // 2. 通过 document 节取 body 节点
- console.log(document.body); // 对应 body 标签
-
- // 3. 通过 document.write 方法向网页输出内容
- document.write('Hello World!');
- </script>
复制代码 上述列举了 document 对象的部门属性和方法,我们先对 document 有一个团体的熟悉。
2.获取DOM对象
querySelector
满意条件的第一个元素
可以直接操作属性
querySelectorAll
满意条件的元素聚集 返回伪数组
不可以直接操作属性--需要遍历得到每一个元素后操作属性
了解其他方式
getElementById
getElementsByTagName
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>DOM - 查找节点</title>
- </head>
- <body>
- <h3>查找元素类型节点</h3>
- <p>从整个 DOM 树中查找 DOM 节点是学习 DOM 的第一个步骤。</p>
- <ul>
- <li>元素</li>
- <li>元素</li>
- <li>元素</li>
- <li>元素</li>
- </ul>
- <script>
- const p = document.querySelector('p') // 获取第一个p元素
- const lis = document.querySelectorAll('li') // 获取第一个p元素
- </script>
- </body>
- </html>
复制代码 总结:
- document.getElementById 专门获取元素类型节点,根据标签的 id 属性查找
- 恣意 DOM 对象都包罗 nodeType 属性,用来检检测节点类型
3.操作元素内容
通过修改 DOM 的文本内容,动态改变网页的内容。
innerText
innerText 将文本内容添加/更新到恣意标签位置,文本中包罗的标签不会被解析。
- <script>
- // innerText 将文本内容添加/更新到任意标签位置
- const intro = document.querySelector('.intro')
- // intro.innerText = '嗨~ 我叫李雷!'
- // intro.innerText = '<h4>嗨~ 我叫李雷!</h4>'
- </script>
复制代码 innerHTML
innerHTML 将文本内容添加/更新到恣意标签位置,文本中包罗的标签会被解析。
- <script>
- // innerHTML 将文本内容添加/更新到任意标签位置
- const intro = document.querySelector('.intro')
- intro.innerHTML = '嗨~ 我叫韩梅梅!'
- intro.innerHTML = '<h4>嗨~ 我叫韩梅梅!</h4>'
- </script>
复制代码 总结:如果文本内容中包罗 html 标签时保举使用 innerHTML,否则发起使用 innerText 属性。
4.常用属性修改(.src,.width,.alt)
直接能过属性名修改,最简洁的语法
- <script>
- // 1. 获取 img 对应的 DOM 元素
- const pic = document.querySelector('.pic')
- // 2. 修改属性
- pic.src = './images/lion.webp'
- pic.width = 400;
- pic.alt = '图片不见了...'
- pic.title="hahahah"
- </script>
复制代码 5.样式属性修改
style 属性操作CSS
应用【修改样式】,通过修改行内样式 style 属性,实现对样式的动态修改。
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>练习 - 修改样式</title>
- </head>
- <body>
- <div class="box">随便一些文本内容</div>
- <script>
- // 获取 DOM 节点
- const box = document.querySelector('.intro')
- box.style.color = 'red'
- box.style.width = '300px'
- // css 属性的 - 连接符与 JavaScript 的 减运算符
- // 冲突,所以要改成驼峰法
- box.style.backgroundColor = 'pink'
- </script>
- </body>
- </html>
复制代码 通过元素节点获得的 style 属性自己的数据类型也是对象,如 box.style.color、box.style.width 分别用来获取元素节点 CSS 样式的 color 和 width 的值。
操作类名(className) 操作CSS
如果修改的样式比较多,直接通过style属性修改比较繁琐,我们可以通过借助于css类名的形式。
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>练习 - 修改样式</title>
- <style>
- .pink {
- background: pink;
- color: hotpink;
- }
- </style>
- </head>
- <body>
- <div class="box">随便一些文本内容</div>
- <script>
- // 获取 DOM 节点
- const box = document.querySelector('.intro')
- // 修改类名--新值换旧值--覆盖
- box.className = 'pink'
- // 两个类名--保留之前的类名
- box.className="box pink"
- </script>
- </body>
- </html>
复制代码 留意:
1.由于class是关键字, 所以使用className去取代
2.className是使用新值换旧值, 如果需要添加一个类,需要生存之前的类名
通过 classList 操作类控制CSS
为了解决className 容易覆盖以前的类名,我们可以通过classList方式追加和删除类名
- <!DOCTYPE html>
- <html lang="en">
-
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Document</title>
- <style>
- div {
- width: 200px;
- height: 200px;
- background-color: pink;
- }
-
- .active {
- width: 300px;
- height: 300px;
- background-color: hotpink;
- margin-left: 100px;
- }
- </style>
- </head>
-
- <body>
-
- <div class="one"></div>
- <script>
- // 1.获取元素
- // let box = document.querySelector('css选择器')
- let box = document.querySelector('div')
- // add是个方法 添加--追加--类名不加点,并且是字符串
- box.classList.add('active')
- // remove() 移除 类
- box.classList.remove('one')
- // 切换类--有就删掉--没有加上
- box.classList.toggle('one')
- //判断是否包含某个类,如果有则返回true,么有则返回false
- box.classList.contains('one') //true
- </script>
- </body>
-
- </html>
复制代码 6.操作表单元素属性(.value,.type,disable)
表单许多情况,也需要修改属性,好比点击眼睛,可以看到暗码,本质是把表单类型转换为文本框
正常的有属性有取值的跟其他的标签属性没有任何区别
获取 OM对象.属性名
设置 OM对象.属性名= 新值
- <!DOCTYPE html>
- <html lang="en">
-
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Document</title>
-
- </head>
-
- <body>
- <input type="text" value="请输入">
- <button disabled>按钮</button>
- <input type="checkbox" name="" id="" class="agree">
- <script>
- // 1. 获取元素
- let input = document.querySelector('input')
- // 2. 取值或者设置值 得到input里面的值可以用 value
- // console.log(input.value)
- input.value = '小米手机'
- input.type = 'password'
-
- // 2. 启用按钮
- let btn = document.querySelector('button')
- // disabled 不可用 = false 这样可以让按钮启用
- btn.disabled = false
- // 3. 勾选复选框
- let checkbox = document.querySelector('.agree')
- checkbox.checked = false
- </script>
- </body>
-
- </html>
复制代码 7.自定义属性(data-自定义属性)
尺度属性: 标签天生自带的属性 好比class id title等, 可以直接使用点语法操作好比: disabled、checked、selected
自定义属性:
在html5中推出来了专门的data-自定义属性
在标签上一律以data-开头
在DOM对象上一律以dataset对象方式获取
- <!DOCTYPE html>
- <html lang="en">
-
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Document</title>
-
- </head>
-
- <body>
- <div data-id="1"> 自定义属性 </div>
- <script>
- // 1. 获取元素
- let div = document.querySelector('div')
- // 2. 获取自定义属性值
- console.log(div.dataset.id)
-
- </script>
- </body>
-
- </html>
复制代码 9.变乱
变乱是编程语言中的术语,它是用来描述程序的行为或状态的,一旦行为或状态发生改变,便立刻调用一个函数。
例如:用户使用【鼠标点击】网页中的一个按钮、用户使用【鼠标拖拽】网页中的一张图片
变乱监听(addEventListener )
团结 DOM 使用变乱时,需要为 DOM 对象添加变乱监听,等待变乱发生(触发)时,便立刻调用一个函数。
addEventListener 是 DOM 对象专门用来添加变乱监听的方法,它的两个参数分别为【变乱类型】和【变乱回调】
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>事件监听</title>
- </head>
- <body>
- <h3>事件监听</h3>
- <p id="text">为 DOM 元素添加事件监听,等待事件发生,便立即执行一个函数。</p>
- <button id="btn">点击改变文字颜色</button>
- <script>
- // 1. 获取 button 对应的 DOM 对象
- const btn = document.querySelector('#btn')
-
- // 2. 添加事件监听
- btn.addEventListener('click', function () {
- console.log('等待事件被触发...')
- // 改变 p 标签的文字颜色
- let text = document.getElementById('text')
- text.style.color = 'red'
- })
-
- // 3. 只要用户点击了按钮,事件便触发了!!!
- </script>
- </body>
- </html>
复制代码 完成变乱监听分成3个步骤:
获取 DOM 元素
通过 addEventListener 方法为 DOM 节点添加变乱监听
等待变乱触发,如用户点击了某个按钮时便会触发 click 变乱类型
变乱触发后,相对应的回调函数会被实行
大白话描述:所谓的变乱无非就是找个机会(变乱触发)调用一个函数(回调函数)。
排除变乱接听(removeEventListener)
- function fn(){
- alert("点击了")
- }
- // 事件监听方法
- btn.addEventListener('click',fn)
- // 事件移除方法
- btn.removeEventListener('click',fn)
复制代码 变乱类型(click ...)
click 译成中文是【点击】的意思,它的含义是监听(等着)用户鼠标的单击操作,除了【单击】还有【双击】dblclick
- <script>
- // 双击事件类型
- btn.addEventListener('dblclick', function () {
- console.log('等待事件被触发...');
- // 改变 p 标签的文字颜色
- const text = document.querySelector('.text')
- text.style.color = 'red'
- })
-
- // 只要用户双击击了按钮,事件便触发了!!!
- </script>
复制代码 结论:【变乱类型】决定了变乱被触发的方式,如 click 代表鼠标单击,dblclick 代表鼠标双击。
变乱处理程序
addEventListener 的第2个参数是函数,这个函数会在变乱被触发时立刻被调用,在这个函数中可以编写恣意逻辑的代码,如改变 DOM 文本颜色、文本内容等。
- <script>
- // 双击事件类型
- btn.addEventListener('dblclick', function () {
- console.log('等待事件被触发...')
-
- const text = document.querySelector('.text')
- // 改变 p 标签的文字颜色
- text.style.color = 'red'
- // 改变 p 标签的文本内容
- text.style.fontSize = '20px'
- })
- </script>
复制代码 结论:【变乱处理程序】决定了变乱触发后应该实行的逻辑。
解绑变乱
- // 解绑事件
- const btn = document.querySelector(".btn")
- btn.onclick=function(){
- console.log("1222222")
- }
- // 解绑事件
- btn.onclick=null
- //匿名函数无法被解绑
- btn.addEventListener("click",function(e){
- console.log("123")
- })
复制代码 案例
JavaScript--浅易版tab选项卡-CSDN博客
JavaScript--浅易版全选,反选-CSDN博客
10.变乱类型
将众多的变乱类型分类可分为:鼠标变乱、键盘变乱、表单变乱、焦点变乱等,我们逐一展开学习。
鼠标变乱(mouseenter,mouseleave)
鼠标变乱是指跟鼠标操作相关的变乱,如单击、双击、移动等。
`mouseenter 监听鼠标是否移入 DOM 元素
`mouseleave 监听鼠标是否移出 DOM 元素
鼠标颠末变乱:
mouseover 和 mouseout 会有冒泡结果--所以不保举
mouseenter 和 mouseleave 没有冒泡结果 (保举)
- <body>
- <h3>鼠标事件</h3>
- <p>监听与鼠标相关的操作</p>
- <hr>
- <div class="box"></div>
- <script>
- // 需要事件监听的 DOM 元素
- const box = document.querySelector('.box');
-
- // 监听鼠标是移入当前 DOM 元素
- box.addEventListener('mouseenter', function () {
- // 修改文本内容
- this.innerText = '鼠标移入了...';
- // 修改光标的风格
- this.style.cursor = 'move';
- })
- // 监听鼠标是移出当前 DOM 元素
- box.addEventListener('mouseleave', function () {
- // 修改文本内容
- this.innerText = '鼠标移出了...';
- })
- </script>
- </body>
复制代码 键盘变乱(keydown,keyup)
keydown 键盘按下触发
keyup 键盘抬起触发
- //键盘事件
- input__.addEventListener("keydown",function(){
- console.log("键盘按下")
- })
- input__.addEventListener("keyup",function(){
- console.log("键盘抬起")
- })
复制代码 焦点变乱(focus,blur,change)
focus 获得焦点
blur 失去焦点
change 切换焦点
- // 焦点触发
- const input__ = document.querySelector(".input__")
- input__.addEventListener("focus",function(){
- console.log("焦点触发")
- })
- // 失去焦点
- input__.addEventListener("blur",function(){
- console.log("失去焦点")
- })
- // 切换焦点
- input__.addEventListener("change",function(){
- console.log("切换焦点")
- })
复制代码 文本框输入变乱(input)
- //检测用户输入事件--input
- input__.addEventListener("input",function(){
- console.log("检测用户输入事件")
- console.log(input__.value)
- console.log(input__.value.length)
- })
复制代码 11.变乱对象(e)
恣意变乱类型被触发时与变乱相关的信息会被以对象的形式记载下来,我们称这个对象为变乱对象。
e.target--获取子元素
e.target.nodeName--判断子元素
e.preventDefault()--制止默认行为
- <body>
- <h3>事件对象</h3>
- <p>任意事件类型被触发时与事件相关的信息会被以对象的形式记录下来,我们称这个对象为事件对象。</p>
- <hr>
- <div class="box"></div>
- <script>
- // 获取 .box 元素
- const box = document.querySelector('.box')
-
- // 添加事件监听
- box.addEventListener('click', function (e) {
- console.log('任意事件类型被触发后,相关信息会以对象形式被记录下来...');
-
- // 事件回调函数的第1个参数即所谓的事件对象
- console.log(e)
- console.log(e.type)
- console.log(e.data)
- })
- </script>
- </body>
复制代码 变乱回调函数的【第1个参数】即所谓的变乱对象,通常习惯性的将这个对数命名为 event、ev 、e 。
接下来简单看一下变乱对象中包罗了哪些有用的信息:
ev.type 当前变乱的类型
ev.clientX/Y 光标相对浏览器窗口的位置
ev.offsetX/Y 光标相于当前 DOM 元素的位置
注:在变乱回调函数内部通过 window.event 同样可以获取变乱对象。
12.情况对象(this)
函数运行在差别情况中, this 所指代的对象差别。
- // 普通函数this指向window
- function fn(){
- console.log(this) //指向window
- }
- // 谁调用,this就是谁
- box.addEventListener("click",function(){
- console.log(this) //指向函数调用者
- })
复制代码 情况对象指的是函数内部特殊的变量 this ,它代表着当前函数运行时所处的情况。
- <script>
- // 声明函数
- function sayHi() {
- // this 是一个变量
- console.log(this);
- }
-
- // 声明一个对象
- let user = {
- name: '张三',
- sayHi: sayHi // 此处把 sayHi 函数,赋值给 sayHi 属性
- }
-
- let person = {
- name: '李四',
- sayHi: sayHi
- }
-
- // 直接调用
- sayHi() // window
- window.sayHi() // window
-
- // 做为对象方法调用
- user.sayHi()// user
- person.sayHi()// person
- </script>
复制代码 结论:
- this 本质上是一个变量,数据类型为对象
- 函数的调用方式差别 this 变量的值也差别
- 【谁调用 this 就是谁】是判断 this 值的大抵规则
- 函数直接调用时实际上 window.sayHi() 所以 this 的值为 window
13.回调函数
回调函数--不回立马实行--例如变乱就是回调函数
如果将函数 A 做为参数传递给函数 B 时,我们称函数 A 为回调函数。
- <script>
- // 声明 foo 函数
- function foo(arg) {
- console.log(arg);
- }
-
- // 普通的值做为参数
- foo(10);
- foo('hello world!');
- foo(['html', 'css', 'javascript']);
-
- function bar() {
- console.log('函数也能当参数...');
- }
- // 函数也可以做为参数!!!!
- foo(bar);
- </script>
复制代码 函数 bar 做参数传给了 foo 函数,bar 就是所谓的回调函数了!!!
间歇函数 setInterval,fn 函数做为参数传给了 setInterval,这便是回调函数的实际应用
- <script>
- function fn() {
- console.log('我是回调函数...');
- }
- // 调用定时器
- setInterval(fn, 1000);
- </script>
复制代码 结论:
- 回调函数本质照旧函数,只不外把它当成参数使用
- 使用匿名函数做为回调函数比较常见
14.变乱流/变乱传递
冒泡--捕获
变乱流是对变乱实行过程的描述,了解变乱的实行过程有助于加深对变乱的明白,提升开发实践中对变乱运用的灵活度。
变乱传递的过程可以分为三个阶段:变乱捕获阶段、目的阶段和变乱冒泡阶段
在变乱传递过程中,起首是变乱捕获阶段。在这个阶段中,变乱从最外层的父元素开始逐层向下传递,直到到达触发变乱的目的元素。这种方式意味着最外层的父元素开始捕获到了变乱。在变乱捕获阶段中,如果目的元素的父元素也绑定了雷同的变乱处理函数,那么也会触发父元素的变乱处理函数。
接下来是目的阶段,也就是变乱真正被触发的阶段。在这个阶段中,变乱处理函数会被实行。此时,如果目的元素的父元素也绑定了雷同的变乱处理函数,那么也会触发父元素的变乱处理函数。
最后是变乱冒泡阶段。在这个阶段中,变乱从目的元素开始逐层向上冒泡,直到到达最外层的父元素或者根元素。这种方式意味着开始触发变乱的目的元素最后冒泡到了最外层的父元素或者根元素。
了解了变乱传递的三个阶段,我们就能更好地明白变乱传递的原理与逻辑了。变乱的传递顺序是从最外层的父元素到目的元素,接着从目的元素到最外层的父元素或者根元素。所以,在变乱传递过程中,先捕获再冒泡。即变乱起首沿着DOM树向下传递,直到到达目的元素,再沿着DOM树向上冒泡。如许的计划有助于变乱的处理与冒泡。

如上图所示,恣意变乱被触发时总会履历两个阶段:【捕获阶段】和【冒泡阶段】。
简言之,捕获阶段是【从父到子】的传导过程,冒泡阶段是【从子向父】的传导过程。
捕获和冒泡--先捕获再冒泡
了解了什么是变乱流之后,我们来看变乱流是怎样影响变乱实行的:
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Document</title>
- <style>
- html{
- background: orange;
- }
- body{
- background: pink;
- }
- .outer{
- width: 300px;
- height: 300px;
- background: red;
- }
- .inner{
- width: 200px;
- height: 200px;
- background: green;
- }
- .child{
- width: 100px;
- height: 100px;
- background: blue;
- }
- </style>
- </head>
- <body>
- <!-- <h3>事件流</h3>
- <p>事件流是事件在执行时的底层机制,主要体现在父子盒子之间事件的执行上。</p> -->
- <div class="outer">
- <div class="inner">
- <div class="child"></div>
- </div>
- </div>
- <script>
- // 获取嵌套的3个节点
- const outer = document.querySelector('.outer');
- const inner = document.querySelector('.inner');
- const child = document.querySelector('.child');
-
- // html 元素添加事件
- document.documentElement.addEventListener('click', function () {
- console.log('html...')
- })
-
- // body 元素添加事件
- document.body.addEventListener('click', function () {
- console.log('body...')
- })
- // 外层的盒子添加事件
- outer.addEventListener('click', function () {
- console.log('outer...')
- })
-
- // 中间的盒子添加事件
- inner.addEventListener('click', function () {
- console.log('inner...')
- })
-
- // 内层的盒子添加事件
- child.addEventListener('click', function () {
- console.log('child...')
- })
- </script>
- </body>
- </html>
复制代码 实行上述代码后发现,当单击变乱触发时,其先人元素的单击变乱也【相继触发】,这是为什么呢?
团结变乱流的特性,我们知道当某个元素的变乱被触发时,变乱总是会先颠末其先人才能到达当前元素,然后再由当前元素向先人传递,变乱在流动的过程中碰到雷同的变乱便会被触发。
再来关注一个细节就是变乱相继触发的【实行顺序】,变乱的实行顺序是可控制的,即可以在捕获阶段被实行,也可以在冒泡阶段被实行。
如果变乱是在冒泡阶段实行的,我们称为冒泡模式,它会先实行子盒子变乱再去实行父盒子变乱,默认是冒泡模式。
如果变乱是在捕获阶段实行的,我们称为捕获模式,它会先实行父盒子变乱再去实行子盒子变乱。
- <body>
- <h3>事件流</h3>
- <p>事件流是事件在执行时的底层机制,主要体现在父子盒子之间事件的执行上。</p>
- <div class="outer">
- <div class="inner"></div>
- </div>
- <script>
- // 获取嵌套的3个节点
- const outer = document.querySelector('.outer')
- const inner = document.querySelector('.inner')
-
- // 外层的盒子
- outer.addEventListener('click', function () {
- console.log('outer...')
- }, true) // true 表示在捕获阶段执行事件
-
- // 中间的盒子
- outer.addEventListener('click', function () {
- console.log('inner...')
- }, false) // false 表示在冒泡阶段执行事件--默认值为 false
- </script>
- </body>
复制代码 结论:
addEventListener 第3个参数决定了变乱是在捕获阶段触发照旧在冒泡阶段触发
addEventListener 第3个参数为 true 表示捕获阶段触发,false 表示冒泡阶段触发,默认值为 false
变乱流只会在父子元素具有雷同变乱类型时才会产生影响
绝大部门场景都采用默认的冒泡模式(此中一个原因是早期 IE 不支持捕获)
制止冒泡
制止冒泡是指阻断变乱的流动,保证变乱只在当前元素被实行,而不再去影响到其对应的先人元素。
- <script>
- // 获取嵌套的3个节点
- const outer = document.querySelector('.outer')
- const inner = document.querySelector('.inner')
- const child = document.querySelector('.child')
-
- // 外层的盒子
- outer.addEventListener('click', function () {
- console.log('outer...')
- })
-
- // 中间的盒子
- inner.addEventListener('click', function (ev) {
- console.log('inner...')
-
- // 阻止事件冒泡
- ev.stopPropagation()
- })
-
- // 内层的盒子
- child.addEventListener('click', function (ev) {
- console.log('child...')
-
- // 借助事件对象,阻止事件向上冒泡
- ev.stopPropagation()
- })
- </script>
复制代码 结论:变乱对象中的 ev.stopPropagation 方法,专门用来制止变乱冒泡。
15.变乱委托(e.target)
e.target获取子元素
e.target.nodeName判断子元素
变乱委托是利用变乱流的特性解决一些现实开发需求的知识本领,主要的作用是提升程序效率。
大量的变乱监听是比较泯灭性能的,如下代码所示
- <script>
- // 假设页面中有 10000 个 button 元素
- const buttons = document.querySelectorAll('table button');
-
- for(let i = 0; i <= buttons.length; i++) {
- // 为 10000 个 button 元素添加了事件
- buttons.addEventListener('click', function () {
- // 省略具体执行逻辑...
- })
- }
- </script>
复制代码 利用变乱流的特性,可以对上述的代码进行优化,变乱的的冒泡模式总是会将变乱流向其父元素的,如果父元素监听了雷同的变乱类型,那么父元素的变乱就会被触发并实行,正是利用这一特性对上述代码进行优化,如下代码所示:
- <script>
- // 假设页面中有 10000 个 button 元素
- let buttons = document.querySelectorAll('table button');
-
- // 假设上述的 10000 个 buttom 元素共同的祖先元素是 table
- let parents = document.querySelector('table');
- parents.addEventListener('click', function () {
- console.log('点击任意子元素都会触发事件...');
- })
- </script>
复制代码 我们的最终目的是保证只有点击 button 子元素才去实行变乱的回调函数,怎样判断用户点击是哪一个子元素呢?
- <script>
- // 假设页面中有 10000 个 button 元素
- const buttons = document.querySelectorAll('table button')
-
- // 假设上述的 10000 个 buttom 元素共同的祖先元素是 table
- const parents = document.querySelector('table')
- parents.addEventListener('click', function (ev) {
- // console.log(ev.target);
- // 只有 button 元素才会真正去执行逻辑
- if(ev.target.tagName === 'BUTTON') {
- // 执行的逻辑
- }
- })
- </script>
复制代码 优化过的代码只对先人元素添加变乱监听,相比对 10000 个元素添加变乱监听实行效率要高许多!!!
JavaScript--tab选项卡--通过变乱委托和自定义属性实现-CSDN博客
制止默认行为
- const form = document.querySelector("form")
- form.addEventListener("submit",function(e){
- // 阻止默认行为
- e.preventDefault()
- })
复制代码 16.页面加载变乱(load,DOMContentLoaded)
变乱名:load
等待页面所有资源加载完毕,就会实行回调函数--load--给window添加
加载外部资源(如图片、外联CSS和JavaScript等)加载完毕时触发的变乱
有些时间需要等页面资源全部处理完了做一些事情
监听页面所有资源加载完毕:
- window.addEventListener('load', function() {
- // xxxxx
- })
复制代码 变乱名:DOMContentLoaded
html文档被完全加载和解析后--DOMContentLoaded触发--给document加
- document.addEventListener("DOMContentLoaded",function(){
- // xxxxx
- })
复制代码 案例--先实行html文档被完全加载和解析--再实行页面所有资源加载完毕
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Document</title>
- <style>
- .box{
- width: 100px;
- height: 100px;
- background: red;
- }
- </style>
- <script>
- // 等待页面所有资源加载完毕,就会执行回调函数--load--给window添加
- window.addEventListener("load",function(){
- alert("页面所有资源加载完毕")
- })
- // html文档被完全加载和解析后--DOMContentLoaded触发--给document加
- document.addEventListener("DOMContentLoaded",function(){
- alert("html文档被完全加载和解析")
- })
- </script>
- </head>
- <body>
- <div class="box"></div>
- </body>
- </html>
复制代码 17.页面尺寸变乱(resize)
会在窗口尺寸改变的时间触发变乱:
- window.addEventListener('resize', function() {
- // xxxxx
- })
复制代码 18.可视区尺寸(clientWidth,clientHeight)
明白为可视区的宽度和高度,看到是多大的,clientWidth和clientHeight就是多大的
包罗padding,包罗滚动条的宽度,不包罗margin,border,只读属性不能修改
box-sizing: border-box;情况下:
clientWidth=width
clientHeight=height
box-sizing: content-box;情况下
clientWidth=width+padding
clientHeight=height+padding
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Document</title>
- <style>
- .father{
- width: 200px;
- height: 200px;
- background: red;
- box-sizing: border-box;
- overflow: scroll;
- }
- .son{
- width: 100px;
- height: 300px;
- background: green;
- }
- </style>
- </head>
- <body>
- <div class="father">
- <div class="son"></div>
- </div>
-
- <script>
- const father = document.querySelector(".father")
- const son = document.querySelector(".son")
- father.addEventListener("click",function(){
- console.log(father.clientWidth); //185--包含了滚动条的距离
- console.log(father.clientHeight); //185--包含了滚动条的距离
- console.log(son.clientWidth); //100
- console.log(son.clientHeight); //300
- })
- </script>
- </body>
- </html>
复制代码 19.元素滚动变乱(scroll)
滚动条在滚动的时间连续触发的变乱
- window.addEventListener('scroll', function() {
- // xxxxx
- })
复制代码 scrollTop和scrollLeft
可以修改,通常用于回到顶部
scrollLeft:对象的最左边到对象在当前窗口表现的范围内的左边的距离,即在出现了横向滚动条的情况下,滚动条拉动的距离。
scrollTop对象的最顶部到对象在当前窗口表现的范围内的顶边的距离,即在出现了纵向滚动条的情况下,滚动条拉动的距离。
scrollWidth和scrollHeight
可以明白为侧边滚动条可滚动的长度或宽度
包罗padding,不包罗margin,border,只读属性不能修改
scrollWidth和scrollHeight这两个属性用来获取指定元素内容层的真实宽度和高度.
当不存在水平或垂直滚动条时,scrollWidth和scrollHeight等于clientWidth和clientHeight,
scrollWidth和scrollHeight即可视区域宽高度+被潜伏区域宽高度()
scrollHeight=clientHeight+被潜伏区域宽高度
scrollWidth=clientWidth+被潜伏区域宽高度
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Document</title>
- <style>
- .father{
- width: 200px;
- height: 200px;
- background: red;
- box-sizing: border-box;
- overflow: scroll;
- padding: 50px;
- }
- .son{
- width: 100px;
- height: 300px;
- background: green;
- }
- </style>
- </head>
- <body>
- <div class="father">
- <div class="son"></div>
- </div>
-
- <script>
- const father = document.querySelector(".father")
- const son = document.querySelector(".son")
- father.addEventListener("click",function(){
- console.log(father.scrollWidth); //200--包含了padding
- console.log(father.scrollHeight); //400--包含了padding
- })
- </script>
- </body>
- </html>
复制代码 20.元素尺寸与位置(offset)
offsetTop和offsetLeft(位置)
offsetLeft只读属性返回当前元素左上角在offsetParent节点内向右偏移的像素数。
offsetTop只读属性返回当前元素左上角在offsetParent节点内向下偏移的像素数。
如果没有定位,offsetTop与offsetLeft得到的数值相对body
如果父级元素定位后,offsetTop与offsetLeft得到的数值相对父级元素
offsetWidth和offsetHeight(尺寸)
offsetWidth与offsetHeight有个特点,就是这两个属性的值只与该元素有关,与四周元素(父级和子级元素无关)。
它们的大小取决于元素的宽高、padding以及边框border,有无滚动条都没有影响,下面是他们的盘算方式。
offsetWidth=width(样式中设置的)+左右padding+左右border
offsetHeight=height(样式中设置的)+上下padding+上下border
JavaScript--scrollTop,clientHeight,offsetHeight,scrollHeight,offsetTop的案例-CSDN博客
offsetWidth和clientWidth的区别
clientWidth:包括内容区域和内边距,忽略了边框,受滚动条影响
offsetWidth:包括内容区域和内边距以及边框,不受滚动条影响
getBoundingClientRect()
获取元素大小位置的别的方法--相对于视口
- btn.addEventListener("click",function(e){
- console.log(btn.getBoundingClientRect())
- })
复制代码 21.DOM 节点操作
dom节点--包罗元素节点--属性节点--文本节点--其他
插入节点
在已有的 DOM 节点中插入新的 DOM 节点时,需要关注两个关键因素:起首要得到新的 DOM 节点,其次在哪个位置插入这个节点。
- <body>>
- <ul class="father">
- <li>123</li>
- <li>123</li>
- <li>123</li>
- <li>123</li>
- </ul>
- <script>
- // 获取节点
- const father=document.querySelector(".father")
-
- // 创建节点--直接标签
- const chiild_back=document.createElement("div")
- chiild_back.className="box"
- chiild_back.innerHTML="我是追加--后面"
- // 追加节点--插入后面
- father.appendChild(chiild_back)
- const chiild_front=document.createElement("div")
- chiild_front.innerHTML="我是追加--前面"
- // 追加节点--插入前面--放哪个元素,放到哪个元素的前面
- father.insertBefore(chiild_front,dad.children[0])
- </script>
- </body>
复制代码 克隆节点
- <ul class="dad">
- <li class="baby">000</li>
- <li class="baby">111</li>
- <li class="baby">222</li>
- <li class="baby">333</li>
- <li class="baby">444</li>
- </ul>
- // 克隆节点
- // false--浅克隆--只克隆标签
- // true--深克隆--还克隆元素
- console.log(dad.children[0].cloneNode(false)) //<li class="baby"></li>
- console.log(dad.children[0].cloneNode(true)) //<li class="baby">000</li>
复制代码 删除节点
删除全部节点(包罗自己)
删除现有的 DOM 节点,也需要关注两个因素:起首由父节点删除子节点,其次是要删除哪个子节点。
- <body>
- <ul class="dad">
- <li>HTML</li>
- <li>CSS</li>
- <li>Web APIs</li>
- </ul>
-
- <script>
- // 删除全部节点--包含了自己
- dad.remove()
- </script>
- </body>
复制代码 删除某一个子节点
- <body>
- <ul class="dad">
- <li>HTML</li>
- <li>CSS</li>
- <li>Web APIs</li>
- </ul>
-
- <script>
- // 获取 ul 父节点
- let dad = document.querySelector('.dad')
- // 删除子节点--只能删除一个
- dad.removeChild(dad.children[0])
- //或者
- let list = document.querySelectorAll(".dad li")
- dad.removeChild(list[0])
- </script>
- </body>
复制代码 结论:removeChild 删除节点时一定是由父子关系。
删除全部子节点
1.通过元素的 innerHTML 属性来删除
- <input type="button" value="按钮" id="btn">
- <div id="dv">
- <p>1</p>
- <p>2</p>
- <p>3</p>
- </div>
- <script>
- document.getElementById("btn").onclick = function () {
- document.getElementById("dv").innerHTML = "";
- }
- </script>
复制代码 2.通过 removeChild() 方法来删除
removeChild() 的用法是先找到父级元素parent,然后调用 parent.removeChild(thisNode) 来删除当前子节点(thisNode),那我们只要循环遍历删除所有的即可。
留意:循环遍历的时间一定要倒序,因为正序的时间,当你把索引为0的子节点删除后,那么原来索引为1的就变成了0,而这时变量 i 已经变成1了,程序继续走时就会删除原先索引为2的如今为1的节点,结果就是最后只删除了一半的节点,朋友们可自行实验明白一下。
- <input type="button" value="按钮" id="btn">
- <div id="dv">
- <p>1</p>
- <p>2</p>
- <p>3</p>
- </div>
- <script>
- document.getElementById("btn").onclick = function () {
- // 获取 div 标签
- var div = document.getElementById("dv");
- // 获取 div 标签下的所有子节点
- var pObjs = div.childNodes;
- for (var i = pObjs.length - 1; i >= 0; i--) { // 一定要倒序,正序是删不干净的,可自行尝试
- div.removeChild(pObjs[i]);
- }
- }
- </script>
复制代码 查找节点
DOM 树中的恣意节点都不是孤立存在的,它们要么是父子关系,要么是兄弟关系,不仅云云,我们可以依据节点之间的关系查找节点。
父子关系
- <body>
- <!-- 获取 ul 的子节点 -->
- <div>
- <ul class="dad">
- <li class="baby">HTML</li>
- <li class="baby">CSS</li>
- <li class="baby">JavaScript 基础</li>
- <li class="baby">Web APIs</li>
- </ul>
- </div>
- <script>
- // 父节点
- const ul = document.querySelector('ul')
- // childNodes 获取全部的子节点,回车换行会被认为是空白文本节点
- console.log(ul.childNodes)
- // 打印为:NodeList(9) [text, li.baby, text, li.baby, text, li.baby, text, li.baby, text]
-
- // children 只获取元素类型节点
- console.log(ul.children)
- // 打印为:HTMLCollection(4) [li.baby, li.baby, li.baby, li.baby]
-
- //parentNode 获取父节点,以相对位置查找节点,实际应用中非常灵活。
- const baby =document.querySelector(".baby")
- console.log(baby.parentNode)
- //爷爷节点div
- console.log(baby.parentNode.parentNode)
- </script>
- </body>
复制代码 兄弟关系
- <body>
- <ul>
- <li>HTML</li>
- <li>CSS</li>
- <li>JavaScript 基础</li>
- <li>Web APIs</li>
- </ul>
- <script>
- // 获取所有 li 节点
- const lis = document.querySelectorAll('ul li')
-
- // 对所有的 li 节点添加事件监听
- for(let i = 0; i < lis.length; i++) {
- lis[i].addEventListener('click', function () {
- // 前一个节点
- console.log(this.previousSibling)
- // 前一个节点的前一个节点---以此类推
- console.log(this.previousSibling.previousSibling)
- // 下一个节点
- console.log(this.nextSibling)
- // 下一个节点的下一个节点---以此类推
- console.log(this.nextSibling.nextSibling)
- })
- }
- </script>
- </body>
复制代码 结论:
- previousSibling 获取前一个节点,以相对位置查找节点,实际应用中非常灵活。
- nextSibling 获取后一个节点,以相对位置查找节点,实际应用中非常灵活。
三.BOM
- DOM 文档对象模子, 定义了一套操作HTML文档的API
- BOM 浏览器对象模子,定义了一套操作浏览器窗口的API
1.BOM的先容
BOM (Browser Object Model ) 是浏览器对象模子
- window对象是一个全局对象,也可以说是JavaScript中的顶级对象--最大的
- 像document、alert()、console.log()这些都是window的属性,根本BOM的属性和方法都是window的
- 所有通过var定义在全局作用域中的变量、函数都会变成window对象的属性和方法
- window对象下的属性和方法调用的时间可以省略window
2.BOM和DOM的区别
3.定时器
3.1.间歇函数(setInterval)
setInterval 是 JavaScript 中内置的函数,它的作用是间隔固定的时间自动重复实行另一个函数,也叫定时器函数。
- <script>
- setInterval(function不需要写函数名(){},间隔函数)
- setInterval(function(){
- console.log("1111")
- },1000)
- // 1. 定义一个普通函数
- function repeat() {
- console.log('不知疲倦的执行下去....')
- }
-
- // 2. 使用 setInterval 调用 repeat 函数
- // 间隔 1000 毫秒,重复调用 repeat
- setInterval(repeat, 1000)
- </script>
复制代码 定时器关闭
- function fn(){
- console.log("1111")
- }
- let time = setInterval(fn,100)
- //定时器关闭
- console.log(time)
- clearInterval(time)
复制代码 3.2.延迟函数(setTimeout)
JavaScript 内置的一个用来让代码延迟实行的函数,叫 setTimeout
语法:
setTimeout 仅仅只实行一次,所以可以明白为就是把一段代码延迟实行, 平常省略window
清除延时函数:
- 注意点
- 延时函数需要等待,所以后面的代码先执行
- 返回值是一个正整数,表示定时器的编号
复制代码- <body>
- <script>
- // 定时器之延迟函数
-
- // 1. 开启延迟函数
- let timerId = setTimeout(function () {
- console.log('我只执行一次')
- }, 3000)
-
- // 1.1 延迟函数返回的还是一个正整数数字,表示延迟函数的编号
- console.log(timerId)
-
- // 1.2 延迟函数需要等待时间,所以下面的代码优先执行
-
- // 2. 关闭延迟函数
- clearTimeout(timerId)
-
- </script>
- </body>
复制代码 4.location对象
location (地址) 它拆分并生存了 URL 地址的各个构成部门, 它是一个对象
属性/方法说明href属性,获取完整的 URL 地址,赋值时用于地址的跳转search属性,获取地址中携带的参数,符号 ?后面部门hash属性,获取地址中的啥希值,符号 # 后面部门reload()方法,用来革新当前页面,传入参数 true 时表示强制革新- <body>
- <form>
- <input type="text" name="search"> <button>搜索</button>
- </form>
- <a href="#/music">音乐</a>
- <a href="#/download">下载</a>
-
- <button class="reload">刷新页面</button>
- <script>
- // location 对象
- // 1. href属性 (重点) 得到完整地址,赋值则是跳转到新地址
- console.log(location.href)
- // location.href = 'http://www.itcast.cn'
-
- // 2. search属性 得到 ? 后面的地址
- console.log(location.search) // ?search=笔记本
-
- // 3. hash属性 得到 # 后面的地址
- console.log(location.hash)
-
- // 4. reload 方法 刷新页面
- const btn = document.querySelector('.reload')
- btn.addEventListener('click', function () {
- // location.reload() // 页面刷新
- location.reload(true) // 强制页面刷新 ctrl+f5
- })
- </script>
- </body>
复制代码 5.navigator对象
navigator是对象,该对象下记载了浏览器自身的相关信息
常用属性和方法:
- // 检测 userAgent(浏览器信息)
- (function () {
- const userAgent = navigator.userAgent
- // 验证是否为Android或iPhone
- const android = userAgent.match(/(Android);?[\s\/]+([\d.]+)?/)
- const iphone = userAgent.match(/(iPhone\sOS)\s([\d_]+)/)
- // 如果是Android或iPhone,则跳转至移动站点
- if (android || iphone) {
- location.href = 'http://m.itcast.cn'
- }})();
复制代码 6.histroy对象
history (历史)是对象,主要管理历史记载, 该对象与浏览器地址栏的操作相对应,如前进、后退等
使用场景
history对象一般在实际开发中比较少用,但是会在一些OA 办公体系中见到。
- <body>
- <button class="back">←后退</button>
- <button class="forward">前进→</button>
- <script>
- // histroy对象
-
- // 1.前进
- const forward = document.querySelector('.forward')
- forward.addEventListener('click', function () {
- // history.forward()
- history.go(1)
- })
- // 2.后退
- const back = document.querySelector('.back')
- back.addEventListener('click', function () {
- // history.back()
- history.go(-1)
- })
- </script>
- </body>
复制代码 7.当地存储
当地存储:将数据存储在当地浏览器中
常见的使用场景:
https://todomvc.com/examples/vanilla-es6/ 页面革新数据不丢失
好处:
1、页面革新或者关闭不丢失数据,实现数据持久化
2、容量较大,sessionStorage和 localStorage 约 5M 左右
localStorage(重点)
作用: 数据可以长期生存在当地浏览器中,革新页面和关闭浏览器,数据也不会丢失,除非手动删除
特性:以键值对的形式存储,而且存储的是字符串, 省略了window
- <!DOCTYPE html>
- <html lang="en">
-
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>本地存储-localstorage</title>
- </head>
-
- <body>
- <script>
- // 本地存储 - localstorage 存储的是字符串
- // 1. 存储
- localStorage.setItem('age', 18)
-
- // 2. 获取
- console.log(localStorage.getItem('age'))
-
- // 3. 删除
- localStorage.removeItem('age')
- // 修改本地数据
- localStorage.setItem("age111","22")
- </script>
- </body>
-
- </html>
复制代码 sessionStorage(了解)
特性:
- 用法跟localStorage根本雷同
- 区别是:当页面浏览器被关闭时,存储在 sessionStorage 的数据会被清除
存储:sessionStorage.setItem(key,value)
获取:sessionStorage.getItem(key)
删除:sessionStorage.removeItem(key)
localStorage存储复杂数据类型
题目:localStorage只能存储字符串,无法存储复杂数据类型.
解决:需要将复杂数据类型转换成 JSON字符串,再存储到当地
语法:JSON.stringify(复杂数据类型)
JSON字符串:
- 起首是1个字符串
- 属性名使用双引号引起来,不能单引号
- 属性值如果是字符串型也必须双引号
- <body>
- <script>
- // 本地存储复杂数据类型
- const goods = {
- name: '小米',
- price: 1999
- }
- // localStorage.setItem('goods', goods)
- // console.log(localStorage.getItem('goods'))
-
- // 1. 把对象转换为JSON字符串 JSON.stringify
- localStorage.setItem('goods', JSON.stringify(goods))
- // console.log(typeof localStorage.getItem('goods'))
-
- </script>
- </body>
复制代码 localStorage使用复杂数据类型
题目:因为当地存储内里取出来的是字符串,不是对象,无法直接使用
解决:把取出来的字符串转换为对象
语法:JSON.parse(JSON字符串)
- <body>
- <script>
- // 本地存储复杂数据类型
- const goods = {
- name: '小米',
- price: 1999
- }
- // localStorage.setItem('goods', goods)
- // console.log(localStorage.getItem('goods'))
- // 1. 把对象转换为JSON字符串 JSON.stringify
- localStorage.setItem('goods', JSON.stringify(goods))
- // console.log(typeof localStorage.getItem('goods'))
- // 2. 把JSON字符串转换为对象 JSON.parse
- console.log(JSON.parse(localStorage.getItem('goods')))
- </script>
- </body>
复制代码 8.正则表达式
正则表达式(Regular Expression)是一种字符串匹配的模式(规则)
使用场景:
例如验证表单:手机号表单要求用户只能输入11位的数字 (匹配)
过滤掉页面内容中的一些敏感词(替换),或从字符串中获取我们想要的特定部门(提取)等
正则根本使用
- <body>
- <script>
- // 正则表达式的基本使用
- const str = 'web前端开发'
- // 1. 定义规则
- //其中/ /是正则表达式字面量
- //正则表达式也是对象
- const reg = /web/
-
- // 2. 使用正则 test()
- //test()方法 用来查看正则表达式与指定的字符串是否匹配
- //如果正则表达式与指定的字符串匹配 ,返回true,否则false
- console.log(reg.test(str)) // true 如果符合规则匹配上则返回true
- console.log(reg.test('java开发')) // false 如果不符合规则匹配上则返回 false
- </script>
- </body>
复制代码 正则表达式replace替换方法
replace 替换方法,可以完成字符的替换
- <body>
- <script>
- // 替换和修饰符
- const str = '欢迎大家学习前端,相信大家一定能学好前端,都成为前端大神'
- // 1. 替换 replace 需求:把前端替换为 web
- // 1.1 replace 返回值是替换完毕的字符串
- const strEnd = str.replace(/前端/, 'web') //只能替换一个
- </script>
- </body>
复制代码 修饰符约束正则实行的某些细节行为,如是否区分大小写、是否支持多行匹配等
- i 是单词 ignore 的缩写,正则匹配时字母不区分大小写
- g 是单词 global 的缩写,匹配所有满意正则表达式的结果
- <body>
- <script>
- // 替换和修饰符
- const str = '欢迎大家学习前端,相信大家一定能学好前端,都成为前端大神'
- // 1. 替换 replace 需求:把前端替换为 web
- // 1.1 replace 返回值是替换完毕的字符串
- const strEnd = str.replace(/前端/, 'web') //只能替换一个
-
- // 2. 修饰符 g 全部替换
- const strEnd = str.replace(/前端/g, 'web')
- console.log(strEnd)
- </script>
- </body>
复制代码 正则表达式实例demo
JavaScript表单验证demo-CSDN博客
JavaScript表单验证replace---demo-CSDN博客
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |