BOM :
浏览器的一窗口 window 对象
不同的窗口不共享 window
实际上全局变量的和全局函数都属于window对象的自定义属性和方法
window 对象的属性
navigator 浏览器的相关信息
userAgent(字符串) 可以用于判断用户登录的设备
history 访问历史记录
length 这个窗口打开过几个页面
back() 回退一步
forward() 前进一步
go(-1/1/2)
location 地址栏
host 主机+端口号 www.jd.com:80
hostname 主机 /域名 www.jd.com
port 端口号 80
href 显示地址栏的完整信息 可获取可设置 ‘https://www.jd.com’
location.href = ‘http://www.baidu.com’
protocal 获取协议 http / https
pathname 路径
search 地址栏中问号后面的一串
reload() 刷新页面 不建议过多使用
location.assign(url) 替换当前文档 可以被历史记录
location. replace(url) 替换当前文档 不会被历史记录
location.reload() ==> 取值 ture false 不取值 默认为false
true ==> 刷新页面 不使用缓存
false ==> 刷新页面 使用缓存
location.reload()// 一直会刷新页面
setTimeout(function () {
// location.href = 'http://www.baidu.com'
// location.assign('http://www.baidu.com')
location.replace()
}, 3000)
document (dom就是bom的一部分)
host 主机+端口号 www.jd.com:80
console.log(document);
// doctype 文档声明
console.log(document.doctype);
// documentElement 文档的根对象html
console.log(document.documentElement);
console.log(document.body);
console.log(document.head);
console.log(document.title);
setTimeout(function () {
// title属性可读可写
document.title = '百度一下'
}, 2000)
// console.log(document.div); // undefined自由属性可以,div不是一个页面中必须的,所以undefined
window的方法
open()打开新窗口
window.open(url,name,窗口的特征) 返回值:被打开的窗口
close()关闭窗口
scollBy(x,y) 滚动条 单位像素 移动
scollTo(x,y) 滚动条 单位像素 达到
window事件 即BOM事件👇
元素.onload 当页面所有内容加载完毕之后再执行(文档、css、js、images…)
// onload 页面资源加载完毕之后再执行js
window.onload = function () {
var a = 10;
console.log(a);
var obj = document.getElementById('a');
console.log(obj);
}
元素.onresize 当视口大小发生改变时,触发事件
// 页面尺寸发生改变时触发
window.onresize = function () {
console.log(666);
}
元素.onscoll 当移动滚动条时触发事件
// 页面滚动触发
window.onscroll = function () {
console.log("窗口大小改变ing");
if(window.innerWidth>960){
box.style.background="blue";
}else if(window.innerWidth>750){
box.style.background="pink";
}else if(window.innerWidth>375){
box.style.background="gray";
}else(window.innerWidth>375){
box.style.background="purple";
}
}
元素.onfocus 获取焦点 页面有了焦点就执行
元素.onblur 失去焦点 页面失去焦点就执行
window.onfocus = function () {
console.log(‘获取焦点’);
}
window.onblur = function () {
console.log(‘失去焦点’);
}
DOM页面的宽高问题
1.可视高度 包含滚动条
document.documentElement.innerWidth
document.documentElement.innerHeight
2.可视高度 不包含滚动条
document.documentElement.clientHeight
document.documentElement.clientWidth
- 页面的实际高度(页面被卷去的高度 – 滚动条距离顶部的距离)
document.documentElement.scrollHeight
document.documentElement.scrollWidth
document.documentElement.scrollTop
document.documentElement.scrollLeft
案例👇
被卷的高度= document.documentElement.scrollHeight实际高度-document.documentElement.clientHeight可视高度
案例
返回底部👇
<style>
body {
width: 100%;
height: 3000px;
}
div {
width: 300px;
height: 300px;
position: fixed;
right: 0;
bottom: 0;
background: #000;
}
</style>
<body>
<div id="goback"></div>
</body>
<script>
var root = document.documentElement || document.body;
$("goback").onclick = function () {
root.scrollTop = 0;
console.log(root.scrollTop);
}
function $(id) {
return document.getElementById(id);
}
</script>
判断到达底部
var root=document.documentElement||document.body;
window.onscoll=function(){
//怎样才算到达底部 页面的实际高度-页面的可视高度
//页面在快要底部的时候就要请求新的数据
//随便给一个10
if(root.scrollTop>=root.scrollHeight-root.clientHeight-10){
alert("别拉了 到底了")
}
}
ie的兼容写法 将documentElement替换成(body)
// 获取根元素的兼容写法
var root = document.documentElement || document.body;
console.log(root.clientHeight);
console.log(root.scrollHeight);
console.log(root.scrollTop);
获取内容的方法
innerHTML 可识别标签
value 表单
innerText 不识别标签
document 的获取元素的相关方法(ES5)
document.getElementById("") ==> id 只有一个,唯一性
document.getElementsByClassName("")[0] ==> class有多个,获取的是一个伪数组(拥有长度,可以通过下角标访问,但是不具有数组的拓展方法)
Tag 标签
document.getElementsByTagName("")[0] ==> 标签
name 多用于表单 标签
新增的获取查找元素的方法(ES6)
查询选择器 参数是任意css选择器的写法
querySelector() 找第一个
querySelectorAll()找所有的
获取元素再改变元素的几种方式
ele.innerHTML=new html content
ele.attribute=new value
ele.setAttribute(attribute,value)
ele.style.property=new style
<div id="a"></div>
<p class="a">pppp</p>
<div class="a"></div>
<input type="text" name="username">
<input type="text" name="username2">
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<script>
console.log(document.getElementById('a'));//<div id="a"></div>
console.log(document.getElementsByClassName('a'));//[p.a, div.a]
console.log(document.getElementsByClassName('a')[0]);//<p class="a">pppp</p>
console.log(document.getElementsByTagName("input"));//[input, input, username: input, username2: input]
console.log(document.getElementsByTagName("input")[0]);//<input type="text" name="username">
console.log(document.getElementsByName('username'));// [input]
console.log(document.querySelector('.a'));//类选择器<p class="a">pppp</p>
console.log(document.querySelector('#a'));//id选择器 <div id="a"></div>
console.log(document.querySelector('p'));//标签选择器 <p class="a">pppp</p>
console.log(document.querySelector("ul li"));//<li>1</li>
console.log(document.querySelector("ul li:nth-child(2)"));//<li>2</li>
console.log(document.querySelectorAll("ul li"));//<li>1</li>
//<li>2</li>
//<li>3</li>
添加和删除元素
document.createElement(element) 创建元素
document.removeChild(element) 删除元素
document.appendChild(element) 添加元素
document.replaceChild(element) 替换元素
获取元素后添加事件处理程序
document.getElementById.οnclick=function(){ }
获取元素后获取元素的属性
attributes 获取元素的所有属性
getAttribute() 获取单个属性值
setAttribute(attribute,value) 添加属性 可覆盖
removeAttribute()移除
获取元素后获取元素的类名
className
classList
remove() 删除类名
add() 添加类名
replace(old , new) 替换类名
Contains()查找 返回布尔值
<img src="" alt="">
<a href="" target=""></a>
<div id="a" class="bb" qq="q" data-hh="h"></div>
<script>
var Odiv = document.querySelector("#a");
console.log(Odiv);
// 获取元素
console.log(Odiv.attributes);//id class qq data-hh
// 获取元素的属性值
console.log(Odiv.getAttribute('id'));//a
// 获取元素的单个属性值
Odiv.setAttribute("my", "hh");
// 添加属性
Odiv.setAttribute('class', 'haha hehe')
// 更改属性<div id="a" class="haha hehe" qq="q" data-hh="h" my="hh"></div>
Odiv.removeAttribute("my", "hh");
// 移除属性<div id="a" class="haha hehe" qq="q" data-hh="h"></div>
// 只有自有属性可以简写 obj.id obj.href
// 自定义属性不能简写
console.log(Odiv.id); //a
console.log(Odiv.my); // undefined
// class也是自有属性 但是class是关键字
console.log(Odiv.className); // 字符串haha hehe
console.log(Odiv.classList); // 伪数组["haha", "hehe", value: "haha hehe"]
console.log(Odiv.classList[1]);//hehe
</script>
<style>
ul {
display: flex;
}
li {
list-style: none;
padding: 20px;
}
.active {
color: red;
}
</style>
<body>
<ul>
<li class="item active">首页</li>
<li class="item">新闻中心</li>
<li class="item">企业文化</li>
</ul>
<script>
var oLi1 = document.querySelector("ul li:nth-child(1)");
var oLi2 = document.querySelector("ul li:nth-child(2)");
//oLi2.onclick = function () {
//oLi1.className = 'item';//换
// oLi2.className += ' active';//加
// }
oLi2.onclick = function () {
// this.classList.add("active")
//this永远指向绑定事件的这个对象oLi2
// oLi2.classList.add("active")
oLi1.classList.remove("active")
oLi2.classList.replace("item", "active")
}
//一般把active显示当前页取的类名
</script>
</body>
切换状态👇
var oLis = document.querySelectorAll("ul li");
for (i = 0; i < oLis.length; i++) {
oLis[i].onclick = function () {
for (var j = 0; j < oLis.length; j++) {
oLis[j].classList.remove("active");
}
// this.classList.add("active")
this.className += " active"
}
}
循环绑定事件
事件处理函数是异步的
在事件处理函数中 this指向绑定事件的这个对象
在普通函数中 this指向window
特殊标签(表单标签)的特殊属性
<body>
<button>按钮</button>
<!-- 默认button可以点 disabled="false" -->
<!-- <button disabled="disabled">按钮</button> -->
<input type="text" disabled>
<input type="checkbox" checked="false">
<select name="" id="">
<option value="1">11</option>
<option value="2" selected>22</option>
<option value="3">33</option>
</select>
</body>
<script>
var oBtn = document.querySelector("button");
var oChk = document.querySelector('input[type="checkbox"]');
setTimeout(function () {
oBtn.disabled = true;//点击后就变灰色
oChk.checked = false;//点击不勾选
}, 2000)
</script>
DOM的增删改查
查询
查询指定元素
1.根据id获取元素
document.getElementById(“id属性的值”);
2.根据标签名字获取元素
document.getElementsByTagName(“标签的名字”);
3.根据name属性的值获取元素
document.getElementsByName(“name属性的值”);
4.根据类样式的名字获取元素
document.getElementsByClassName(“类样式的名字”);
5.根据选择器获取元素
document.querySelector(“选择器”);
document.querySelectorAll(“选择器”);
获取到元素后再👇
parentNode 找父元素
children找儿子们
childNodes 找儿子,节点集合(包含换行,标签,文本,注释等节点)
previousSibling 前一个兄弟节点
previousElementSibling 前一个兄弟元素
nextSibling 后一个兄弟节点
nextElementSibling 后一个兄弟元素
firstChild 找第一个子节点 ==childNodes[0]
firstElementChild 找第一个子元素
lastChild
lastElementChild
新增
创建元素 var new=document.createElement(“p”)
插入元素 ele.appendChild(new)插入最后位置
ele.insertBerore(new,old) 把new元素插入到指定的old前面
创建文本 var text=document.createTextNode(‘呵呵’)
插入文本 ele.appendChild(text)
ele.innerHTML += " "
删除
ele.remove() 删除自己
ele.removeChild()删除自己指定的子元素,不能删除隔代子孙
ele.innerHTML = ’ ’ 删除所有的子元素
修改
ele.replaceChild(new,old )
复制(克隆)
cloneNode() 默认false 只复制标签自己
cloneNode(true) 复制标签及子元素
js当中 换行,注释,标签,属性都称为节点
只有标签称为元素 element
有两个特殊属性允许访问完整文档:
document.body - 文档的 body
document.documentElement - 完整文档
nodeType 节点类型 数字(只读)
文本节点 3
标签节点 1
注释节点 8
属性节点 2
nodeName 节点的名称 字符串(只读)
文本节点 #text
标签 P / H3 / DIV
注释 #comment
nodeValue 节点的值 字符串
<div class="a">
111
<p>11</p>
<span>222</span>
<!-- 注释 -->
<h3></h3>
</div>
var oDiv = document.querySelector('div');
var childNodes = oDiv.childNodes;
console.log(childNodes[0].nodeName); // #text
console.log(childNodes[0].nodeType); // 3
console.log(childNodes[0].nodeValue); // 3
console.log(childNodes[1].nodeName); // P
console.log(childNodes[1].nodeType); // 1
console.log(childNodes[1].nodeValue); // null
console.log(childNodes[5].nodeName); // #comment
console.log(childNodes[5].nodeType); // 8
console.log(childNodes[5].nodeValue); // null
console.log(document.nodeType); // 9
console.log(document.doctype.nodeType); // 10
console.log(oDiv.attributes[0].nodeType);
创建新 HTML 元素(节点)
如需向 HTML DOM 添加新元素,您必须首先创建这个元素(元素节点),然后将其追加到已有元素。
实例👇
<div id="div1">
<p id="p1">这是一个段落。</p>
<p id="p2">这是另一个段落。</p>
</div>
<script>
var para = document.createElement("p");//创建新标签元素
var node = document.createTextNode("这是新文本。");
para.appendChild(node);//向<p>元素追加这个文本节点
var element = document.getElementById("div1");//查找一个已有的元素
element.appendChild(para);//已有的元素追加新元素
//var child = document.getElementById("p1");
//element.insertBefore(para, child);//也可以
</script>
<body>
<p>111</p>
<ul id="list"></ul>
<script>
// 页面的回流与重绘 渲染
// 所有css都会引发重绘 不一定回流
// 回流必定会引发重绘
// margin-top translateY
// font-size:100px transform:scale()
// display:none opacity:0 visibility:hidden
var oUl = document.querySelector('#list');
// 创建10个li
// for (var i = 0; i < 10; i++) {
// var oLi = document.createElement('li');
// oLi.innerHTML = i;
// oUl.appendChild(oLi) // 引发10次回流
// }
// 文档碎片
var fragment = document.createDocumentFragment();
console.log(fragment);
for (var i = 0; i < 10; i++) {
var oLi = document.createElement('li');
oLi.innerHTML = i;
fragment.appendChild(oLi)
}
oUl.appendChild(fragment) // 只会引发一次回流
// 要尽量的减少DOM操作
</script>
</body>
css样式可以设置也可以获取
设置
ele.style.color = ‘red’
ele.style.cssText = ‘color:red;font-size:30px’ 可一次性设置多个样式
ele.classList.add(‘c’) 推荐
获取
ele.style.color 只能获取行内样式
getStyle(ele,attr) 自己封装的兼容的函数
getComputedStyle
currentSyle
// 获取样式的兼容写法
function getStyle(ele, attr) {
if (window.getComputedStyle) {
return getComputedStyle(ele)[attr]
}
return ele.currentStyle[attr]
}
var oDiv = document.querySelector('div');
// oDiv.style.color = 'green';
oDiv.style.background = 'gray';
oDiv.style.fontSize = '30px';
// oDiv.style.cssText = "font-size:30px;border:1px solid #000";
oDiv.classList.add('c');
// getComputedStyle(ele).属性
// ele.currentStyle.属性
// console.log(getComputedStyle(oDiv).height);
// console.log(oDiv.currentStyle.height);
console.log(getStyle(oDiv, 'height'));
ele.style.width 获取的是css设置的宽
ele.clientWidth width + padding
ele.offsetWidth width + padding + border
ele.offsetLeft / offsetTop 距离最近的具有定位的祖先元素的距离
事件:被触发并得到回应
事件:事件源+事件处理函数
常见的事件绑定方式
//1.行内js
<button onclick=("fn("hello")")>按钮</button>
function fn(n){
console.log(n)
}
//2.直接获取对象,会覆盖前面的事件
var btn=document.querySelector("button")
btn.onclick=function(){
}
//3.事件监听addEventListener("click",function(){},是否支持捕获流(默认不支持false))
//优势:可同时绑定多个同类型的事件,不会覆盖
btn.addEventListener("click",function(){
console.log(777);
})
//事件监听的兼容写法(IE低版本)
btn.attachEvent("onclick",function(){
console.log(777);
})
事件监听程序的方法允许您向相同元素添加多个事件,同时不覆盖已有事件:
//绑定--封装后的兼容写法
function addEvent(ele,type,cb){
if(window.addEventListener){
ele.addEventListener(type,cb)
}else{
ele.attachEvent("on"+type,cb)
}
}
addEvent("btn","click",function(){
console.log(777);
})
移除事件绑定(用空对象覆盖之前的函数)
<button onclick=("fn("hello")")>按钮</button>
function fn(n){
console.log(n)
}
setTimeout(function(){
btn.onclick=null
},2000)
事件监听方式绑定的方式如果移除需要挨个移除,具名函数好移除
//移除--封装后的兼容写法
function removeEvent(ele,type,cb){
if(window.EventListener){
ele.removeEventListener(type,cb)
}else{
ele.detachEvent("on"+type,cb)
}
}
removeEvent("btn","click",fn1)
//fn1具名函数
案例👇
<button onclick="fn()">按钮</button>
<script>
function fn() {
console.log(2);
}
var oBtn = document.querySelector('button');
setTimeout(function () {
oBtn.onclick = null;
// oBtn.removeEventListener('click', fn1)
// oBtn.removeEventListener('click', fn2)
//不考虑兼容的移除绑定的写法
removeEvent(oBtn, 'click', fn1)
}, 3000)
oBtn.addEventListener('click', function () {
console.log(6);
})
oBtn.addEventListener('click', fn1)
oBtn.addEventListener('click', fn2)
function fn1() {
console.log(7);
}
function fn2() {
console.log(8);
}
//fn写成具名函数好移除
function removeEvent(ele, type, cb) {
if (window.removeEventListener) {
ele.removeEventListener(type, cb)
} else {
ele.detachEvent('on' + type, cb)
}
}
</script>
事件监听的参数实际上有三个
addEventListener(事件类型,事件处理函数,是否支持捕获流)
(默认不支持false捕获流,即默认true冒泡流从内到外))
事件流: 事件捕获阶段,处于目标阶段,事件冒泡阶段
捕获流:从外到内event capturing Netscape
冒泡流:从内到外event bubbling IE
主流浏览器都支持冒泡流
事件对象:浏览器专门记录事件发生的整个过程的一个对象
事件处理函数的第一个参数
//this -> body 绑定事件的对象
//target -> p 指向具体触发事件的标签
//事件对象的兼容写法
document.onclick=function(e){
//event是IE低版本的事件对象
var e=e||event;
var target=e.target||e.srcElement;
}
阻止事件冒泡(不向外传播)
e.stopPropagation();//阻止事件冒泡
if(e.stopPropagation){
e.stopPropagation()
}else{
//低版本IE阻止事件冒泡的方式
e.cancleBubble=true
}
案例👇
<style>
.big {
width: 500px;
height: 500px;
background-color: #000;
border: 1px solid #000;
}
.box {
width: 300px;
height: 300px;
background-color: #0f0;
border: 1px solid #0f0;
margin: 100px;
}
.small {
width: 100px;
height: 100px;
margin: 100px;
background-color: #f00;
}
</style>
<div class="big">
<div class="box">
<div class="small">1111111</div>
</div>
</div>
<script>
// 事件不向外传播 --- 阻止事件冒泡
$('.big').addEventListener('click', function () {
console.log('big');
})
$('.box').addEventListener('click', function () {
console.log('box');
})
$('.small').addEventListener('click', function (e) {
var e = e || event;
// 阻止事件冒泡
// e.stopPropagation();
if (e.stopPropagation) {
e.stopPropagation()
} else {
// 低版本IE阻止事件冒泡的写法
e.cancelBubble = true
}
console.log('small');
})
function $(e) {
return document.querySelector(e)
}
</script>
事件委托(委托给别人做)
原理:事件冒泡(给父元素添加事件,判断哪个子元素触发的)
性能:页面上的事情处理函数越多,性能就越差
解决两个问题:
1. 事件处理函数过多 消耗性能
2. 无法给未来的对象添加事件
事件委托优点:
只有一个事件处理函数
可以给未来的对象添加事件绑定 !!!
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
var oUl = document.querySelector('ul')
setTimeout(function () {
var li = document.createElement('li');
li.innerHTML = '我是后来的6';
oUl.appendChild(li)
}, 1000)
oUl.addEventListener('click', function (e) {
// console.log(666);
var e = e || event;
var target = e.target || e.srcElement;
console.log(target.innerHTML);
console.log(this);
// this 和 target 的区别
//this 永远指向绑定事件的这个对象
//target 更具体的标签 p h3 li ...
})