获取DOM节点
// 注:id相同,只选择第1个
document.getElementById()
document.getElementsByClassName()
// 选择符合选择器的第1个元素
document.querySelector()
// 选择所有符合条件的元素,返回类数组
document.querySelectorAll()
DOM内容、样式、属性
// 节点内容
// 1. innerHTML
// 可以书写HTML语法
var box1=document.querySelector(".box1");
box1.innerHTML="<ul><li>鼠</li><li>牛</li></ul>";
// 2. innerText
// 纯文本
// 3. document.write();
// 只能将文本追加到</body>前
// 解析文本中的标签内容
// 节点样式
// 1. - 变 驼峰命名法,相当于添加了行内样式
box1.style.fontSize="50px";
box1.style.color="pink";
var link=document.querySelector("p>a");
link.href="https://www.baidu.com/";
link.target="blank";
// 2.更改多个样式时,可以放在类中,className会覆盖以前的类
box1.className = 'box box-style1';
// 3. classList 追加,删除,切换类名
// classList.contains('类名')
box.classList.add('box-border');
box.classList.toggle('box-style2'); //无->有;有->无
box.classList.remove('box-border');
//属性
box.setAttribute('style','font-size:100px');
let n= box.getAttribute("style");
//自定义属性
box.setAttribute('data-n','10');
let n= box.getAttribute("data-n");
console.log(n);
DOM新建移动克隆删除
// 新建节点
let li1 = document.createElement("li");
ul.appendChild(li1);
ul.insertBofore(标签名,在该元素前);
//移动节点
//将ul下的结点li1 移动到ul2下
ul2.appendChild(li1);
// 删除节点
ul.removeChild(li1);
// 克隆节点
// true深度克隆,包含后代结点。默认false,不含后代结点
box.appendChild( ul.cloneNode(true) )
结点关系
// 元素节点 即不包含文本节点,空文本节点,注释节点等
// children
// parentNode
// firstElementChild
// lastElementChild
// previousElementsSibling
// nextElementSibling
DOM性能优化
let ul = document.querySelector('ul')
// 创建文档片段,没有插入到DOM树中
let frag = document.createDocumentFragment()
for (let i = 0; i < 10; i++) {
let li = document.createElement('li')
li.innerHTML = `<h1>${i}</h1>`
frag.appendChild(li)
}
ul.appendChild(frag)
事件绑定与事件流
1.elem.onEventType = fun
- 给同一元素的同一事件类型添加多个事件,会覆盖
2.elem.addEventListener(“eventType”,fun,[false])
- 能给同一元素的同一事件类型添加多个事件,不会覆盖
- 默认冒泡阶段触发,true设置为捕获阶段触发
捕获:从外到内触发同名事件
冒泡:从内到外触发同名事件
事件类型
// click
// dblclick
// mousedown
// mouseup
// mousemove
//mouseover mouseout 有冒泡 可使用事件委托
//mouseenter mouseleave不冒泡
// focus获得焦点 blur失去焦点
// Keydown 键盘按下 Keyup 键盘弹起
// input 文本域输入监听事件
// change 表单里的值发生变化且失去焦点时
事件对象e
// 事件对象e
// 鼠标位置属性:
type 事件类型
clientX、clientY 光标相对于浏览器可见窗口的左上角
offsetX、offsetY 光标相对于当前DOM元素的左上角
pageX、pageY 光标相对于整张网页(比如网页有滚动条)
//触发事件的DOM元素
e.target
// 键盘按键属性:
key 按下的键盘键值
// 方法:
阻止事件流 e.stopPropagation();
阻止默认行为 e.preventDefault(); 或 return false
事件委托
通过事件冒泡,将子元素的事件委托给父元素触发
<body>
<h2>输入内容</h2>
<input type="text">
<ul></ul>
<script>
let input = document.querySelector('input')
let ul = document.querySelector('ul')
// 添加li元素
input.addEventListener('keyup', function (e) {
if (e.key === 'Enter') {
let li = document.createElement('li')
li.innerHTML = input.value
ul.appendChild(li)
}
})
// 删除点击的li元素
ul.addEventListener('click', function (e) {
ul.removeChild(e.target)
})
</script>
</body>
offset
<!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;
padding: 10px;
border: 10px solid #ccc;
/* box-sizing: border-box; */
background-color: pink;
margin-top: 20px;
}
</style>
</head>
<body>
<div></div>
</body>
<script>
let div = document.querySelector('div')
// 盒子大小:width+padding+border
console.log(div.offsetWidth);
console.log(div.offsetHeight);
// 盒子距离页面左边、顶部距离
console.log(div.offsetLeft); //8 浏览器默认
console.log(div.offsetTop); //20 垂直方向外边距塌陷
</script>
</html>
放大镜
<!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>
.box {
position: relative;
width: 350px;
height: 350px;
border: 1px solid #000;
margin: 50px;
}
.box>.mask {
position: absolute;
top: 0;
left: 0;
width: 100px;
height: 100px;
background-color: rgba(0, 0, 0, 0.5);
display: none;
}
.big {
position: absolute;
top: 0;
left: 380px;
width: 400px;
height: 400px;
overflow: hidden;
display: none;
}
/*
大图片大小x
350/100 = 400/x 得x=1400
*/
.big>img {
position: absolute;
width: 1400px;
left: 0;
top: 0;
}
</style>
</head>
<body>
<div class="box">
<img src="./small.jpg.avif" alt="">
<div class="mask"></div>
<div class="big">
<img src="./big.jpg.avif" alt="">
</div>
</div>
</body>
<script>
let box = document.querySelector('.box')
let mask = document.querySelector('.mask')
let bigBox = document.querySelector('.big')
let bigImg = document.querySelector('.big>img')
box.onmousemove = function (e) {
// 1.遮罩层移动
let x = e.clientX - box.offsetLeft - 50
let y = e.clientY - box.offsetTop - 50
if (x < 0 || y < 0 || x > box.offsetWidth - mask.offsetWidth || y > box.offsetHeight - mask.offsetHeight) return
mask.style.left = x + 'px'
mask.style.top = y + 'px'
// 2.大图片移动left,已知遮罩层移动x
// x/350 = left/1400 得 left
bigImg.style.left = -(1400 * x / 350) + 'px'
bigImg.style.top = -(1400 * y / 350) + 'px'
}
box.onmouseenter = function(){
mask.style.display = 'block'
bigBox.style.display = 'block'
}
box.onmouseleave = function(){
mask.style.display = 'none'
bigBox.style.display = 'none'
}
</script>
</html>
scroll
<!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>
body {
margin: 0;
padding: 0;
}
.active {
position: static;
width: 100%;
height: 50px;
background-color: pink;
}
</style>
</head>
<body>
<p>第1个p标签</p>
<p>第2个p标签</p>
<p>第3个p标签</p>
<p>第4个p标签</p>
<p>第5个p标签</p>
<p>第6个p标签</p>
<p>第7个p标签</p>
<p>第8个p标签</p>
<p class="active">第9个p标签</p>
<p>第10个p标签</p>
<p>第11个p标签</p>
<p>第12个p标签</p>
<p>第13个p标签</p>
<p>第14个p标签</p>
<p>第15个p标签</p>
<p>第16个p标签</p>
<p>第17个p标签</p>
<p>第18个p标签</p>
<p>第19个p标签</p>
<p>第20个p标签</p>
<p>第21个p标签</p>
<p>第22个p标签</p>
<p>第23个p标签</p>
<p>第24个p标签</p>
<p>第25个p标签</p>
<p>第26个p标签</p>
<p>第27个p标签</p>
<p>第28个p标签</p>
<p>第29个p标签</p>
<p>第30个p标签</p>
</body>
<script>
let p = document.querySelector('.active')
let pTop = p.offsetTop
window.onscroll = function () {
if (document.documentElement.scrollTop > pTop) {
p.style.position = 'fixed'
p.style.top = 0
} else {
p.style.position = 'static'
}
}
</script>
</html>
client
可视区宽高
<!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;
padding: 10px;
margin: 20px;
background-color: pink;
overflow: auto;
}
</style>
</head>
<body>
<div>很多文字很多文字很多文字很多文字很多文字很多文字很多文字很多文字很多文字很多文字很多文字很多文字很多文字很多文字很多文字很多文字很多文字很多文字很多文字很多文字很多文字很多文字很多文字很多文字很多文字很多文字很多文字很多文字很多文字很多文字很多文字很多文字很多文字很多文字很多文字很多文字很多文字很多文字很多文字很多文字很多文字很多文字很多文字很多文字</div>
</body>
<script>
let div = document.querySelector('div')
// 179width(去除滚动条宽度) + 20padding
console.log(div.clientWidth);
// 200height + 20padding
console.log(div.clientHeight);
</script>
</html>
排他思想
let divs = document.querySelectorAll('div');
for (let i = 0; i < divs.length; i++) {
divs[i].addEventListener('click', function () {
//法1 排他思想
// for (let j = 0; j < divs.length; j++) {
// divs[j].classList.remove('pink');
// }
//法2 找到有pink类的DOM对象,删除pink类
document.querySelector('.pink').classList.remove('pink');
// this指向点击的div
this.classList.add('pink');
});
}
开关思想
单按钮随机点名
<!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>
.box {
width: 800px;
margin: 0 auto;
text-align: center;
}
.box>.container {
margin-bottom: 20px;
background-color: pink;
overflow: hidden;
}
.box>.container div {
float: left;
width: 80px;
line-height: 30px;
border: 1px solid #000;
margin: 0 20px 20px;
}
.active {
background-color: green;
}
</style>
</head>
<body>
<div class="box">
<div class="container">
</div>
<button>开始</button>
</div>
</body>
<script>
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
let container = document.querySelector('.container')
// 创建添加元素
arr.forEach((item) => {
let newDiv = document.createElement('div')
newDiv.innerHTML = item
container.appendChild(newDiv)
})
// 按钮
let btn = document.querySelector('button')
let divs = document.querySelectorAll('.box>.container div')
function getRandomIntInclusive(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min; //含最大值,含最小值
}
let timer = null
btn.onclick = function () {
if (btn.innerText === '开始') {
timer = setInterval(() => {
// 排他
for (let i = 0; i < divs.length; i++) {
divs[i].classList.remove('active')
}
// 随机
divs[getRandomIntInclusive(0, arr.length - 1)].classList.add('active')
}, 100);
btn.innerText = '暂停'
} else {
clearInterval(timer)
btn.innerText = '开始'
}
}
</script>
</html>
定时器与延时器
setInterval( func , time )、clearInterval()
setTimeout( func, time )、clearTimeout()
定时器与延时器均为异步语句,宏任务队列