DOM、BOM

74 阅读12分钟

一、DOM

1.元素的增删改查

1.获取元素

document.documentElement // 1.1 获取html根标签 
document.body.scrollTop || document.documentElement.scrollTop; // 滚动距离浏览器兼容处理
document.documentElement.scrollTop = "0";  // 返回顶部 实例
document.documentElement.offsetWidth  // 当前页面的宽度
document.documentElement.offsetHeight  // 当前页面的高度

document.body  //  1.2 获取 body
document.getElementById("id名"); // 1.3 获取id名的单个元素
document.getElementsByClassName("类名"); // 1.4 获取 class类名的集合 (html5)
document.getElementsByTagName("标签名"); // 1.5 获取 标签名 的集合
document.querySelector("css任意选择器"); // 1.6 获取css任意选择器的第一个 (html5)
document.querySelectorAll("css任意选择器"); // 1.7 获取 css 任意选择器的集合 (html5)

// 返回值:元素对象  
var time = document.getElementById("time");
console.log(time);  // <div>2019-10-10</div>
console.log(typeof time); //object
console.dir(time); // div#time  可以查看元素对象的所有属性和方法

2.修改元素

// 1.改变元素的内容 element.innerText + element.innerHTML 都可读写内容
element.innerHTML = new html content;  // 1. 改变元素的 innerHTML 推荐使用
box.innerHTML = "<h1> Hello world !!!</h1>";   // 示例
time.innerHTML = getDate(); 
// 注意:innerText 不识别html标签,去除空格和换行

// 2.属性操作 src href id className title
element.attribute = new value;  // 2. 改变 HTML 元素的属性值
document.querySelector("input").placeholder = "请输入用户名";  // 示例

element.setAttribute(attribute, value); // 3. 改变 HTML 元素的属性值
document.querySelector("input").setAttribute("placeholder", "请输入用户名");  // 示例

// 3.样式属性操作
// 注意:js里的样式采取驼峰命名法 比如fontSize、backgroundColor
// js修改style样式操作,产生的是行内样式,css 权重比较高
element.style.property = new style; // 4. 改变 HTML 元素的样式
box.style.width = "120px"; // 示例
// 点击时 添加类
female.onclick = function(){ 
  this.className="current";
  male.className = "";
 }


// 4.表单元素的属性操作
// type、value、checked、selected、disabled
//  案例:仿京东显示隐藏密码
<div class="box">
<label for="">
<img src="images/close.png" alt="" id="eye">
</label>
<input type="password" name="" id="pwd">
</div>
<script>
// 1. 获取元素
var eye = document.getElementById('eye');
var pwd = document.getElementById('pwd');
// 2. 注册事件 处理程序
var flag = 0;
eye.onclick = function() {
  // 点击一次之后, flag 一定要变化
  if (flag == 0) {
    pwd.type = 'text';
    eye.src = 'images/open.png';
    flag = 1; // 赋值操作
  } else {
    pwd.type = 'password';
    eye.src = 'images/close.png';
    flag = 0;
  }
}
</script>

3.添加和删除元素

document.createElement(element)  // 创建 HTML 元素
document.appendChild(element)    // 添加 HTML 元素
document.removeChild(element)    // 删除 HTML 元素
document.replaceChild(element)   // 替换 HTML 元素

2.offset、client、scroll系列属性

1.offset偏移-获取元素的大小和坐标

// offsetParent:获取距离当前元素最近的定位父元素的节点,如果父元素没有定位,父元素此时是body;
// **offsetLeft、offsetTop 是距离offsetParent 的偏移**,如果没有定位父元素,那是相对于body的距离
// 注意: offsetLeft 是【只读】属性
// offsetWidth 、offsetHeight 是自身宽度、高度(包含内边距+边框)

<div id="box">
  <div id="child"></div>
</div>

