DOM
DOM树
获取元素
-
根据ID获取 getElementById()
document.getElementById() //参数是大小写敏感的字符串
2021-5-15 -
根据标签名获取 getElementsByTagName()
- 知否知否,应是绿肥红瘦
- 知否知否,应是绿肥红瘦
- 知否知否,应是绿肥红瘦
- 知否知否,应是绿肥红瘦
- 知否知否,应是绿肥红瘦
- 生僻字
- 生僻字
- 生僻字
- 生僻字
- 生僻字
-
通过HTML5新增的方法获取
document.getElementsByClassName('类名'); //根据类名获得某些元素的集合
document.querySelector('选择器'); //返回指定选择器中的第一个元素对象 例:var firstBox = document.querySelector('.box'); // .表示类 var nav = document.querySelector('#nav');//#表示id var li = document.querySelector('li'); //标签
document.querySelectorAll('选择器'); //根据指定选择器返回所有元素对象集合 例:var allBox = document.querySelectorAll('.box');
-
获取body html标签
//获取body var bodyEle = document.body;
//获取html var htmlELe = document.documentElement;
事件
1.事件由三部分组成: 事件源 事件类型 事件处理程序(事件三要素)
事件源: 事件被触发的对象 谁 按钮
事件类型: 如何触发 什么事件 比如 鼠标点击 还是鼠标经过 还是键盘按下
事件处理程序: 通过一个函数赋值的方式 完成
<body>
<button id="btn">唐伯虎</button>
<script>
var btn = document.getElementById('btn');
//btn事件源 onclick 时间类型 function 事件处理程序
btn.onclick = function () {
alert('点秋香');
}
</script>
2.执行事件的步骤
1)获取事件源
2)注册事件(绑定事件)
3)添加事件处理程序(采取函数赋值形式)
3. 常用的鼠标事件
onclick 鼠标点击左键触发
onmouseover 鼠标经过触发
onmouseout 鼠标离开触发
onfocus 获得鼠标焦点触发
onblur 失去鼠标焦点触发
onmousemove 鼠标移动触发
onmouseup 鼠标弹起触发
onmousedown 鼠标按下触发
操作元素
1.改变元素内容
element.innerText 从起始位置到终止位置的内容,但它不识别html标签,同时空格和换行也会被去掉
element.innerHTML 从起始位置到终止位置的全部内容,包括html标签,同时保留空格和换行
这两个标签是可读写的,可以获取元素里面的内容
<body>
<p>
我是文字
<span>123</span>
</p>
<script>
var p = document.querySelector('p');
console.log(p.innerText);
console.log(p.innerHTML);
</script>
</body>
········································································
输出结果:
我是文字 123
------------------------------
我是文字
<span>123</span>
2. 常用元素的属性操作
src、href、id、title、alt等
3.表单元素的属性操作
表单属性:
type、value、checked、selected、disabled
<body>
<button>按钮</button>
<input type="text" value="输入内容">
<script>
// 1.获取元素
var btn = document.querySelector('button');
var input = document.querySelector('input');
// 2.注册事件 处理程序
btn.onclick = function () {
//表单里面的值 文字内容通过value而不是innerText innerHTML来处理
input.value = "被点击了";
// btn.disabled = true;
//this指向的是事件函数的调用者btn
this.disabled = true;
}
</script>
</body>
4. 样式属性操作
1.element.style 行内样式操作
2.element.className 类名样式操作
//JS修改style样式操作 产生的是行内样式 CSS权重比较高
//JS 里面的样式采用驼峰命名法 比如fontSize backgroundColor
//className会覆盖原先的类名
<head>
<style>
div: {
width:200px;
height:200px;
background-color: pink;
}
</style>
</head>
<body>
<div></div>
<script>
var div = document.querySelector('div');
div.onclick = function() {
div.style.backgroundColor = 'purple';
this.style.width = '250px';
}
</scrip>
</body>
------------------------------------------------------------
<head>
<style>
div: {
width:200px;
height:200px;
background-color: pink;
}
.change {
background-color: purple;
color: #fff;
font-size: 25px;
margin-top: 100px;
}
</style>
</head>
<body>
<div class="first">文本</div>
<script>
var div = document.querySelector('div');
div.onclick = function() {
// 当样式比较多或者功能复杂 可以用className直接修改类
this.className = 'change';
//如果想在原先的类的基础上加新的类
this.className = 'first change';
}
</scrip>
</body>
5.自定义属性的操作
1.获得属性的值
element.属性 获得内置的属性
element.getAttribute('属性') 获得新的自定义的属性
例:
<div id="demo" index="1"></div>
//id是内置属性 index是自定义属性
var div = document.querySelector('div');
console.log(div.id);
2.设置属性值
element.属性 = '值' 设置内置属性值
element.setAttribute('属性','值') 主要针对自定义属性
例:
div.id = "test";
3.移除属性
element.removeAttribute('属性')
例:
div.removeAttribute('index')
//H5里面规定 所有自定义属性都以data-开头
新增的获取自定义属性的方法element.dataset.index 或者 element.dataset['index']
dataset 是存放了所有以data开头的自定义属性的集合
比如上面的自定义属性index 改成data-index
兼容性不太行 建议用getAttribute
<div data-index="2" data-list-name="andy"></div>
var div = document.querySelector('div');
console.log(div.dataset.index); // 2 这里就不用加data-了
console.log(div.dataset['index'];//2
console.log(div.dataset.listName);//andy 注意如果自定义属性里面有多个-连接的单词 获取需要驼峰命名法
节点操作(获取元素的另一种方法)
1.节点概述
一般来说,元素、属性、文本全是节点。节点至少拥有nodeType(节点类型)、nodeName(节点名称)和nodeValue(节点值)三个基本属性
元素节点的nodeType为1
属性节点的nodeType为2
文本节点的nodeType为3(文本节点包括文字,空格,换行等)
2.节点层级
- 父子节点
node.parentNode 得到的是离节点最近的父级节点,找不多返回null
node.childNodes 得到的是指定节点的子节点的集合,该集合为实时更新的集合。包含元素节点、文本节点等等
node.children 是一个只读属性,返回所有的子元素节点,只返回子元素节点
node.firstChild 返回第一个子节点 不管是文本节点还是元素节点
node.lastChild 同上
node.firstElementChild 返回第一个子元素节点 有兼容性问题
node.lastElementChild 返回最后一个子元素节点 有兼容性问题
实际开发中 一般用node.children[0]来表示第一个子元素节点,一般用node.children[node.children.length-1]来表示最后一个子元素节点
- 兄弟节点
node.nextSibling 返回当前元素的下一个兄弟节点 找不到则返回null。同样也包含了所有的节点
node.previousSibling 返回当前元素的上一个兄弟节点。同上
node.nextELementSibling 返回当前元素的下一个兄弟元素节点 找不到则返回null。IE9以上才兼容
node.previousElementSibling 返回当前元素的上一个兄弟元素节点 同上
为了解决兼容性问题,自己封装一个函数:
function getNextElementSibling(element) {
var el = element;
while (el = el.nextSibling) {
if (el.nodeType === 1) {
return el;
}
}
return null;
}
3. 创建节点 & 添加节点
document.createElement('tagName')
该方法创建由tagName指定的HTML元素。也称为动态创建元素节点
node.appendChild(child) 将一个节点添加到指定父节点的子节点列表的末尾。node父级 child是子集
node.insertBefore(child,指定元素) 将 child添加到父节点的指定子节点前面。
4.删除节点
node.removeChild(child) 从DOM中删除一个子节点 ,返回被删除的子节点
小tips:元素里面阻止链接跳转 可以href='javascript:;'
5.复制节点(克隆节点)
node.cloneNode() 返回调用该方法的节点的一个副本,也称为克隆节点
如果参数为空或者false,则是浅拷贝,只复制标签,不复制里面的内容;如果括号里面为true,则为深拷贝。复制标签和内容。
6.三种 动态创建元素的区别
document.write() 是直接将内容写入页面的内容流,但文档执行完毕,则他会导致页面全部重绘
innerHTML 创建多个元素效率更高(不要拼接字符串,而是采用数组形式拼接) 结构稍微复杂
createElement()创建多个元素效率稍微低一点,但结构更清晰
注册事件(绑定事件)
1.注册事件概述
给元素添加事件,称为注册事件或者绑定事件
注册事件由两种方式**:传统方式和方法监听注册方式**
传统注册方式:
- 利用on开头事件 onclick
- btn.onclick = function(){}
- 特点:注册事件的唯一性:同一个元素同一个事件只能设置一个处理函数,最新的处理函数会覆盖前面的函数
方法监听注册事件:
- addEventListener()他是一个方法
- IE9之前不支持,可以用attachEvent()
- 特点:同一个元素同一个事件可以注册多个监听器
2.addEventListener事件监听方式
eventTarget.addEventListener(type, listener[, useCapture])
该方法将制定的监听器注册到eventTarget(目标对象)上,当该对象触发制定的事件时,就会执行事件处理函数。
该方法接受三个参数
type:事件类型字符串 比如click mouseover 注意这里不要带on
listener:事件处理函数 事件发生时,会调用该函数
useCapture:可选参数 布尔型 默认false
3.解绑事件
传统方式:
element.onclick = null;
方法监听注册方式:
element.removeEventListener(type, listener) //addEventListener()
element.detachEvent(type,listener) //attachEvent()
divs[1].addEventListener('click',fn); //要用这种移除方法 就要给function起个名字
function fn() {
alert(22);
divs[1].removeEventListener('click',fn); //该函数弹出一次后就解绑自己
}
divs[2].attachEvent('onclick',fn1); //要用这种移除方法 就要给function起个名字
function fn1() {
alert(222);
divs[2].detachEvent('click',fn1); //该函数弹出一次后就解绑自己
}
4.DOM事件流
事件流描述的是从页面接受事件的顺序
事件发生的时候会在元素节点之间按照特定的顺序传播,这个传播过程就是DOM事件流
比如给一个div注册了点击事件:
1.捕获阶段
2.当前目标阶段
3.冒泡阶段
onclick 和 attachEvent只能得到冒泡阶段
addEventListener 第三个参数如果是true,得到捕获阶段 ;如果是false或者默认 表示冒泡阶段。如果点击一个元素,元素和它的父元素都有监听事件,那么捕获阶段会先执行父元素的函数,再执行该元素的函数。冒泡则相反。
5.事件对象
var div = document.querySelector('div');
div.onclick = function(event){
console.log(event);
}
div.addEventListener('click',function(e){console.log(e);})
//event就是一个事件对象,写在小括号里,当做形参来看
//事件对象只有有了事件才会存在,系统自己创建
//事件对象是我们事件的一系列相关数据的集合 跟事件相关的,比如鼠标点击就包含了鼠标的信息
//这个事件对象我们可以自己命名 比如event evt e等
//事件对象也有兼容性问题 ie678通过window.event 兼容性写法 event = event || window.event;
e.target 返回的是触发事件的对象(元素) this返回的是绑定事件的对象(元素)
即 e.target 点击了哪个元素,就返回哪个元素 this是哪个元素绑定了这个点击事件 就返回谁
var a = document.querySelector('a');
a.addEventListener('click',function(e) {
e.preventDefault();
})
6.事件委托(事件代理)
原理:不是每个子节点单独设置事件监听器,而是事件监听器设置在其父节点上,然后利用冒泡原理影响每个子节点
<ul>
<li>知否知否,应是绿肥红瘦</li>
<li>知否知否,应是绿肥红瘦</li>
<li>知否知否,应是绿肥红瘦</li>
<li>知否知否,应是绿肥红瘦</li>
<li>知否知否,应是绿肥红瘦</li>
</ul>
//点击每个li都弹出对话框,以前需要给每个li都注册事件,辛苦且访问DOM次数越多,延长整个页面的交互就绪事件
//事件委托:给ul注册事件,然后利用事件对象的target来找到当前点击的li,因为点击li事件会冒泡到ul上,ul有注册事件,就会触发监听器
//只访问了一次DOM 提高交互速度
小tips:禁止选中 文字和禁止右键菜单
document.addEventListener('contextmenu', function(e) {
e.preventDefault();
}) // 禁止右键菜单
document.addEventListener('selectstart', function(e) {
e.preventDefault();
})
7.鼠标事件对象
8.键盘事件对象
三个事件执行顺序:keydown->keypress->keyup
keyup keydown 不区分事件大小写 a和A都得到65
keypress区分
e.keyCode 键盘按键的ASCII码值
BOM
1.BOM概述
BOM即浏览器对象模型,提供了独立于内容而与浏览器窗口进行交互的对象,核心对象是window
BOM比DOM更大,它包含DOM
window对象是浏览器的顶级对象,它有双重角色
1.它是JS访问浏览器窗口的一个接口
2.它是一个全局对象,定义在全局作用域中的变量、函数都会变成window对象的属性和方法
var num = 10;
console.log(num);
console.log(window.num); //在调用的时候可以省略window
function fn(){
console.log(11);
}
fn();
window.fn();
2.window对象的常见事件
-
窗口加载事件 等页面所有内容都加载完了才执行这个函数
window.onload = function(){} //传统刚注册事件方式只能写一次 如果有多个,以最后一个为准 或者 window.addEventListener('load',function(){}); //不存在这个问题
document.addEventListener('DOMContentLoaded',function(){}) 该事件仅当DOM加载完成时候触发 不包括样式表 图片flash等等 IE9以上才支持
-
调整窗口大小事件 只要窗口大小发生像素变化就会触发
window.onresize = function(){} window.addEventListener = ("resize",function(){});
3.定时器
setTimeout(调用函数 [, 延迟的毫秒数]) 用于设置一个定时器,该定时器在定时器到期后执行调用函数 window. 可以省略
setTimeout(function() {
console.log('时间到了');
},2000);
//调用函数可以直接写函数,也可以写函数名 或者 '函数名()'
function callback (){
console.log('时间到了');
}
var time1 = setTimeout(callback,3000);
var time2 = setTimeout('callback',5000);
停止setTimeout()定时器window.clearTimeout (timeoutID);
window.可以省略
window.clearTimeout (timeoutID);
var timer = setTimeout(function(){}, 5000);
btn.addEventListener('click', function() {
clearTimeout(timer);
})
setInterval()计时器 每间隔一段时间 就去调用这个函数
setInterval(回调函数,[间隔的毫秒数]);
两个计时器基本相同,只是一个只执行一次 一个循环执行
停止setInterval()计时器
clearInterval();
4.this指向
//1.全局作用域或者普通函数中this指向全局对象window(定时器里面的this指向window)
console.log(this); //window
function fn() {
console.log(this);
}
window.fn(); // window
window.setTimeout(function() {
console.log(this);
},1000); //window
//2.方法调用中 谁调用 this就 指向谁
var o = {
sayHi: function() {
console.log(this); // this 指向的是o这个对象
}
}
o.sayHi();
var btn = document.querySelector('button');
btn.onclick = function(){
console.log(this); //this 指向btn
}
//3.构造函数中this指向构造函数的实例
function Fun() {
console.log(this); //this指向的是fun 实例对象
}
var fun = new Fun();
5.JS 执行机制
JavaScript 语言的一大特点就是单线程,也就是说,同一个时间只能做一件事。这是因为 Javascript 这门脚本语言诞生的使命所致——JavaScript 是为处理页面中用户的交互,以及操作 DOM 而诞生的。比如我们对某个 DOM 元素进行添加和删除操作,不能同时进行。 应该先进行添加,之后再删除。
为了解决这个问题,利用多核 CPU 的计算能力,HTML5 提出 Web Worker 标准,允许 JavaScript 脚本创建多个线程。于是,JS 中出现了同步和异步。
**同步:**前一个任务结束后再执行后一个任务,程序的执行顺序与任务的排列顺序是一致的、同步的。比如做饭的同步做法:我们要烧水煮饭,等水开了(10分钟之后),再去切菜,炒菜。
**异步:**你在做一件事情时,因为这件事情会花费很长时间,在做这件事的同时,你还可以去处理其他事情。比如做饭的异步做法,我们在烧水的同时,利用这10分钟,去切菜,炒菜。
同步任务:都放在主线程上执行 ,形成一个执行栈
异步任务:通过回调函数实现的,有以下三类
1.普通事件:click ,resize
2.资源加载 如load、error等
3.定时器,包括setInterval、setTimeout等
异步任务相关回调函数添加到任务队列中(也叫消息队列)
JS执行机制
1.先执行栈中的同步任务
2.异步任务(回调函数)放入任务队列中
3.一旦执行栈中的所有同步任务执行完毕,系统就会按次序读取任务队列中的异步任务,于是被读取的异步任务结束等待状态,进入执行栈,开始执行
事件循环参见文章:【JS】深入理解事件循环,这一篇就够了!(必看) - 知乎 (zhihu.com)
6.location对象
location.assign() 可以跳转页面 ,记录浏览历史,也可以后退
7.navigator对象
包含有关浏览器的信息,有很多属性 最常用的userAgent
8.history对象
与浏览器的历史记录进行交互 该对象包含用户(在浏览器窗口中)访问过的URL
PC端网页特效
1.offset:动态的得到钙元素的位置(偏移)、大小等
offset与style的区别
2.client 客户端 获取元素可视区的相关信息
3.立即执行函数
不需要调用,立马能够自己执行的函数
作用:创建了一个独立的作用域,避免了命名冲突问题
//写法
(function() {})(); 或者 (function(){}()); //加个小括号表示调用
(function(形参) {})(实参); 或者 (function(形参){}(实参));
4.scroll
滚动的,利用scroll属性可以动态得到该元素的大小,滚动距离等
注意:元素被卷去的头部是element.scrollTop,如果是页面被卷去的头部是window.pageYOffset
scrollHeight是返回内容的高度,clientHeight是返回盒子的高度
5.mouseenter 和 mouseover的区别
当鼠标移动到元素上时会触发mouseenter事件,与mouseover的区别是,mouseover经过自身盒子会触发,经过子盒子还会触发(冒泡)。mouseenter只在经过自身盒子触发,不会冒泡。
跟mouseenter搭配 鼠标离开mouseleave 同样不会冒泡
6.动画函数封装
动画实现原理:通过定时器setInterval()不断移动盒子位置
实现步骤:
1.获得盒子当前位置
2.让盒子在当前位置上加1个移动距离
3.利用定时器不断重复操作
4.加上一个结束定时器的条件
5.注意此元素需要添加定位,才能使用element.style.left
简单动画函数封装:(obj 目标对象, target 目标位置)
function animate(obj,target) {
clearInterval(obj.timer);//先清除以前的定时器,只保留当前的一个定时器执行
obj.timer = setInterval(function() { //将计时器作为obj的一个方法,不声明新的变量,不占用新的内存,同时不同的obj有不同的timer
if (obj.offsetLeft == target) {
clearInterval(obj.timer);
}
obj.style.left = obj.offsetLeft + 1 + 'px';
},30);
}
var div = document.querySelector('div');
var span = document.querySelector('span');
animate(div,300);
animate(span,200);
缓动动画效果原理
思路:
1.让盒子每次移动的距离慢慢变小,速度会慢慢落下来
2.核心算法:(目标值 - 现在的位置) / 10 作为每次移动的距离 步长
function animate(obj,target) {
clearInterval(obj.timer);
obj.timer = setInterval(function() {
var step = (target - obj.offsetLeft) / 10; //步长公式
step = step > 0?Math.ceil(step) : Math.floor(step); //step大于0向右走,向上取整,反之向下取整
if (obj.offsetLeft == target) {
clearInterval(obj.timer);
}
obj.style.left = obj.offsetLeft + step + 'px';
},30);
动画函数添加回调函数
函数可以作为一个参数,将这个函数作为参数传到另一个函数里面,当另一个函数执行完之后,再执行传进去的这个函数,这个过程就叫回调
function animate(obj,target, callback) {
clearInterval(obj.timer);
obj.timer = setInterval(function() {
var step = (target - obj.offsetLeft) / 10;
step = step > 0?Math.ceil(step) : Math.floor(step);
if (obj.offsetLeft == target) {
clearInterval(obj.timer);
if (callback) { //回调函数执行
callback();
}
}
obj.style.left = obj.offsetLeft + step + 'px';
},30);
btn.addEventListener('click', function() {
animate(span, 800, function() { //回调函数 animate里面其他步骤执行完 执行这个function
alert('你好吗');
});
})
节流阀
移动端
触屏事件
触摸事件对象 TouchEvent
TouchEvent是一类描述手指在触屏的状态变化的事件。用于描述一个或多个触电,使得开发者可以检测触点的移动,增加和减少等等
div.addEventListener('touchstart',function(e) {
console.log(e);
console.log(e.touches);
console.log(e.targetTouches);
console.log(e.changedTouches);
});
classList 属性 返回元素的类名
<div class="one two"></div>
var div = document.querySelector('div');
console.log(div.classList); // ['one','two']
//添加类名 追加类名 不覆盖之前的类名
div.classList.add('three');
//删除类名
div.classList.remove('three');
//切换类名 有则去掉 无则添加
div.classList.toggle('bg');
本地存储
window.sessionStorage
1.生命周期为关闭浏览器窗口
2.在同一个窗口(页面)下数据可以共享
3.以键值对的形式存储使用
存储数据
sessionStorage.setItem(key,value)
获取数据
sessionStorage.getItem(key)
删除数据
sessionStorage.removeItem(key)
删除所有数据
sessionStorage.clear();
window.localStorage
1.生命周期永久有效,除非手动删除 否则关闭页面也会存在
2.可以多窗口(页面)共享(同一浏览器可以共享)
3.以键值对形式存储
方法同sessionStorage
Promise:
1.Promise使用
注意:1.执行器函数executor里面改变状态方法有三种:resolve()、reject()和抛出异常。抛出异常会让Promise变为失败状态。
注意:then方法,里面可以写一个参数,onResolved,可以省略onRejected。如果只想写一个onRejected,那么要写成(null,onRejected)
注意:4.Promise.resolve(value) 如果传入的值不是promise对象,则返回一个成功的promise对象。如果传入的是一个promise对象,则参数的结果决定了resolve的结果
let p1 = new Promise((resolve,reject) => {
resolve('OK');
})
let p2 = Promise.resolve('Success');
let p3 = Promise.resolve('Oh Yeah');
const result = Promise.all([p1,p2,p3]); //成功的promise
2.Promise关键问题
- 一个Promise指定多个成功/失败回调函数,都会调用吗?
当promise改变为对应状态时,都会调用
2.改变promise状态和指定回调函数谁先谁后?
都有可能。如果先指定的回调(只是说定义,而不是执行),那么当状态发生改变,回调函数就会调用得到数据。如果先改变状态,那么当指定回调时,回调函数就会调用,得到数据。
3.例题 来判断异步同步的问题
let p = new Promise((resolve, reject) => {
resolve('OK')
})
let result = p.then(value => {
console.log(value); //2.then方法为微任务,执行完第一个console.log之后执行then,于是return之后,result状态变为成功
return value
},reason => {
console.warn(reason);
})
console.log(result); //1.此时result只是进行了定义,但是后面的函数没有执行,没有确定result的状态
setTimeout(() => {
console.log(result)
},1000);
依次输出:
Promise {[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined} // console.log(result)输出
OK
Promise {[[PromiseStatus]]: "fulfilled", [[PromiseValue]]: OK}
async与await
async函数
1.函数的返回值为promise对象
2.promise对象的结果由async函数执行的返回值决定
(返回规则同then方法)
async function main(){
let p =new Promise((resolve,reject) => {
resolve('OK');
})
let res = await p;
console.log(res);//OK
let res2 = await 10;
console.log(res2); //10
//promise失败了需要try catch捕获
}