BOM
全称 browser object model - 浏览器对象模型
浏览器对象模型:使用对象组成的结构对浏览器进行操作
navigator
存储浏览器信息
appName ==> application name ==> 应用程序名称 ==> 记录的是浏览器名称
history
操作浏览器的历史记录
back():后退一个页面
btn.onclick = function() {
// 回退
history.back()
}
forward():前进一个页面
btn.onclick = function() {
// 前进
history.forward()
}
go():前进或后退多个页面
btn.onclick = function() {
// history.back()
// go方法可以前进或后退多个页面
// 数字是几,就前进或后退几个页面
// 前进用正数 后退用负数
history.go(-2)
}
location
操作地址栏url
属性href:获取/设置完整的url
获取完整的地址
location.href
console.log(location.href);
设置完整的地址
location.href = 新地址
location.href = 'http://baidu.com'
属性search:获取地址url中的参数/数据部分
设置地址栏参数
location.search = ?键=值&键=值
location.search = '?a=1&b=2'
获取地址栏参数
location.search
console.log(location.search);
属性hash:获取地址栏中的锚点
设置锚点
location.hash = #单词
location.hash = '#abc'
获取锚点
location.hash
console.log(location.hash);
window的属性
获取浏览器窗口大小
innerWidth属性
console.log(innerWidth);
innerHeight属性
console.log(innerHeight);
都会包含滚动条的宽和高
window方法
弹出层
window.alert(123)
window.confirm(123)
window.prompt('143qwasdf')
全局定义的函数,都属于window的方法
全局定义的变量,都属于window的属性
定时器
setInterval(函数, 毫秒数):让函数每隔毫秒数,就执行一次,会不停的执行下去
利用返回值,可以停止定时器 - clearInterval(返回值)
setTimeout(函数, 毫秒数):让函数延迟毫秒数执行一次,就这一次
返回这个定时器在页面中是第几个,利用返回值,可以停止定时器 - clearTimeout(返回值)
var a = setTimeout(function() {
console.log(1111);
}, 3000)
console.log(a);
btn.onclick = function() {
clearTimeout(a)
}
window.open(url):打开新的标签页
window.open('http://baidu.com') // 新打开一个标签页
window.close():关闭窗口
window.scrollTo(x, y):设置卷去的距离
控制滚动条位置
window.scrollTo(200, 500)
window事件
window.onload:当所有资源加载完成后,触发执行
window.onresize:当浏览器窗口大小发生改变,触发执行
window.onresize = function() {
console.log(innerWidth, innerHeight);
}
window.onscroll:当浏览器卷去的距离发生改变,触发执行
window.onscroll = function() {
console.log(666);
}
DOM
document object model 文档对象模型,由对象组成的结构操作html文档
获取标签
document.querySelector(css选择器)
获取满足css选择器的第一个标签,返回一个标签
var li = document.querySelector('ul li')
console.log(li);
document.querySelectorAll(css选择器)
获取所有满足css选择器的标签,返回一个集合
var lis = document.querySelectorAll('ul li')
console.log(lis);
document.getElementById('id名') - 只能获取到一个标签
console.log( document.getElementById('var') );
document.getElementsByClassName('类名') - 只要标签有这个类名,就都可以获取到
console.log( document.getElementsByClassName('uu') );
console.log( document.getElementsByClassName('uu')[0] );
document.getElementsByTagName('标签名')
console.log( document.getElementsByTagName('ul') );
console.log( document.getElementsByTagName('ul')[0] );
document.getElementsByName('name属性的值')
console.log( document.getElementsByName('myul') );
html基本结构标签
html标签
console.log( document.documentElement );
body标签
console.log( document.body );
head标签
console.log( document.head );
网页标题
console.log( document.title ); // 获取标签
document.title = '这是我的网页' // 设置网页标题
获取标签名
标签.tagName
console.log( oDiv.tagName );
操作内容
文本内容
标签.innerText:给标签设置内容
oDiv.innerText = '哈哈'
获取标签内容:标签.innerText
console.log(oDiv.innerText);
带标签的内容
oDiv.innerHTML = '<b>哈哈</b>' //设置
console.log(oDiv.innerHTML); //获取
表单标签的内容
标签.value = 值
ipt.value = '张三'
标签.value
console.log(ipt.value);
操作属性
设置属性 标签.setAttribute(属性名, 属性的值)
box.setAttribute('name', 'dd')
box.setAttribute('name', 'mydd')
获取属性的值 标签.getAttribute(属性名)
console.log( box.getAttribute('name') );
console.log( box.getAttribute('class') );
删除属性 标签.removeAttribute(属性名)
box.removeAttribute('name')
样式操作
获取标签样式:getComputedStyle(标签)--- 返回所有css键值对组成的对象
console.log( getComputedStyle(box) );
设置样式
标签.style.css键 = 值 ---- 设置到行内
box.style['margin-left'] = '100px'
如果css键中包含连字符,有歧义,就必须使用中括号语法了
将带有连字符的css键使用小驼峰写法
box.style.marginLeft = '100px'
box.style.width = '400px'
box.style.height = '400px'
类名操作
直接操作class属性值
标签.className = 值
标签.className
给box添加类名mybox
console.log(box.className);
box.className = 'mybox' // 重新设置class属性的值
标签.classList
add():添加一个类名
box.classList.add('mybox')
remove():删除一个类名
box.classList.remove('mybox')
contains():判断是否有这个类名
console.log( box.classList.contains('mybox') );
toggle():让类名在删除和添加之间切换
btn.onclick = function() {
// 让某个类名在删除和添加之间切换
box.classList.toggle('mybox')
}
获取卷去的距离
有文档声明
document.documentElement.scrollTop
没有文档声明
document.body.scrollTop
万能写法
var t = document.documentElement.scrollTop || document.body.scrollTop
// console.log(t);
document.documentElement.scrollTop = document.body.scrollTop = 数字
短路运算
使用逻辑运算符 && 和 || 给变量进行赋值
var 变量 = 值1 && 值2
如果左边为true,就会将右边的值赋值给变量
如果左边为false,就会将左边的值赋值给变量
var b = 2 && 3;
console.log(b); // 3
var c = 5 && false
console.log(c); // false
var 变量 = 值1 || 值
如果左边为true,就会将左边的值赋值给变量
如果左边为false,就会将右边的值赋值给变量
var a = 1 || 2;
console.log(a); // 1
var a = 0 || 2
console.log(a); // 2
国庆倒计时案例
<div class="box">
距离国庆还有: <span>0</span> 天 <span>0</span> 小时 <span>0</span> 分钟 <span>0</span> 秒
</div>
// 获取所有标签
var spans = document.querySelectorAll('span')
daojishi()
function daojishi() {
// 获取国庆的时间日期对象中的时间戳
var guoqing = new Date('2023-10-1 0:0:0')
guoqing = guoqing.getTime()
// 获取当前的时间戳
var now = new Date()
now = now.getTime()
// 求毫秒差
var diff = guoqing - now
// 根据毫秒差换算天、小时、分钟、秒
var day = parseInt(diff / 1000 / 60 / 60 / 24)
var hour = parseInt(diff / 1000 / 60 / 60) % 24
var minute = parseInt(diff / 1000 / 60) % 60
var second = parseInt(diff / 1000) % 60
// 将天、小时、分钟、秒放在对应的span标签中
spans[0].innerText = day
spans[1].innerText = hour
spans[2].innerText = minute
spans[3].innerText = second
}
// 设置定时器
setInterval(daojishi, 1000)
网页换皮肤案例
<div class="box">
<img src="./images/1.jpg" alt="">
<img src="./images/2.jpg" alt="">
<img src="./images/3.jpg" alt="">
</div>
<button>按钮</button>
<script>
var btn = document.querySelector('button')
var box = document.querySelector('.box')
var imgs = document.querySelectorAll('.box img')
btn.onclick = function() {
// 将box的height设置为200px
// box.style.height = '200px'
var height = getComputedStyle(box).height
if (height === '200px') {
box.style.height = 0
} else {
box.style.height = '200px'
}
}
// 给每个图片都添加点击事件
for (var a = 0; a < imgs.length; a++) {
imgs[a].onclick = function() {
// 获取当前图片的路径名
var imgPath = this.getAttribute('src')
// 将当前图片设置为body的背景
// document.body.style.background = 'url(' + imgPath + ') no-repeat 0 0/100% 100%'
document.body.style.backgroundImage = 'url(' + imgPath + ')'
document.body.style.backgroundRepeat = 'no-repeat'
document.body.style.backgroundSize = '100% 100%'
box.style.height = '0'
}
}
</script>
节点操作
节点:html文档的每一个组成部分,最小的组成单位
创建标签
document.createElement(标签名)
var div = document.createElement('div')
div.innerText = '盒子'
div.className = 'box'
div.style.width = '200px'
div.setAttribute('name', 'mybox')
console.log(div);
插入标签
父.appendChild(子)
父.insertBefore(新, 旧)
document.body.appendChild(div)
document.body.insertBefore(div, ul)
获取标签
获取子标签 - 父.children
console.log( ul.children );
获取某个标签的上一个兄弟标签 - 标签.previousElementSibling
var fourth = document.querySelector('.fourth')
console.log(fourth);
console.log( fourth.previousElementSibling );
下一个兄弟标签 - 标签.nextElementSibling
console.log ( fourth.nextElementSibling );
获取父标签 - 子.parentElement
console.log( fourth.parentElement );
第一个子 - 父.firstElementChild
console.log( ul.firstElementChild );
最后一个子 - 父.lastElementChild
console.log( ul.lastElementChild );
替换标签
父.replaceChild(新, 旧的子标签)
var b = document.createElement('b')
b.innerText = '加粗'
// 使用b标签替换掉fourth
ul.replaceChild(b, fourth)
删除标签
父.removeChild(子)
ul.removeChild(fourth)
复制标签
标签.cloneNode()
// 如果要将标签中的内容和子标签都复制出来,就给方法添加参数true
console.log( fourth.cloneNode(true) );
标签的尺寸大小
带边框
标签.offsetWidth
标签.offsetHeight
var w2 = box.offsetWidth
var h2 = box.offsetHeight
console.log(w2, h2);
不带边框
标签.clientWidth
标签.clientHeight
var box = document.querySelector('.box')
var w1 = box.clientWidth
var h1 = box.clientHeight
console.log(w1, h1);
标签位置
参照设置过定位的直系祖宗标签
标签.offsetLeft
标签.offsetTop
var l1 = big.offsetLeft
var t1 = big.offsetTop
console.log(l1, t1);
var small = document.querySelector('.small')
var l2 = small.offsetLeft
var t2 = small.offsetTop
console.log(l2, t2);
边框的厚度
标签.clientLeft
标签.clientTop
var box = document.querySelector('.box')
var l = box.clientLeft
console.log(l);
var t = box.clientTop
console.log(t);
窗口大小不包含滚动条
document.documentElement.clientWidth
document.documentElement.clientHeight
var w1 = innerWidth
var h1 = innerHeight
var w2 = document.documentElement.clientWidth
var h2 = document.documentElement.clientHeight
console.log(w1, h1);
console.log(w2, h2);
回流和重绘
浏览器的渲染过程
浏览器会先解析html成DOM树,同时解析css成样式规则;
将DOM树和css规则合成渲染树
布局:计算标签关系、位置、大小
喷绘:给标签涂颜色
让浏览器显示
回流和重绘
回流:操作需要重新布局
如果动态操作了标签的节点、位置、大小,浏览器需要重新计算标签的大小和位置,也就造成了回流
setStyle(div, {
width: 0,
height: '8px',
border: '1px solid #000',
position: 'absolute',
left: '100px',
top: 0,
// 设置旋转的原点
transformOrigin: '1px 100px',
transform: 'rotate('+0*6+'deg)'
})
}
function setStyle(ele, obj) {
for (var key in obj) {
ele.style[key] = obj[key]
}
// 循环一次,就设置一次,回流很多次
// 优化:将所有的样式拼接成一个style属性的值 === > 字符串;通过设置style属性,造成1次回流即可
str=width:100px;height:100px;border:1px solid #000;
// 设置标签的style属性,值为str
var arr = []
for (var key in obj) {
arr.push( key + ':' + obj[key] + ';' )
}
// console.log(arr);
var str = arr.join('')
// console.log(str);
// ele.setAttribute('style', str)
// js还提供了设置样式的属性 - cssText
ele.style.cssText = str
}
重绘:操作需要重新喷绘
如果动态操作了标签的颜色等属性,就需要重新喷绘,也就造成了重绘
<style>
.box{
width: 100px;
height: 100px;
background-color: #f00;
}
</style>
<body>
<div class="box"></div>
</body>
<script>
document.querySelector('.box').style.backgroundColor = '#0f0'
</script>
都影响了渲染性能
优化
合并样式修改
cssText style属性 类名
优化批量的DOM操作
隐藏,操作,显示
ul.style.display = 'none'
for (var a = 0; a < 10; a++) {
var li = document.createElement('li')
li.innerText = a + 1
ul.appendChild(li)
}
ul.style.display = 'block'
复制,操作,替换
var newUL = ul.cloneNode(true)
// console.log(newUL);
for (var a = 0; a < 10; a++) {
var li = document.createElement('li')
li.innerText = a + 1
newUL.appendChild(li)
}
console.log(newUL);
ul.parentElement.replaceChild(newUL, ul)
文档碎片(虚拟标签)
var fg = document.createDocumentFragment() // 创建文档碎片
for (var a = 0; a < 10; a++) {
var li = document.createElement('li')
li.innerText = a + 1
fg.appendChild(li)
}
console.log(fg);
// 将文档碎片放在ul中
ul.appendChild(fg)
优化定时器中的DOM操作
将定时器中获取标签的操作,放在定时器外面
// 获取原本的宽度
var w = small.offsetWidth
timer = setInterval(function() {
...
},1000)
手动封装两个数字的数学运算函数
function math(a, b, operator) {
// 将两个数字转成字符串
a = '' + a
b = '' + b
// 判断这两个数是否整数
// 判断字符串是否包含 .
if (!a.includes('.') && !b.includes('.')) {
// 直接进行整数运算就好
var result
switch (operator) {
case '+':
result = a + b
break
case '-':
result = a - b
break
case '*':
result = a * b
break
case '/':
result = a / b
break
}
return result
}
// 不是整数
// 找a和b中.所在下标
var aDotIndex = a.indexOf('.')
var bDotIndex = b.indexOf('.')
// 根据下标截取小数点后所有字符串
var aSuffix = a.slice(aDotIndex)
var bSuffix = b.slice(bDotIndex)
// 求最长的位数
var max = Math.max(aSuffix.length, bSuffix.length)
// 计算要乘以的数字
var num = Math.pow(10, max)
// 将两个数字都乘以num
a = a * num
b = b * num
var result
switch (operator) {
case '+':
result = (a + b) / num
break
case '-':
result = (a - b) / num
break
case '*':
result = (a * b) / Math.pow(10, max * 2)
break
case '/':
result = a / b
break
}
return result
}
console.log(math(1, 2, '/'))