body { margin: 0; }
#box {position: relative; width: 300px; height: 300px;
  background-color: red; overflow: hidden; margin: 50px;
 }
#child { width: 100px; height: 100px; background-color: blue;
      margin: 50px; border: 10px solid green; padding: 10px;}
      
window.onload = function(){
  var box = document.getElementById("box");
  var width = box.offsetWidth;   // 对象的自身宽度 + 左右padding + 左右border
  var height = box.offsetHeight; // 对象的自身高度 + 上下padding + 上下border
  var top = box.offsetTop;   // 纵坐标:对象距离窗口的外边距 margin-top
  var left = box.offsetLeft; // 横坐标 对象距离窗口的左边距 margin-left
  console.log(width +","+ height+","+ top+","+left); // box:300,300,50,50
    
var child = document.getElementById('child'); // 获取child
  var w = child.offsetWidth;
  var h = child.offsetHeight;
  var t = child.offsetTop;
  var l = child.offsetLeft;
  console.log("child:"+ w +","+ h+","+ t+","+l); // child:140,140,50,50
  console.log("child:"+w+","+h+","+t+","+l); // child:140,140,100,100 
  // 注意:若父级没有定位,子元素是相对于body的距离    
}

2.client系列属性

// 和 offset 不同的是 包括padding  但是不包括边框
// clientLeft 、clientTop 是 border-left、border-top 的 边框宽度
// clientWidth、clientHeight 是自身宽高+padding

<div id="box"></div>

#box {width: 100px; height: 100px;margin: 50px;
  padding: 10px; border: 30px solid red; background-color: green;}
  
var box = document.getElementById("box");
var w = box.clientWidth; // 自身宽度 + 左右padding
var h = box.clientHeight;  // 自身高度 + 上下padding
var t = box.clientTop;  // border-top的边框高度
var l = box.clientLeft; // border-left的边框宽度
console.log("clientBox:"+w+","+h+","+t+","+l); // clientBox:120,120,30,30  

3.scroll滚动属性

// scrollLeft 、scrollTop 水平/垂直滚动距离,默认是0    只有当触发的 onscroll 事件后,才会产生值得变化!!!
注意:scrollTop 是内容滚动出去的距离!!!
scrollWidth 内容宽度+padding,不包括滚动条,宽度和 clientWidth相等
scrollHeight 内容高度+padding+未显示区域

<div id="box">从劳动人民中间走来的新时代领路人,始终心系劳动人民。党的十八大以来,习近平总书记多次出席全国劳动模范和先进工作者表彰大会,同劳动模范代表座谈,看望慰问坚守岗位的...!” </div>

#box { width: 100px; height: 100px; margin: 50px;
  border: 30px solid red; padding: 10px;
  background-color: green; overflow: auto;  /* 当内容超出,会自动产生滚动条 */
 }
 
var box = document.getElementById('box');
console.log(box.scrollLeft);  // 0 默认为0
console.log(box.scrollTop);  // 0 默认为0
// 当拖动box中的滚动条的时候触发
box.onscroll = function () {
  console.log(box.scrollLeft); // 横向没有滚动条,永远是0
  console.log(box.scrollTop);
}

4.处理兼容:获取页面滚动出去的距离

// 获取页面滚动距离的浏览器兼容性问题
// 获取页面滚动出去的距离
function getScroll() {
  var scrollLeft = document.body.scrollLeft || document.documentElement.scrollLeft;
  var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
  return {
    scrollLeft: scrollLeft,
    scrollTop: scrollTop
  }
}

5.实例:当滚动条滚动到底时使表单可用

// 注册**信息时    勾选统一协议:当滚动条滚动到底是使表单可用
var inputs = document.getElementsByTagName('input'); // 获取所有input元素
var info = document.getElementById('info'); // 获取表单
info.onscroll = function () {
  if(this.scrollHeight - this.scrollTop == this.clientHeight) { // 判断垂直滚动条是否滚动到底
    inputs[0].disabled = false;
    inputs[1].disabled = false;
 }
}

