DOM-获取&属性操作
Web API基本认知
作用和分类
- 作用: 就是使用 JS 去操作 html 和浏览器
- 分类:DOM (文档对象模型)、BOM(浏览器对象模型)
什么是DOM
- DOM(Document Object Model——
文档对象模型)是用来呈现以及与任意 HTML 或 XML文档交互的API - 白话文:DOM是浏览器提供的一套专门用来 操作网页内容 的功能
- DOM作用
- 开发网页内容特效和实现用户交互
DOM树
- DOM树是什么?
- 将 HTML 文档以树状结构直观的表现出来,我们称之为文档树或 DOM 树
- 描述网页内容关系的名词
- 作用:
文档树直观的体现了标签与标签之间的关系
DOM对象
-
DOM对象:浏览器根据html标签生成的
JS对象- 所有的标签属性都可以在这个对象上面找到
- 修改这个对象的属性会自动映射到标签身上
-
DOM的核心思想
- 把网页内容当做
对象来处理
- 把网页内容当做
-
document 对象
- 是 DOM 里提供的一个
对象 - 所以它提供的属性和方法都是
用来访问和操作网页内容的- 例:document.write()
- 网页所有内容都在document里面
- 是 DOM 里提供的一个
获取DOM对象
根据CSS选择器来获取DOM元素
查找元素DOM元素就是利用 JS 选择页面中标签元素
选择匹配的第一个元素(语法)
document.querySelector('CSS选择器')
注意:获取DOM对象之前需要声明一个变量在前面接着,推荐使用:const
const 任意变量名,也可跟获取的标签名一样 = document.querySelector('CSS选择器')
- 参数
- 包含一个或多个有效的CSS选择器
字符串
- 包含一个或多个有效的CSS选择器
- 返回值
- CSS选择器匹配的
第一个元素,一个 HTMLElement对象。 如果没有匹配到,则返回null。
- CSS选择器匹配的
- 参看文档
注意:
必须是字符串,也就是必须加引号
选择匹配的多个元素(语法)
document.querySelectorAll('CSS选择器')
//例如:
document.querySelectorAll('ul li')
注意:获取DOM对象之前需要声明一个变量在前面接着,推荐使用:const
const 任意变量名,也可跟获取的标签名一样 = document.querySelectorAll('CSS选择器')
- 参数
- 包含
一个或多个有效的CSS选择器字符串
- 包含
- 返回值
- CSS选择器匹配的
NodeList 对象集合
- CSS选择器匹配的
- 得到的是一个
伪数组:- 有长度有索引号的数组
- 但是没有 pop() push() 等数组方法
- 想要得到里面的每一个对象,则需要遍历(for)的方式获得。
注意:哪怕只有一个元素,通过querySelectAll() 获取过来的也是一个伪数组,里面只有一个元素而已
其他获取DOM元素方法(了解)
//根据id获取一个元素
document.getElementById('nav')
//根据 标签获取一类元素 获取页面 所有div
document.getElementsByTagName('div')
//根据 类名获取元素 获取页面 所有类名为w的
document.getElementsByClassName('w')
操作元素内容
对象.innerText 属性(语法)
- 元素innerText 属性
- 将文本内容添加/更新到任意标签位置
- 显示纯文本,
不解析标签
const info = document.querySelector('.info')
//获取标签内部的文字
info.innerText = '牛豫哲'
///添加/修改标签内部文字内容
对象.innerHTML 属性(语法)
- 元素.innerHTML 属性
- 将文本内容添加/更新到任意标签位置
会解析标签,多标签建议使用模板字符
const info = document.querySelector('.info')
//获取标签内部的文字
info.innerHTML = `<strong>牛豫哲</strong>`
///添加/修改标签内部文字内容
操作元素属性
操作元素常用属性
用途:
可以通过 JS 设置/修改标签元素属性,比如通过 src更换 图片
最常见的属性比如: href、title、src 等
语法
对象.属性 = 值
- 举例说明
// 1.获取元素
const pic = document.querySelector('img')
// 2.操作元素
pic.src = './ images/b02.jpg'
pic.title = '刘德华黑马演唱会'
操作元素样式属性
用途:
- 还可以通过 JS 设置/修改标签元素的样式属性。
- 比如通过 轮播图小圆点自动更换颜色样式
- 点击按钮可以滚动图片,这是移动的图片的位置 left 等等
通过 style 属性操作CSS
语法
对象.style.样式属性=值
- 举例说明
const box = document.querySelector('.box')
//修改元素样式 注意:
box.style.width = '200px' 修改样式通过style属性引出
box.style.marginTop = '15px' 如果属性有-连接符,需要转换为小驼峰命名法
box.style.backgroundColor = 'pink' 赋值的时候,需要的时候不要忘记加css单位
操作类名(className) 操作CSS
说明:如果修改的样式比较多,直接通过style属性修改比较繁琐,我们可以通过借助于css类名的形式。
语法
//active是一个css类名
元素.className = 'active' 修改大量样式的更方便
大白话就是可以从写一个css样式,让后命名为active 直接使用这个css,顶替掉或覆盖以前的样式
注意:1. 由于class是关键字, 所以使用className去代替 2. className是使用新值换旧值, 如果需要添加一个类,需要保留之前的类名
通过 classList 操作类控制CSS
语法
为了解决className 容易覆盖以前的类名,我们可以通过classList方式追加和删除类名
//追加一个类
元素.classList.add('类名')
//删除一个类
元素.classList.remove('类名') 修改不多样式的时候方便
//切换一个类 有就删掉,没有就加上
元素.classList.toggle('类名') classList 是追加和删除不影响以前类名
操作表单元素属性
- 表单很多情况,也需要修改属性,比如点击眼睛,可以看到密码,本质是把表单类型转换为文本框
- 正常的有属性有取值的 跟其他的标签属性没有任何区别
- 表单属性中添加就有效果,移除就没有效果,一律使用布尔值表示 如果为true 代表添加了该属性 如果是false 代表移 除了该属性
- 比如: disabled、checked、selected
语法
获取: DOM对象.属性名
表单.velue = '用户名
设置: DOM对象.属性名 = 新值
表单.type = 'password'
自定义属性
- 标准属性:
- 标签天生自带的属性 比如class id title等, 可以直接使用点语法操作比如: disabled、checked、selected
- 自定义属性:
- 在html5中推出来了专门的data-自定义属性
- 在标签上一律以data-开头
- 在DOM对象上一律以dataset对象方式获取
<body>
<div class="box" data-id="10">盒子</div>
<script>
const box = document.querySelector('.box')
console.log(box.dataset.id
</script>
</body>
定时器-间歇函数
定时器函数介绍
- 网页中经常会需要一种功能:每隔一段时间需要自动执行一段代码,不需要我们手动去触发
- 例如:网页中的倒计时
- 要实现这种需求,需要定时器函数
- 定时器函数有两种
定时器函数基本使用
开启定时器(语法)
setInterval(函数,间隔时间)
作用:每隔一段时间调用这个函数 单位:间隔时间单位是毫秒
举例说明
function repeat() {
console.log('前端程序员,就是头发多咋滴~~')
}
//每隔一秒调用repeat函数
setInterval(repeat, 1000 )
注意: 1. 函数名字不需要加括号 2. 定时器返回的是一个id数字
关闭定时器(语法)
let 变量名 = setInterval(函数,间隔时间)
clearInterval(变量名)
一般不会刚创建就停止,而是满足一定条件再停止
let timer = setInterval(function() {
console.1og('hi~~')
},1000)
clearInterval(timer)
综合案例
- 需求:每隔一秒钟切换一个图片
- 分析:
- 准备一个数组对象,里面包含详细信息(素材包含)
- 获取元素
- 设置定时器函数
- 设置一个变量++
- 找到变量对应的对象
- 更改图片、文字信息
- 激活小圆点:移除上一个高亮的类名,当前变量对应的小圆点添加类
- 处理图片自动复原从头播放(放到变量++后面,紧挨)
- 如果图片播放到最后一张, 就是大于等于数组的长度
- 则把变量重置为0
<title>轮播图点击切换</title>
<style>
* {
box-sizing: border-box;
}
.slider {
width: 560px;
height: 400px;
overflow: hidden;
}
.slider-wrapper {
width: 100%;
height: 320px;
}
.slider-wrapper img {
width: 100%;
height: 100%;
display: block;
}
.slider-footer {
height: 80px;
background-color: rgb(100, 67, 68);
padding: 12px 12px 0 12px;
position: relative;
}
.slider-footer .toggle {
position: absolute;
right: 0;
top: 12px;
display: flex;
}
.slider-footer .toggle button {
margin-right: 12px;
width: 28px;
height: 28px;
appearance: none;
border: none;
background: rgba(255, 255, 255, 0.1);
color: #fff;
border-radius: 4px;
cursor: pointer;
}
.slider-footer .toggle button:hover {
background: rgba(255, 255, 255, 0.2);
}
.slider-footer p {
margin: 0;
color: #fff;
font-size: 18px;
margin-bottom: 10px;
}
.slider-indicator {
margin: 0;
padding: 0;
list-style: none;
display: flex;
align-items: center;
}
.slider-indicator li {
width: 8px;
height: 8px;
margin: 4px;
border-radius: 50%;
background: #fff;
opacity: 0.4;
cursor: pointer;
}
.slider-indicator li.active {
width: 12px;
height: 12px;
opacity: 1;
}
</style>
<div class="slider">
<div class="slider-wrapper">
<img src="./images/slider01.jpg" alt="" />
</div>
<div class="slider-footer">
<p>对人类来说会不会太超前了?</p>
<ul class="slider-indicator">
<li class="active"></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
<div class="toggle">
<button class="prev"><</button>
<button class="next">></button>
</div>
</div>
</div>
<script>
// 1. 初始数据
const sliderData = [
{ url: './images/slider01.jpg', title: '对人类来说会不会太超前了?', color: 'rgb(100, 67, 68)' },
{ url: './images/slider02.jpg', title: '开启剑与雪的黑暗传说!', color: 'rgb(43, 35, 26)' },
{ url: './images/slider03.jpg', title: '真正的jo厨出现了!', color: 'rgb(36, 31, 33)' },
{ url: './images/slider04.jpg', title: '李玉刚:让世界通过B站看到东方大国文化', color: 'rgb(139, 98, 66)' },
{ url: './images/slider05.jpg', title: '快来分享你的寒假日常吧~', color: 'rgb(67, 90, 92)' },
{ url: './images/slider06.jpg', title: '哔哩哔哩小年YEAH', color: 'rgb(166, 131, 143)' },
{ url: './images/slider07.jpg', title: '一站式解决你的电脑配置问题!!!', color: 'rgb(53, 29, 25)' },
{ url: './images/slider08.jpg', title: '谁不想和小猫咪贴贴呢!', color: 'rgb(99, 72, 114)' },
]
// 1.获取元素
// 1.1获取图片元素
const img = document.querySelector('.slider-wrapper img')
// 1.2获取p文字元素
const p = document.querySelector('.slider-footer p')
let i = 0 //信号量 控制图片的张数
// 2.开启定时器
setInterval(function (){
i++
// 无缝衔接位置
if (i >= sliderData.length){
i = 0
}
// 更换图片路径
img.src = sliderData[i].url
// 把字写到p里面
p.innerHTML = sliderData[i].title
// 小圆点
// 先删除以前的active
document.querySelector('.slider-indicator .active').classList.remove('active')
// 只让当前li添加active
document.querySelector(`.slider-indicator li:nth-child(${i + 1})`).classList.add('active')
},1000)
</script>
DOM事件基础
事件监听(绑定)
事件监听
- 什么是事件?
- 事件是在编程时系统内发生的动作或者发生的事情
- 比如用户在网页上单击一个按钮
- 什么是事件监听?
就是让程序检测是否有事件产生,一旦有事件触发,就立即调用一个函数做出响应,也称为 绑定事件或者注册事件比如鼠标经过显示下拉菜单,- 比如点击可以播放轮播图等等
事件监听(语法)
元素对象.addEventListener('事件类型',要执行的函数)
事件监听三要素
事件源:那个dom元素被事件触发了,要获取dom元素
事件类型:用什么方式触发,比如鼠标单击 click、鼠标经过 mouseover 等
时间调用的函数:要做什么事
举例说明
<button>按钮</button> 1. //事件源
<script>
const but = document.querySelector('button') //先获取按钮
but.addEventListener('click',function(){ 2. //事件类型:click是鼠标点击.点击了一下按钮
alert('你好鸭!') 3. //时间调用的函数:弹出‘你好鸭!’对话框
})
</script>
注意:1.事件类型要加引号 2.函数是点击之后再去执行,每次 点击都会执行一次
事件类型
鼠标事件 -鼠标触发
click鼠标点击mouseenter鼠 标 经 过mouseleave鼠标离开
焦点事件-表单获得光标
focus获得焦点blur失去焦点
键盘事件-键盘触发
Keydown键盘按下触发Keyup键盘抬起触发
文本事件-表单输入触发
input用户输入事件
事件对象
获取事件对象
- 事件对象是什么
也是个对象,这个对象里有事件触发时的相关信息- 例如:鼠标点击事件中,事件对象就存了鼠标点在哪个位置等信息
- 使用场景
- 可以判断用户按下哪个键,比如按下回车键可以发布新闻
- 可以判断鼠标点击了哪个元素,从而做相应的操作
获取事件对象(语法)
//在事件绑定的回调函数的第一个参数就是事件对象
//一般命名为event、ev、e
元素.addEventListener('click',function (e) {
})
示例
<body>
<input type="text">
<script>
// 先获取
const input = document.querySelector('input')
input.addEventListener('keyup', function (e) {
// if判断是否是回车键
if (e.key === 'Enter') {
console.log('我按下了回车键')
}
})
</script>
</body>
事件对象常用属性
- 部分常用属性
- type
- 获取当前的事件类型
- clientX/clientY
- 获取光标相对于浏览器可见窗口左上角的位置
- offsetX/offsetY
- 获取光标相对于当前DOM元素左上角的位置
- key
- 用户按下的键盘键的值
- 现在不提倡使用keyCode
- type
环境对象
- 环境对象:指的是函数内部特殊的变量 this ,它代表着当前函数运行时所处的环境
- 作用:弄清楚this的指向,可以让我们代码更简洁
- 函数的调用方式不同,this 指代的对象也不同
【谁调用, this 就是谁】是判断 this 指向的粗略规则- 直接调用函数,其实相当于是 window.函数,所以 this 指代 window
回调函数
- 如果将函数 A 做为参数传递给函数 B 时,我们称函数 A 为回调函数
- 简单理解: 当一个函数当做参数来传递给另外一个函数的时候,这个函数就是回调函数
- 说白了等待执行或者听命令执行的函数叫回调函数
综合案例
Tab栏切换
需求:鼠标经过不同的选项卡,底部可以显示 不同的内容
<title>tab栏切换</title>
<style>
* {
margin: 0;
padding: 0;
}
.tab {
width: 590px;
height: 340px;
margin: 20px;
border: 1px solid #e4e4e4;
}
.tab-nav {
width: 100%;
height: 60px;
line-height: 60px;
display: flex;
justify-content: space-between;
}
.tab-nav h3 {
font-size: 24px;
font-weight: normal;
margin-left: 20px;
}
.tab-nav ul {
list-style: none;
display: flex;
justify-content: flex-end;
}
.tab-nav ul li {
margin: 0 20px;
font-size: 14px;
}
.tab-nav ul li a {
text-decoration: none;
border-bottom: 2px solid transparent;
color: #333;
}
.tab-nav ul li a.active {
border-color: #e1251b;
color: #e1251b;
}
.tab-content {
padding: 0 16px;
}
.tab-content .item {
display: none;
}
.tab-content .item.active {
display: block;
}
</style>
</head>
<body>
<div class="tab">
<div class="tab-nav">
<h3>每日特价</h3>
<ul>
<li><a class="active" href="javascript:;">精选</a></li>
<li><a href="javascript:;">美食</a></li>
<li><a href="javascript:;">百货</a></li>
<li><a href="javascript:;">个护</a></li>
<li><a href="javascript:;">预告</a></li>
</ul>
</div>
<div class="tab-content">
<div class="item active"><img src="./images/tab00.png" alt="" /></div>
<div class="item"><img src="./images/tab01.png" alt="" /></div>
<div class="item"><img src="./images/tab02.png" alt="" /></div>
<div class="item"><img src="./images/tab03.png" alt="" /></div>
<div class="item"><img src="./images/tab04.png" alt="" /></div>
</div>
</div>
<script>
// 1.先把五个小a获取过来
const as = document.querySelectorAll('a')
for(let i = 0;i < as.length;i++){
as[i].addEventListener('mouseenter',function(){
// console.log('鼠标经过')
// 排他思想
// 干掉别人,移除类active
document.querySelector('.tab-nav .active').classList.remove('active')
// 我上位,添加类active this 当前那个a
this.classList.add('active')
// 下面五个大盒子一一对应,.item
// 干掉别人
document.querySelector('.tab-content .active').classList.remove('active')
// 对应序列号的那个item 显示 添加 active 类
// 这个i是上面的i 跟上面联动 因为是css标签,所以i+1
document.querySelector(`.tab-content .item:nth-child(${i + 1})`).classList.add('active')
})
}
</script>
Dom事件进阶
事件流
事件流与两个阶段说明
-
事件流指的是事件完整执行过程中的流动路径- 说明:假设页面里有个div,当触发事件时,会经历两个阶段,分别是捕获阶段、冒泡阶段
- 简单来说:
捕获阶段是 从父到子冒泡阶段是从子到父 实际工作都是使用事件冒泡为主
事件捕获
-
事件捕获概念:
- 从DOM的根元素开始去执行对应的事件 (从外到里)
-
事件捕获需要写对应代码才能看到效果
-
代码
-
DOM.addEventListener(事件类型,事件处理函数,是否使用捕获机制)
-
-
说明:
- addEventListener第三个参数传入 true 代表是捕获阶段触发(很少使用)
- 若传入false代表冒泡阶段触发,默认就是false
- 若是用 L0 事件监听,则只有冒泡阶段,没有捕获
事件冒泡
- 事件冒泡概念:
- 当一个元素的事件被触发时,同样的事件将会在该元素的所有祖先元素中依次被触发。这一过程被称为事件冒泡
- 简单理解:当一个元素触发事件后,会依次向上调用所有父级元素的 同名事件
- 事件冒泡是默认存在的
- L2事件监听第三个参数是 false,或者默认都是冒泡
阻止冒泡
问题:因为默认就有冒泡模式的存在,所以容易导致事件影响到父级元素
需求:若想把事件就限制在当前元素内,就需要阻止事件冒泡
前提:阻止事件冒泡需要拿到事件对象
阻止冒泡(语法)
- 第一种
事件对象.stopPropagation()
注意:此方法可以阻断事件流动传播,不光在冒泡阶段有效,捕获阶段也有效
第二种
- 我们某些情况下需要
阻止默认行为的发生,比如 阻止 链接的跳转,表单域跳转
语法
e.preventDefault()
解绑事件
- on事件方式,直接使用null覆盖偶就可以实现事件的解绑
解绑事件(语法)
//绑定事件
btn.onclick = function () {
alert('点击了')
}
//解绑事件
btn.onclick = null
-
addEventListener方式,必须使用:
-
removeEventListener(事件类型, 事件处理函数, [获取捕获或者冒泡阶段])
-
例如:
function fn() {
alert('点击了')
}
// 绑定事件
btn.addEventListener('click', fn)
//解绑事件
btn.removeEventListener('click', fn)
注意:匿名函数无法被解绑
鼠标经过事件的区别
- 鼠标经过事件:
- mouseover 和 mouseout 会有冒泡效果
- mouseenter 和 mouseleave 没有冒泡效果 (推荐)
两种注册事件的区别
- 传统on注册(L0)
- 同一个对象,后面注册的事件会覆盖前面注册(同一个事件)
- 直接使用null覆盖偶就可以实现事件的解绑
- 都是冒泡阶段执行的
- 事件监听注册(L2)
- 语法: addEventListener(事件类型, 事件处理函数, 是否使用捕获)
- 后面注册的事件不会覆盖前面注册的事件(同一个事件)
- 可以通过第三个参数去确定是在冒泡或者捕获阶段执行
- 必须使用removeEventListener(事件类型, 事件处理函数, 获取捕获或者冒泡阶段)
- 匿名函数无法被解绑
事件委托
- 事件委托是利用事件流的特征解决一些开发需求的知识技巧
- 优点:
减少注册次数,可以提高程序性能 - 原理:事件委托其实是利用事件冒泡的特点。
- 给
父元素注册事件,当我们触发子元素的时候,会冒泡到父元素身上,从而触发父元素的事件
- 给
- 实现:
事件对象.target. tagName可以获得真正触发事件的元素 ul.addEventListener('click', function(){}) 执行父级点击事件
- 优点:
其他事件
页面加载事件
- 加载外部资源(如图片、外联CSS和JavaScript等)加载完毕时触发的事件
- 为什么要学?
- 有些时候需要等页面资源全部处理完了做一些事情
- 老代码喜欢把 script 写在 head 中,这时候直接找 dom 元素找不到
- 事件名:load
- 监听页面所有资源加载完毕:
- 给
window添加load事件
- 给
//页面加载事件
window.addEventListener('load',function () {
//执行的操作
})
注意:不光可以监听整个页面资源加载完毕,也可以针对某个资源绑定load事件
- 当初始的 HTML 文档被完全加载和解析完成之后,DOMContentLoaded 事件被触发,而无需等待样式表、图像等完 全加载
- 事件名:DOMContentLoaded
- 监听页面DOM加载完毕:
- 给
document添加 DOMContentLoaded 事件
- 给
document.addEventListener('DOMContentLoaded',function () {
//执行的操作
})
元素滚动事件
-
- 滚动条在滚动的时候持续触发的事件
- 为什么要学?
- 很多网页需要检测用户把页面滚动到某个区域后做一些处理, 比如固定导航栏,比如返回顶部
- 事件名:scroll
- 监听整个页面滚动:
- 给 window 或 document 添加 scroll 事件
//页面滚动事件
window.addEventListener('scroll', function () {
//执行的操作
})
- 监听某个元素的内部滚动直接给某个元素加即可
- 使用场景:
- 我们想要页面滚动一段距离,比如100px,就让某些元素
- 显示隐藏,那我们怎么知道,页面滚动了100像素呢?
- 就可以使用scroll 来检测滚动的距离~~~
页面滚动事件-获取位置
- scrollLeft和scrollTop (属性)
-
- 获取被卷去的大小
- 获取元素内容往左、往上滚出去看不到的距离
- 这两个值是可
读写的
- 尽量在scroll事件里面获取被卷去的距离
div.addEventListener('scroll', function () {
console.log(this.scrollTop)
})
页面滚动事件-获取位置
- 开发中,我们经常检测页面滚动的距离,比如页面滚动100像素,就可以显示一个元素,或者固定一个元素
//页面滚动事件
window.addEventListener('scroll', function () {
// document. documentELement 是htmL元素获取方式
const n = document.documentE lement.scrollTop
console.log(n)
})
document.documentElement HTML 文档返回对象为HTML元素
页面滚动事件-滚动到指定的坐标
- scrollTo() 方法可把内容滚动到指定的坐标
- 语法:
- 元素.scrollTo(x, y)
- 例如
//让页面滚动到y轴1000像素的位置
window.scrollTo(0,1000)
页面尺寸事件
- 会在窗口尺寸改变的时候触发事件:
- resize
window.addEventListener('resize', function () {
//执行的代码
})
- 检测屏幕宽度:
window.addEventListener('resize', function () {
let W = document.documentE1ement.ClientWidth
console.1og(w)
})
页面尺寸事件-获取元素宽高
- 获取宽高:
- 获取元素的可见部分宽高(不包含边框,margin,滚动条等)
- clientWidth和clientHeight
元素尺寸与位置
- 使用场景:
- 前面案例滚动多少距离,都是我们自己算的,最好是页面滚动到某个元素,就可以做某些事。
- 简单说,就是通过js的方式,得到元素在页面中的位置
- 这样我们可以做,页面滚动到这个位置,就可以做某些操作,省去计算了
元素尺寸于位置-尺寸
- 获取宽高:
- 获取元素的自身宽高、包含元素自身设置的宽高、
padding、border - offsetWidth和offsetHeight
- 获取出来的是数值,方便计算
- 注意: 获取的是可视宽高, 如果盒子是隐藏的,获取的结果是0
- 获取元素的自身宽高、包含元素自身设置的宽高、
- 获取位置:
- 获取元素距离自己定位父级元素的左、上距离
- offsetLeft和offsetTop 注意是只读属性
- 获取位置:
- element.getBoundingClientRect()
- 方法返回元素的大小及其相对于视口的位置
总结
| 属性 | 作用 | 说明 |
|---|---|---|
| scrollLeft和scrollTop | 被卷去的头部和左侧 | 配合页面滚动来用,可读写 |
| clientWidth 和 clientHeight | 获得元素宽度和高度 | 不包含border,margin,滚动条 用于js 获取元素大小,只读属性 |
| offsetWidth和offsetHeight | 获得元素宽度和高度 | 包含border、padding,滚动条等,只 读 |
offsetLeft和offsetTop | 获取元素距离自己定位父 级元素的左、上距离 | 获取元素位置的时候使用,只读属性 |
今日单词
| 属性 | 作用 | 说明 |
|---|---|---|
| 事件对象. stopPropagation( ) | 阻止冒泡 | 因为默认就有冒泡模式的存在,所以容易导致事件影响到父级元素 |
| e. preventDefault( ) | 阻止冒泡 | 阻止链接的跳转,表单域跳转 |
| removeEventListener | 解绑事件 | 比如有弹窗解绑之后弹窗出不来 |
综合案例
Dom节点&移动端滑动
日期对象
实例化
- 日期对象:用来表示时间的对象
- 作用:可以得到当前系统时间
- 在代码中发现了
new关键字时,一般将这个操作称为实例化 - 创建一个时间对象并获取时间:
获取当前时间
const date = new Date()
获取指定时间
const date = new Date('2002-5-22')
console.log(date)
时间对象方法
- 因为日期对象返回的数据我们不能直接使用,所以需要转换为实际开发中常用的格式
| 方法 | 作用 | 说明 |
|---|---|---|
| getFullYear() | 获得年份 | 获取四位年份 |
| getMonth() | 获得月份 | 取值为 0 ~ 11 需+1 |
| getDate() | 获取月份中的每一天 | 不同月份取值也不相同 |
| getDay() | 获取星期 | 取值为 0 ~ 6 |
| getHours() | 获取小时 | 取值为 0 ~ 23 |
| getMinutes() | 获取分钟 | 取值为 0 ~ 59 |
| getSeconds() | 获取秒 | 取值为 0 ~ 59 |
时间戳
-
使用场景: 如果计算倒计时效果,前面方法无法直接计算,需要借助于时间戳完成
-
什么是时间戳:
- 是指1970年01月01日00时00分00秒起至现在的毫秒数,它是一种特殊的计量时间的方式
-
算法:
- 将来的时间戳 - 现在的时间戳 = 剩余时间毫秒数
- 剩余时间毫秒数 转换为 剩余时间的 年月日时分秒 就是 倒计时时间
- 比如 将来时间戳 2000ms - 现在时间戳 1000ms = 1000ms
- 1000ms 转换为就是 0小时0分1秒
三种方式获取时间戳:
- 使用 getTime() 方法
const date = new Date()
console.log(date.getTime())
简写 +new Date()
console.log(+new Date())
-
使用 Date.now()
- 无需实例化
但是只能得到当前的时间戳, 而前面两种可以返回指定时间的时间戳
console.log(Date.now())
节点操作
DOM 节点
- DOM节点
DOM树里每一个内容都称之为节点
- 节点类型
元素节点- 所有的标签 比如 body、 div
- html 是根节点
- 属性节点
- 所有的属性 比如 href
- 文本节点
- 所有的文本
- 其他
查找节点
- 关闭二维码案例:
- 点击关闭按钮, 关闭的是二维码的盒子, 还要获取erweima盒子
- 思考:
- 关闭按钮 和 erweima 是什么关系呢?
- 父子关系
- 所以,我们完全可以这样做:
- 点击关闭按钮, 直接关闭它的爸爸,就无需获取erweima元素了
- 节点关系:针对的找亲戚返回的都是对象
- 父节点
- 子节点
- 兄弟节点
父节点查找
parentNode属性- 返回最近一级的父节点 找不到返回为null
子元素.parentNode
子节点查找
- childNodes
- 获得所有子节点、包括文本节点(空格、换行)、注释节点等
children 属性 (重点)- 仅获得所有元素节点
- 返回的还是一个伪数组
父元素.children
兄弟节点查找
- 下一个兄弟节点
nextElementSibling属性
- 上一个兄弟节点
previousElementSibling属性
增加节点
- 很多情况下,我们需要在页面中增加元素
- 比如,点击发布按钮,可以新增一条信息
- 一般情况下,我们新增节点,按照如下操作:
- 创建一个新的节点
- 把创建的新的节点放入到指定的元素内部
创建节点
- 即创造出一个新的网页元素,再添加到网页内,一般先创建节点,然后插入节点
- 创建元素节点方法:
//创造一个新的元素节点
document.createElement('div')
追加节点
- 要想在界面看到,还得插入到某个父元素中
- 插入到父元素的最后一个子元素:
//插入到这个父元素的最后
父元素.appendChild(要插入的元素)
- 插入到父元素中某个子元素的前面
//插入到父元素中某个子元素的前面
父元素.insertBefore(要插入的元素,在哪个元素前面)
克隆节点
- 特殊情况下,我们新增节点,按照如下操作:
- 复制一个原有的节点
- 把复制的节点放入到指定的元素内部
元素.cloneNode(布尔值)
- cloneNode会克隆出一个跟原标签一样的元素,括号内传入布尔值
- 若为true,则代表克隆时会包含后代节点一起克隆
- 若为false,则代表克隆时不包含后代节点
- 默认为false
删除节点
- 若一个节点在页面中已不需要时,可以删除它
- 在 JavaScript 原生DOM操作中,要删除元素必须通过父元素删除
父元素.removeChild(要删除的元素/子元素)
- 注:
- 如不存在父子关系则删除不成功
- 删除节点和隐藏节点(display:none) 有区别的: 隐藏节点还是存在的,但是删除,则从html中删除节点
M端事件
- 移动端也有自己独特的地方。比如触屏事件 touch(也称触摸事件),Android 和 IOS 都有。
- 触屏事件 touch(也称触摸事件),Android 和 IOS 都有。
- touch 对象代表一个触摸点。触摸点可能是一根手指,也可能是一根触摸笔。触屏事件可响应用户手指(或触控笔 )对屏幕或者触控板操作。
- 常见的触屏事件如下:
| 触屏touch事件 | 说明 |
|---|---|
| touchstart | 手指触摸到一个DOM元素时触发 |
| touchmove | 手指在一个DOM元素上滑动时触发 |
| touchend | 手指在一个DOM元素上移开时触发 |
JS插件
- 插件: 就是别人写好的一些代码,我们只需要复制对应的代码,就可以直接实现对应的效果
- 学习插件的基本过程
- 熟悉官网,了解这个插件可以完成什么需求
- 看在线演示,找到符合自己需求的demo
- 查看基本使用流程
- 查看APi文档,去配置自己的插件
- 注意: 多个swiper同时使用的时候, 类名需要注意区分
-
本地文件路径
使用方法:引入css/js.mini文件,然后打开对应序号的效果开始往自己网页上Ctrl+C/V
重绘和回流(理论)
-
浏览器是如何进行界面渲染的
- 解析(Parser)HTML,生成DOM树(DOM Tree)
- 同时解析(Parser) CSS,生成样式规则 (Style Rules)
- 根据DOM树和样式规则,生成渲染树(Render Tree)
- 进行布局 Layout(回流/重排):根据生成的渲染树,得到节点的几何信息(位置,大小)
- 进行绘制 Painting(重绘): 根据计算和获取的信息进行整个页面的绘制
- Display: 展示在页面上
-
回流(重排)
- 当 Render Tree 中部分或者全部元素的尺寸、结构、布局等发生改变时,浏览器就会重新渲染部分或全部文档的过 程称为 回流。
-
重绘
- 由于节点(元素)的样式的改变并不影响它在文档流中的位置和文档布局时(比如:color、background-color、 outline等), 称为重绘。
重绘不一定引起回流,而回流一定会引起重绘。 -
会导致回流(重排)的操作:
- 页面的首次刷新
- 浏览器的窗口大小发生改变
- 元素的大小或位置发生改变
- 改变字体的大小
- 内容的变化(如:input框的输入,图片的大小)
- 激活css伪类 (如::hover)
- 脚本操作DOM(添加或者删除可见的DOM元素)
简单理解影响到布局了,就会有回流 -
思考下述代码的重绘重排过程:
let s = document.body.style
s.padding = "2px" //重排+重绘
s.border = "1px solid red" //再一次重排+重绘
s.color = "blue" //再一次重绘
s.backgroundcolor = "#ccc" //再一次 重绘
s.fontsize = "14px" //再一次重排+重绘
今天多一份拼搏,明日多一份欢笑
综合案例
Bom操作
window对象
BOM(浏览器对象模型)
- BOM(Browser Object Model ) 是浏览器对象模型
- window对象是一个全局对象,也可以说是JavaScript中的顶级对象
- 像document、alert()、console.log()这些都是window的属性,基本BOM的属性和方法都是window的。
- 所有通过var定义在全局作用域中的变量、函数都会变成window对象的属性和方法
- window对象下的属性和方法调用的时候可以省略window
定时器-延时函数
- JavaScript 内置的一个用来让代码延迟执行的函数,叫 setTimeout
- 语法:
setTimeout(回调函数,等待的毫秒数)
- setTimeout 仅仅只执行一次,所以可以理解为就是把一段代码延迟执行, 平时省略window
- 清除延时函数:
let timer = setTimeout(回调函数,等待的毫秒数)
clearTimeout(timer)
- 注意点
- 延时器需要等待,所以后面的代码先执行
- 每一次调用延时器都会产生一个新的延时器
JS执行机制
同步任务
- 先执行不需要等待的程序,执行完再去执行待执行的程序
异步任务
- 用于存放待执行程序,比如点击,倒计时
详细请看ppt/文档
由于主线程不断的重复获得任务、执行任务、再获取任务、再执行,所以这种机制被称为事件循环( event loop)。
location对象
- location 的数据类型是对象,它拆分并保存了 URL 地址的各个组成部分
常用属性和方法:
search属性获取地址中携带的参数,符号 ?后面部分
console.log(location.search)
hash属性获取地址中的啥希值,符号 # 后面部分
console.log(location.hash)
//后期vue路由的铺垫,经常用于不刷新页面,显示不同页面,比如 网易云音乐
reload方法用来刷新当前页面,传入参数 true 时表示强制刷新
<button>刷新</button>
<script>
let btn = document.querySelector('button')
btn.addEventListener('click',function (){
location.reload(true)
//强制刷新 类似ctrl + f5
})
</script>
href属性获取完整的 URL 地址,对其赋值时用于地址的跳转
//可以得到当前文件URL地址
console.log(location.href)
//可以通过js方式跳转到目标地址
location.href = 'http://www.baidu.com'
navigator对象
- navigator的数据类型是对象,该对象下记录了浏览器自身的相关信息
- 通过 userAgent 检测浏览器的版本及平台
// 检测 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'
}
})()
histroy对象
- history 的数据类型是对象,主要管理历史记录, 该对象与浏览器地址栏的操作相对应,如前进、后退、历史记录等
| history对象方法 | 作用 <> |
|---|---|
| back() | 可以后退功能 |
| forward() | 前进功能 |
| go(参数) | 前进后退功能 参数如果是1 前进一个页面 如果是-1 后退1个页面 |
history 对象一般在实际开发中比较少用,但是会在一些 OA 办公系统中见到
本地储存
本地存储介绍
- 以前我们页面写的数据一刷新页面就没有了,是不是?
- 随着互联网的快速发展,基于网页的应用越来越普遍,同时也变的越来越复杂,为了满足各种各样的需求,会经常 性在本地存储大量的数据,HTML5规范提出了相关解决方案
-
、数据存储在用户浏览器中
-
设置、读取方便、甚至页面刷新不丢失数据
-
容量较大,sessionStorage和localStorage约 5M 左右
- 常见的使用场景:
- todomvc.com/examples/va… 页面刷新数据不丢失
本地存储分类
- 作用: 可以将数据永久存储在本地(用户的电脑), 除非手动删除,否则关闭页面也会存在
- 特性:
- 可以多窗口(页面)共享(同一浏览器可以共享)
- 以键值对的形式存储使用
- 语法
localStorage存储数据
//localStorage.setItem('键','值')
localStorage.setItem(数据名, 数据)
//改 如果原来有这个键,则是改,如果么有这个键是增
localStorage.setItem('数据名', '新数据')
localStorage获取数据
localStorage.getItem('数据名')
localStorage删除数据
localStorage.removeItem('数据名')
- 浏览器查看本地数据
本地存储分类- sessionStorage
- 特性:
- 生命周期为关闭浏览器窗口
- 在同一个窗口(页面)下数据可以共享
- 以键值对的形式存储使用
- 用法跟localStorage 基本相同
存储复杂数据类型
存储复杂数据类型
- 本地只能存储字符串,无法存储复杂数据类型.
- 解决:需要将复杂数据类型转换成JSON字符串,再存储到本地
- 语法:
JSON.stringify(复杂数据类型)
<script>
const obj = {
uname: 'pink老师',
age: 18,
gender: '女'
}
// 1.复杂数据类型存储必须转换为 JSON字符串存储
localStorage.setItem('obj', JSON.stringify(obj))
// JSON 对象 属性和值有引号,而是引号统一是双引号
</script>
将复杂数据转换成JSON字符串 存储 本地存储中
取出复杂数据类型
- 因为本地存储里面取出来的是字符串,不是对象,无法直接使用
- 解决:把取出来的字符串转换为对象
- 语法:JSON.parse(JSON字符串)
<script>
const obj = {
uname: 'pink老师',
age: 18,
gender: '女'
}
// 取
// 1. 把JSON字符串转换为 对象
const str = localStorage.getItem('obj')
console.log(JSON.parse(str))
//上下两种方式都可以
const str = JSON.parse(localStorage.getItem('obj'))
console.log(str)
</script>
将JSON字符串转换成对象
取出时候使用
综合案例
正则&阶段案例
正则表达式
介绍
- 正则表达式(Regular Expression)是用于匹配字符串中字符组合的
模式。在 JavaScript中,正则表达式也是对象 - 通常用来查找、替换那些符合正则表达式的文本,许多语言都支持正则表达式
- 正则表达式在 JavaScript中的使用场景:
- 例如验证表单:用户名表单只能输入英文字母、数字或者下划线, 昵称输入框中可以输入中文(
匹配)- 比如用户名: /^[a-z0-9_-]{3,16}$/
- 过滤掉页面内容中的一些敏感词(
替换),或从字符串中获取我们想要的特定部分(提取)等 。
- 例如验证表单:用户名表单只能输入英文字母、数字或者下划线, 昵称输入框中可以输入中文(
语法
介绍
- 我们想要查找是否有戴眼镜的人, 怎么做呢?
-
定义规则: 戴眼镜的
-
根据规则去查找:找到则返回
- 正则同样道理,我们分为两步:
-
定义规则
-
查找
- 比如:查找下面文本中是否包含字符串 '前端'
let str = 'IT培训,前端开发培训,web前端培训,软件测试培训,产品经理培训'
语法
- JavaScript 中定义正则表达式的语法有两种,我们先学习其中比较简单的方法:
- 定义正则表达式语法:
const 变量名 = /表达式/
其中 / / 是正则表达式字面量
比如:
const 变量名 = /前端/
- 判断是否有符合规则的字符串:
- test() 方法 用来查看正则表达式与指定的字符串是否匹配
regObj.test(被检测的字符串)
比如:
//要检测的字符串
const str = 'IT培训,前端开发培训,web前端培训,软件测试培训,产品经理培训'
//1.定义正则表达式,检测规则
const reg = /前端/
//2.检测方法
console.log(reg.test(str)) //true
//如果正则表达式与指定的字符串匹配 ,返回true,否则false
- 检索(查找)符合规则的字符串:
- exec() 方法 在一个指定字符串中执行一个搜索匹配
regObj.exec(被检测字符串)
比如:
//要检测的字符串
const str = 'IT培训,前端开发培训,web前端培训,软件测试培训,产品经理培训'
//1.定义正则表达式,检测规则
const reg = /前端/
//2.检测方法
console.log(reg.exec(str)) //返回的是数组如下图:
//如果匹配成功,exec() 方法返回一个数组,否则返回null
元字符
介绍
- 普通字符:
- 大多数的字符仅能够描述它们本身,这些字符称作普通字符,例如所有的字母和数字。 也就是说普通字符只能够匹配字符串中与它们相同的字符。
- 元字符(特殊字符)
- 是一些具有特殊含义的字符,可以极大提高了灵活性和强大的匹配功能。
- 比如,规定用户只能输入英文26个英文字母,普通字符的话 abcdefghijklm…..
- 但是换成元字符写法: [a-z]
- 是一些具有特殊含义的字符,可以极大提高了灵活性和强大的匹配功能。
- 参考文档:
边界符(表示位置,开头和结尾,必须用什么开头,用什么结尾)
- 正则表达式中的边界符(位置符)用来提示字符所处的位置,主要有两个字符
- 如果 ^ 和 $ 在一起,表示必须是精确匹配
| 边界符 | 说明 |
|---|---|
| ^ | 表明匹配行首的文本(以谁开始) |
| $ | 表明匹配行尾的文本(以谁结束) |
- 正则表达式中的边界符(位置符)用来提示字符所处的位置,主要有两个字符
console.log(/哈/.test('哈')) // true
console.1og(/二哈/.test('二哈')) // true
console.1og(/二哈/.test('很二哈哈')) // true
//^开头
console.log(/^二哈/.test('很二哈哈')) // false
console.log(/^二哈/.test('二哈很傻')) // true
//$结尾
console.log(/^二哈$/.test('二哈很傻')) // false
console.log(/^二哈$/.test('二哈二哈')) // false
console.log(/^二哈$/.test('二哈')) // true
量词 (表示重复次数)
- 量词用来
设定某个模式出现的次数
| 量词 | 说明 |
|---|---|
| * | 重复零次或更多次 * 表示重复 0 次或多次 |
| + | 重复一次或更多次 + 表示重复至少 1 次 |
| ? | 重复零次或一次 ? 表示重复 0 次或1次 |
| {n} | 重复n次 |
| {n,} | 重复n此或更多次 |
| {n,m} | 重复n到m次 |
注意: 逗号左右两侧千万不要出现空格
量词用来 设定某个模式出现的次数
// *表示重复0次或者更多次
console.log(/^哈*$/.test('')) // true
console.log(/^哈*$/.test('哈')) // true
console.log( /^哈*$/.test('哈哈哈')) // true
// +表示重复1次或者更多次
console.log(/^哈+$/.test('')) // false
console.log(/^哈+$/.test('哈')) // true
console.log(/^哈+$/.test( '哈哈哈')) // true
//?表示重复0次或者1次0||1
console.1og(------')
console.log(/^哈?$/.test('')) // true
console.log(/^哈?$/.test('哈')) // true
console.log(/^哈?$/.test('哈哈哈')) // fasle
console.log(/^哈{2}$/.test('')) // false
console.log(/^哈{2}$/.test('哈')) // false
console.log(/^哈{2}$/.test('哈哈')) // true
console.log(/^哈{2}$/.test('哈哈哈')) // false
//{n,}是>= n的意思
console.log(/^哈{2,}$/.test('')) // false
console.log(/^哈{2,}$/.test('哈')) // false
console.log(/^哈{2,}$/.test('哈哈')) // true
console.log(/^哈{2,}$/.test('哈哈哈')) // true
// {n,m}是次数>= n<= m的意思注意,逗号左右千万不要有空格
console.log(/^哈{2,4}$/.test('')) // false
console.log(/^哈{2,4}$/.test('哈')) // false
console.log(/^哈{2,4}$/.test('哈哈')) // true
console. log(/^哈{2,4}$/.test('哈哈哈')) // true
console. log(/^哈{2,4}$/.test('哈哈哈哈')) // true
console. log(/^哈{2,4}$/.test('哈哈哈哈哈')) // false
字符类 (比如 \d 表示 0~9)
- 匹配字符集合
- 后面的字符串只要包含 abc 中任意一个字符,都返回 true
//只要中括号里面的任意字符出现都返回为true
console.log(/[abc]/.test('andy')) // true
console.1og(/[abc]/.test('baby')) // true
console.1og(/[abc]/.test('cry')) // true
console.log(/[abc]/.test('die')) // false
- 里面加上 - 连字符
- 使用连字符 - 表示一个范围
console.log(/^[a-z]$/.test('c')) //true
- 比如:
- [a-z] 表示 a 到 z 26个英文字母都可以
- [a-zA-Z] 表示大小写都可以
- [0-9] 表示 0~9 的数字都可以
- 认识下:
腾讯QQ号:^[1-9][0-9]{4,}$(腾讯QQ号从10000开始)
- 里面加上 ^ 取反符号
- 比如:
- [^a-z] 匹配除了小写字母以外的字符
- 注意要写到中括号里面
- . 匹配除换行符之外的任何单个字符
- 预定义:指的是 某些常见模式的简写方式。
| 预定类 | 说明 |
|---|---|
| \d | 匹配0-9之间的任一数字,相当于[0-9] |
| \D | 匹配所有0-9以外的字符,相当于[^0-9] |
| \w | 匹配任意的字母、数字和下划线,相当于[A-Za-Z0-9] |
| \W | 除所有字母、数字和下划线以外的字符,相当于[^A-Za-z0-9_] |
| \s | 匹配空格(包括换行符、制表符、空格符等),相等于[\t\r\n\v\f] |
| \S | 匹配非空格的字符,相当于[^\t\r\n\v\f] |
- 日期格式: ^\d{4}-\d{1,2}-\d{1,2}
修饰符
- 修饰符约束正则执行的某些细节行为,如是否区分大小写、是否支持多行匹配等
- 语法:
/表达式/修饰符
- i 是单词 ignore 的缩写,正则匹配时字母不区分大小写
- g 是单词 global 的缩写,匹配所有满足正则表达式的结果
console.log(/a/i.test('a')) // true
console.log(/a/i.test('A')) // true
- 替换 replace 替换
- 语法:
字符串.replace(/正则表达式/,'替换的文本')