6.实例:鼠标拖拽盒子案例

代表性网站:百度-登录窗口      效果:鼠标拖动盒子,盒子跟着走
分析:发生这件事情会用到的3个事件:当鼠标在盒子上按下不放onmousedown、鼠标移动 onmousemove 、onmouseup 鼠标弹起/鼠标离开
求:鼠标移动的过程中,盒子的坐标 (需要知道的值:鼠标在盒子上按下时,鼠标在盒子上的位置)
鼠标在页面上的位置 - 鼠标在盒子上的位置 = 盒子的坐标

// 1. 鼠标按下时,鼠标在盒子上的位置:鼠标的位置 - 盒子的位置
var x = e.pageX - box.offsetLeft; 
var y = e.pageY - box.offsetTop;

// 2、鼠标在移动过程中,求盒子的位置:盒子的坐标 = 鼠标当前在页面中的位置 - 鼠标在盒子中的位置
var boxX = e.pageX - x;
var boxY = e.pageY - y;
// 改变盒子的坐标
box.style.left = boxX + 'px';
box.style.top = boxY + 'px';

// 3、鼠标离开盒子时,移除 鼠标移动 事件

<div class="nav">
    <a href="javascript:;" id="register">注册信息</a>
</div>
<div class="d-box" id="d_box">
    <div class="hd" id="drop">注册信息 (可以拖拽)
        <span id="box_close">【关闭】</span>
    </div>
    <div class="bd"></div>
</div>


<script src="common.js"></script>
<script>
var box = document.getElementById('d_box');
var drop = document.getElementById('drop');

drop.onmousedown = function (e) {
  e = e || window.event; // 兼容性处理 
  // 当鼠标按下的时候,求鼠标在盒子中的位置
  // 鼠标在盒子中的位置 = 鼠标在页面上的位置 - 盒子的位置
  var x = getPage(e).pageX - box.offsetLeft;
  var y = getPage(e).pageY - box.offsetTop;

  document.onmousemove = function (e) {  // 鼠标在文档中移动
    e = e || window.event;
    // 当鼠标在页面上移动的时候。求盒子的坐标
    // 盒子的坐标 = 鼠标当前在页面中的位置 - 鼠标在盒子中的位置
    var boxX = getPage(e).pageX - x;
    var boxY = getPage(e).pageY - y;
    box.style.left = boxX + 'px';
    box.style.top = boxY + 'px';
  }
 }

  // 当鼠标弹起的时候,移除鼠标移动事件
  document.onmouseup = function () {
    document.onmousemove = null;
 }

  // 点击关闭按钮,隐藏盒子
  var box_close = document.getElementById('box_close');
  box_close.onclick = function () {
    box.style.display = 'none';
  }
</script>
盒子移动的简单动画
// 1、单击一次按钮,盒子向右偏移 10px
var btn = document.getElementById('btn');
var box = document.getElementById('box');
btn.onclick = function () {
  box.style.left = box.offsetLeft + 10 + "px";
}
// 注意:通过style.left 获取的是标签中的style属性设置的样式属性的值,如果标签中的style没有设置该样式属性,获取到的是空字符串

// 2、盒子不停得向右移动
// 方式一: 使用for 循环
for(var i=1; i<100; i++) {
  box.style.left = box.offsetLeft + 5 + "px";
}
// 方式二:setInterval 定时器的方式 
setInterval(function(){
  box.style.left = box.offsetLeft + 5 + "px"
 }, 30)

// 让盒子停在500px 的位置:
var btn = document.getElementById('btn');
var box = document.getElementById('box');
var timer;
var step = 6; // 步进
var target = 600; // 当最终停止的位置 不确定时,用变量
btn.onclick = function () {
  timer = setInterval(function(){
    if (box.offsetLeft >= target) {  // >= 防止偏移值根本没有500这个值
      clearInterval(timer);  // 停止定时器
      box.style.left = target + 'px'; // 设置横坐标为 最终停止的位置
      console.log(box.style.left);
      return; // 退出函数
    }
    box.style.left = box.offsetLeft + step + 'px';
    /*console.log(box.style.left); // 打印盒子坐标*/
 }, 30)
}

3.DOM事件

1.常用事件属性


// 1. window 常见的事件属性
window.onload    // 当页面已完成加载时,一个页面建议只写一个,因为如果写多个会只执行最后一个
onresize         // 当浏览器窗口被调整大小时
onunload        // 页面卸载时

// 2. form 事件
onfocus     // 当输入字段获得焦点时
onblur      // 当失去焦点时
onchange    // 当用户改变输入字段内容时
onsubmit    // 在提交表单时触发

// 3. 鼠标事件 
onclick      //  鼠标点击事件
onmousemove  // 鼠标移动
onmouseup    // 鼠标弹起/鼠标离开
onmouseenter 和 onmouseleave // 鼠标经过和离开
onmouseover 和 onmouseout 事件  // 鼠标进入和鼠标移出
onmousedown 和 onmouseup  // 当鼠标按下不放时和当鼠标按钮被释放时
onscroll      // 当元素滚动条被滚动时运行的脚本

// 4. 键盘事件
keydown   // 监听键盘按键按下
keyup     // 键盘按键抬起
keyCode  // 键盘码  

2.事件对象

什么是事件对象?
用来获取事件的详细信息, 例鼠标坐标、键盘按键
ie下可以直接使用event,非ie需要传入事件对象参数

// 1.clientX+clientY 获取鼠标坐标:
// 获取的是鼠标指针距离可视窗口(不包括上面的地址栏和滑动条)的距离,会随着滚动条滚动而改变;
document.onclick = function(e){
  var oEvent = e || window.event;
  var box = document.getElementById("box");
  box.innerHTML = "当前鼠标的x,y坐标:"+ oEvent.clientX + "," + oEvent.clientY
}

// 2.pageX +pageY 获取鼠标坐标:鼠标指针距离文档(HTML)的左上角距离,不会随着滚动条滚动而改变;
document.onclick = function(e){
  var oEvent = e || event;
  var box = document.getElementById("box");
  box.innerHTML = "当前鼠标的x,y坐标:"+ oEvent.pageX + "," + oEvent.pageY
}

// 3. 监听鼠标按下时的键盘码
document.onkeydown=function(ev){
  var oEvent=ev||event
  //键盘每个键对应的值可以百度搜索一下有一个表的  keyCode就是键的值
  box.innerHTML=oEvent.keyCode
}

3.处理兼容:获取鼠标在页面中的位置

// 获取鼠标在页面的位置,处理浏览器兼容性
function getPage(e) {
  var pageX = e.pageX || e.clientX + getScroll().scrollLeft;
  var pageY = e.pageY || e.clientY + getScroll().scrollTop;
  return {
    pageX: pageX,
    pageY: pageY
  }
}

4.事件冒泡

// 事件流会从DOM节点最里面的事件往最外面执行
// 取消事件冒泡兼容写法:
var oEvent = e || event;     // 获取事件对象
oEvent.cancelBubble = true;  // 取消事件冒泡

5.事件绑定、解绑和捕获

事件绑定 addEventListener(事件名,函数,捕获)第三个参数为可选,默认为false,false即事件流为事件冒泡
事件解绑 removeEventListener(事件名,函数,捕获), 默认为false
事件捕获和事件冒泡相反,如果开启了事件捕获就先执行捕获事件再执行当前被点击事件
注意,事件绑定中传入匿名函数会导致无法进行事件解绑

二、BOM

1.BOM的顶级对象-window

浏览器对象模型提供了独立于内容的、可以与浏览器窗口进行互动的对象结构。BOM由多个对象组成,其中代表浏览器窗口的Window对象是BOM的顶层对象,其他对象都是该对象的子对象。
我们在浏览器中的一些操作都可以使用BOM的方式进行编程处理,比如:刷新浏览器、后退、前进、在浏览器中输入URL等
浏览器的顶级对象是 window,当使用window的成员时,window 可以省略
全局变量都是window 的属性    打印 window 的全部成员     console.dir(window)
定义变量名时 注意不要和window的属性 重名!!!
例: name 是window的属性,是字符串类型,  top 是window 的属性,只能获取不能赋值

2.浏览器常用的3种对话框

1.alert() 警告框

2.prompt() 提示输入框

// 参数:1. 提示语   2.默认值
btn02.onclick = function () {
    var userName = prompt('请输入姓名', '张三');
    console.log(userName);
}

3.confitrm() 让用户决定是否-确定/取消框

// 参数:提示语
btn03.onclick = function () {
  var isTrue = confirm('确定要删除数据?');
  console.log(isTrue);
}

3.Location对象

1.最常用属性

// 1. 获取当前页面地址
btn01.onclick = function(){ console.log(location.href); }
  
// 2. 跳转指定的地址页面
btn02.onclick = function(){ location.href = 'http:www.itheima.com'; }

// 其他属性
origin  // 协议+域名
hash 	// #锚点
host 	 // 主机(域名部分)
hostname	//主机(域名部分)
Protocol	// 协议 例: “http:”
search	// 查询字符串 ? 号后的字符串数据 例:name=zs&age=18
	

2.url的组成

网址:统一资源定位符  scheme://host:port/path?query#fragment

1scheme:通信协议:常用的 http 、 ftp、 maito
2host:主机(域名):服务器(计算机)域名系统 (DNS) 主机名或 IP 地址
3port:端口号:整数,可选,省略时使用方案的默认端口,如http的默认端口为804path:路径: 由零或多个'/'符号隔开的字符串,一般用来表示主机上的一个目录或文件地址
5query:查询:可选,用于给动态网页传递参数,可有多个参数,用'&'符号隔开,每个参数的名和值用'='符号隔开。例如:name=zs
6fragment:信息片断  : 字符串,锚点.

实例:
http://www.itheima.com:80/a/b/index.html?name=zs&age=18#bottom
http://www.itheima.com/a/b/index.html?name=zs&age=18#bottom

3.常用方法

// 1. assign() 委派  作用和 href 的作用一样,可以让页面跳转到指定的地址
// 参数:指定跳转的地址
btn02.onclick = function(){ location.assign('http:www.itheima.com'); }

// 2.replace() 替换掉地址栏的地址,但是不记录历史(只有记录历史,后退按钮才能使用,浏览器才能记住曾经访问过的页面)
// 参数:指定 替换的网址
btn02.onclick = function(){ location.replace('http:www.itheima.com'); }

// 3.reload() 重新加载 F5 
// 参数:true 强制从服务器获取页面,  false 如果浏览器有缓存的话,直接从缓存获取页面
btn02.onclick = function(){ location.reload(false); }

4.navigator对象

记录当前浏览器、操作系统、以及当前浏览器使用某内核 的信息

最常用属性:userAgent  通过这个属性可以知道 当前设备 的操作系统版本、浏览器版本、内核
// 例:
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36"
//通过这个特殊的字符串可以判断 是 pc端的设备 还是移动端的设备 --> 返回不同的页面
// 浏览器端记录的useragent 让服务器判断这个事情,在访问百度时,会把useragent的内容发送给服务器,服务器通过useragent的值进行特殊的判断,判断是pc端还是移动端,再返回相应的页面

5.history对象

浏览器的【前进】、【后退】功能, 通常情况下,只有 【OA办公系统】 会使用到此对象

最常用方法:
forward() // 前进
back()    // 后退
go(1)    // 前进
go(-1)   // 后退