【前端】BOM & DOM

发布于:2025-03-12 ⋅ 阅读:(15) ⋅ 点赞:(0)

两天更新完毕,建议关注收藏点赞
友情链接:
HTML&CSS&LESS&Bootstrap&Emmet
Axios & AJAX & Fetch
BOM DOM
待整理 js2


BOM

BOM (Browser Object Model,简称BOM) 是指浏览器对象模型,它提供了独立于内容的、可以与浏览器窗口进行互动的对象结构。通过BOM可以操作浏览器窗口,比如弹出框、控制浏览器跳转、获取分辨率等。

DOM

核心要点:增删改查,创建,属性操作,事件操作

文档对象模型(Document Object Model,简称DOM),是W3C组织推荐的处理可扩展标记语言的标准编程接口。通过 DOM 提供的接口可以对页面上的各种元素进行操作(大小、位置、颜色等)。

  • DOM树
    DOM树 又称为文档树模型,把文档映射成树形结构,通过节点对象对其处理,处理的结果可以加入到当前的页面。
    在这里插入图片描述
    文档:一个页面就是一个文档,DOM中使用document表示
    节点:网页中的所有内容,在文档树中都是节点(标签、属性、文本、注释等),使用node表示
    标签节点:网页中的所有标签,通常称为元素节点,又简称为“元素”,使用element表示
    DOM把这些节点都看作对象。
  • 总结
    创建
  1. document.write
  2. innerHTML
  3. createElement
  4. appendChild
  5. insertBefore
  6. removeChild

    主要修改dom的元素属性,dom元素的内容、属性, 表单的值等
  7. 修改元素属性: src、href、title等
  8. 修改普通元素内容: innerHTML 、innerText
  9. 修改表单元素: value、type、disabled等
  10. 修改元素样式: style、className

    主要获取查询dom的元素
  11. DOM提供的API 方法: getElementById、getElementsByTagName 古老用法 不太推荐
  12. H5提供的新方法: querySelector、querySelectorAll 提倡
  13. 利用节点操作获取元素: 父(parentNode)、子(children)、兄(previousElementSibling、nextElementSibling) 提倡
    属性操作
    主要针对于自定义属性。
  14. setAttribute:设置dom的属性值
  15. getAttribute:得到dom的属性值
  16. removeAttribute移除属性
    事件操作
    给元素注册事件, 采取 事件源.事件类型 = 事件处理程序
    在这里插入图片描述

一般获取元素

document.getElementById(id)
参数:id值,区分大小写的字符串
返回值:元素对象 或 null

<body>
    <div id="time">2019-9-9</div>
    <script>
        // 因为我们文档页面从上往下加载,所以先得有标签 所以我们script写到标签的下面
        var timer = document.getElementById('time');
        console.log(timer);
        console.log(typeof timer);
        // console.dir 打印我们返回的元素对象 更好的查看里面的属性和方法
        console.dir(timer);
    </script>
</body>

document.getElementsByTagName('标签名') 或者
element.getElementsByTagName('标签名') 
作用:根据标签名获取元素对象
参数:标签名
返回值:元素对象集合(伪数组,数组元素是元素对象)
注意:getElementsByTagName()获取到是动态集合,即:当页面增加了标签,这个集合中也就增加了元素。

document.getElementsByClassName()是h5新增的方法,有浏览器兼容性问题

<script>
        // 1.获取元素 获取的是 tbody 里面所有的行
var trs = document.querySelector('tbody').querySelectorAll('tr');
        // 2. 利用循环绑定注册事件
for (var i = 0; i < trs.length; i++) {
            // 3. 鼠标经过事件 onmouseover
	trs[i].onmouseover = function() {
                    // console.log(11);
		this.className = 'bg';
	}
                // 4. 鼠标离开事件 onmouseout
   trs[i].onmouseout = function() {
		this.className = '';
	}
}
</script>
<script>
        // 1. 全选和取消全选做法:  让下面所有复选框的checked属性(选中状态) 跟随 全选按钮即可
        // 获取元素
        
        var j_cbAll = document.getElementById('j_cbAll'); 
        var j_tbs = document.getElementById('j_tb').getElementsByTagName('input'); 
        // 全选按钮注册事件
        j_cbAll.onclick = function() {
                // this.checked 当前复选框的选中状态
                console.log(this.checked);
                for (var i = 0; i < j_tbs.length; i++) {
                    j_tbs[i].checked = this.checked;
                }
         }
         // 给所有的子复选框注册单击事件
        for (var i = 0; i < j_tbs.length; i++) {
            j_tbs[i].onclick = function() {
                // flag 控制全选按钮是否选中
                var flag = true;
                // 每次点击下面的复选框都要循环检查者4个小按钮是否全被选中
                for (var i = 0; i < j_tbs.length; i++) {
                    if (!j_tbs[i].checked) {
                        flag = false;
                        break; 
                    }
                }
                // 设置全选按钮的状态
                j_cbAll.checked = flag;
            }
        }
    </script>
  • querySelector 和 querySelectorAll 是两种常用的 DOM 查询方法。
  1. querySelector只能选择第一个匹配的节点;
  2. querySelectorAll可以选择多个节点,以","分隔开,返回的是个数组;
querySelector 返回指定选择器的第一个元素对象  
里面的选择器需要加符号 .box  #nav
var firstBox = document.querySelector('.box');

//获取特殊元素
document.body //body元素对象
document.documentElement //html元素对象

层级关系获取元素

在这里插入图片描述
节点就是前面DOM树中的所有节点,网页的所有内容都是节点。节点至少拥有nodeType(节点类型)、nodeName(节点名称)和nodeValue(节点值)这三个
基本属性。
 元素节点 nodeType 为 1
 属性节点 nodeType 为 2
 文本节点 nodeType 为 3 (文本节点包含文字、空格、换行等)

//父级节点 返回最近的一个父节点或者null
node.parentNode

//返回包含指定节点的子节点的集合,该集合为即时更新的集合。
//包含了所有的子节点,包括元素节点,文本节点等。
//如果只想要获得里面的元素节点,则需要专门处理。 所以我们一般不提倡使用childNodes
parentNode.childNodes

//是一个只读属性,返回所有的子元素节点。它只返回子元素节点,其余节点不返回
//是得到了各个浏览器的支持
parentNode.children

//第一个或最后一个 找不到则返回null。同样,也是包含所有的节点。
//子节点 不仅仅是元素节点
parentNode.firstChild
parentNode.lastChild

//返回第一个子元素节点,找不到则返回null。
//注意:这两个方法有兼容性问题,IE9 以上才支持。
parentNode.firstElementChild
parentNode.lastElementChild

//综上
//firstChild 和 lastChild 包含其他节点,操作不方便
//firstElementChild 和lastElementChild 又有兼容性问题
//如果要第一个子元素节点,使用 parentNode.chilren[0]
//如果是最后一个子元素节点,使用 parentNode.chilren[parentNode.chilren.length - 1]

//兄弟节点 返回当前元素的下一个兄弟节点,找不到则返回null。包含所有的节点。
node.nextSibling
node.previousSibling

//兄弟元素节点 注意:这两个方法有兼容性问题, IE9 以上才支持。
node.nextElementSibling
node.previousElementSibling

//使用自己封装的获取兄弟节点函数 同时解决兼容性
function getNextElementSibling(element) {
	 var el = element;
	 while (el = el.nextSibling) {
		 if (el.nodeType === 1) {
		 	return el;
		 }
	 }
	 return null;
}

//下拉菜单
var nav = document.querySelector('.nav');
var lis = nav.children; // 得到4个小li
for (var i = 0; i < lis.length; i++) {
	lis[i].onmouseover = function() {
		this.children[1].style.display = 'block';
	}
	lis[i].onmouseout = function() {
		this.children[1].style.display = 'none';
	}
}

事件event

事件是可以被 JavaScript 侦测到的行为。简单理解: 触发— 响应机制

  • 事件三要素
    事件源(谁):触发事件的元素
    事件类型(什么事件): 例如 click 点击事件
    事件处理程序(做啥):事件触发后要执行的代码(函数形式),事件处理函数
  • 执行事件步骤
    获取事件源,注册事件(绑定事件),添加事件处理程序(采用函数赋值形式)
  • 常见的鼠标事件
    在这里插入图片描述
<body>
    <button id="btn">唐伯虎</button>
    <script>
        // 点击一个按钮,弹出对话框
        // 1. 事件是有三部分组成  事件源  事件类型  事件处理程序   我们也称为事件三要素
        //(1) 事件源 事件被触发的对象   谁  按钮
        var btn = document.getElementById('btn');
        //(2) 事件类型  如何触发 什么事件 比如鼠标点击(onclick) 还是鼠标经过 还是键盘按下
        //(3) 事件处理程序  通过一个函数赋值的方式 完成
        btn.onclick = function() {
            alert('点秋香');
        }
    </script>
</body>

JS 特效三大系列【offset】【scroll】【client】

//offset
1. offsetLeft : 用于获取元素到最近的定位父盒子的左侧距离 
 
* 计算方式: 当前元素的左边框的左侧到定位父盒子的左边框右侧 
* 如果父级盒子没有定位, 那么会接着往上找有定位的盒子 
* 如果上级元素都没有定位,那么最后距离是与body的left值 
 
2. offsetTop : 用于获取元素到最近定位父盒子的顶部距离
 
 * 计算方式:当前元素的上边框的上侧到定位父盒子的上边框下侧 
 * 如果父级盒子没有定位,那么会接着往上找有定位的盒子 
 * 如果上级元素都没有定位,那么最后距离是与body的top值 
 
3. offsetWidth :用于获取元素的真实宽度(除了margin以外的宽度) 
 
4. offsetHeight : 用于获取元素的真实高度(除了margin以外的高度) 
 
5. offsetParent :用于获取该元素中有定位的最近父级元素 
 
* 如果当前元素的父级元素都没有进行定位,那么offsetParent为body

//与  style . ( left  /  top  /  width  /  height ) 的区别:
1. offset系列的是只读属性,而通过style的方式可以读写 
2. offset系列返回的数值类型(结果四舍五入),style返回的是字符串 
3. style 可以返回没有定位的元素的left值和top值,而 offsetLeft 和 offsetTop 不可以

//scroll
	1. scrollHeight :元素中内容的实际高度(没有边框) 
 
	* 如果内容不足,就是元素的高度 
 
	2. scrollWidth : 元素中内容的实际宽度(没有边框)
 
	* 如果内容不足,就是元素的宽度 
 
	3. scrollTop : onscroll事件发生时,元素向上卷曲出去的距离 
 
	4. scrollLeft : onscroll事件发生时,元素向左卷曲出去的距离

//兼容问题
* 未声明 DTD: 谷歌,火狐,IE9+支持 document.body.scrollTop/scrollLeft 
* 已经声明DTD:IE8以下支持 document.documentElement.scrollTop/scrollLeft 
* 火狐/谷歌/ie9+以上支持的 window.pageYOffest/pageXOffest
//兼容代码
function getScroll() {
  return {
    left: window.pageXOffset || document.body.scrollLeft || document.documentElement.scrollLeft || 0,
    top: window.pageYOffset || document.body.scrollTop || document.documentElement.scrollTop || 0
  };
}

//client
1. clientWidth : 获取网页可视区域的宽度 
 
2. clientHeight: 获取网页可视区域的高度 
 
3. clientX : 获取鼠标事件发生时的应用客户端区域的水平坐标 
 
4. clientY : 获取鼠标事件发生时的应用客户端区域的垂直坐标

//兼容问题
 //由浏览器对象不同导致 
 * 未声明 DTD: 谷歌,火狐,IE9+支持 document.body.clientWidth/clientHeight 
 * 已经声明DTD:IE8以下支持 document.documentElement.clientWidth/clientHeight 
 * 火狐/谷歌/ie9+以上支持的 window.innerWidth/innerHeight
//兼容代码
function client() {
  if (window.innerWidth) {
    return {
      "width": window.innerWidth,
      "height": window.innerHeight
    };
  } else if (document.compatMode === "CSS1Compat") {
    return {
      "width": document.documentElement.clientWidth,
      "height": document.documentElement.clientHeight
    };
  } else {
    return {
      "width": document.body.clientWidth,
      "height": document.body.clientHeight
    };
  }
}
 //由事件参数对象的兼容性问题导致 
 1. 谷歌,火狐,IE9+ : 事件参数对象随着事件处理函数的参数传入 
 2. IE8以下: event对象必须作为window对象的一个属性(window.event)
  • 总结
网页可见区域宽: document.body.clientWidth; 
网页可见区域高: document.body.clientHeight; 

网页真实元素宽: document.body.offsetWidth (包括边线的宽); 
网页真实元素高: document.body.offsetHeight (包括边线的宽); 

网页正文全文宽: document.body.scrollWidth; 
网页正文全文高: document.body.scrollHeight; 

网页被卷去的高: document.body.scrollTop; 
网页被卷去的左: document.body.scrollLeft; 

浏览器窗口的顶部边缘与屏幕的顶部边缘之间的距离: window.screenTop; 
浏览器窗口的左边缘与屏幕的左边缘之间的距离: window.screenLeft; 

屏幕分辨率的高: window.screen.height; 
屏幕分辨率的宽: window.screen.width; 

屏幕可用工作区高度: window.screen.availHeight; 
屏幕可用工作区宽度: window.screen.availWidth;

操作元素

element.innerText 不解析html标签,去除空格、换行
element.innerHTML 不去除

//常见属性
src,href
id,alt,title

//表单元素
type,value,checked,selected,disabled

//样式属性
element.style
element.className//覆盖原先类名 class是关键字不能用
//当js修改样式时为行内样式,优先级高

box.style.display = 'none';

//自定义属性
element.getAttribute('attr_name')
element.setAttribute('attr_name','value')
element.removeAttribute('属性');
//H5规定自定义属性data-开头做为属性名并且赋值。
H5新增 element.dataset.index 或者 element.dataset[‘index’] 
//ie11才开始支持

//循环雪碧图 精灵图
var lis = document.querySelectorAll('li');
for (var i = 0; i < lis.length; i++) {
// 让索引号 乘以 44 就是每个li 的背景y坐标  index就是我们的y坐标
	var index = i * 44;
	lis[i].style.backgroundPosition = '0 -' + index + 'px';
}

//仿新浪注册页面
        // 首先判断的事件是表单失去焦点 onblur
        // 如果输入正确则提示正确的信息颜色为绿色小图标变化
        // 如果输入不是6到16位,则提示错误信息颜色为红色 小图标变化
        // 因为里面变化样式较多,我们采取className修改样式
        // 1.获取元素
        var ipt = document.querySelector('.ipt');
        var message = document.querySelector('.message');
        //2. 注册事件 失去焦点
        ipt.onblur = function() {
            // 根据表单里面值的长度 ipt.value.length
            if (this.value.length < 6 || this.value.length > 16) {
                // console.log('错误');
                message.className = 'message wrong';
                message.innerHTML = '您输入的位数不对要求6~16位';
            } else {
                message.className = 'message right';
                message.innerHTML = '您输入的正确';
            }
        }
<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>dataset 示例</title>
</head>
<body>
    <button id="myButton" data-index="1">点击我</button>

    <script>
        // 获取按钮元素
        var button = document.getElementById("myButton");

        // 读取 dataset
        console.log("初始索引:", button.dataset.index); // 输出: "1"

        // 修改 dataset
        button.dataset.index = "2";
        console.log("修改后的索引:", button.dataset.index); // 输出: "2"

        // 监听点击事件
        button.addEventListener("click", function() {
            // 自增 index
            this.dataset.index = parseInt(this.dataset.index) + 1;
            alert("当前索引: " + this.dataset.index);
        });
    </script>
</body>
</html>
//创建节点
document.createElement('name')
//创建由tagName指定的HTML元素。因为这些元素原先不存在,称为动态创建元素节点。

//将一个节点添加到指定父节点的子节点列表末尾。
//类似于 CSS 里面的after 伪元素。
node.appendChild(child)

//将一个节点添加到父节点的指定子节点前面。
//类似于 CSS 里面的 before 伪元素。
node.insertBefore(child, 指定元素)

//从 DOM 中删除一个子节点,返回删除的节点。
node.removeChild(child)

//返回调用该方法的节点的一个副本。 也称为克隆节点/拷贝节点
node.cloneNode()
//括号参数为空或者为false则是浅拷贝,即只克隆复制节点本身,不克隆里面的子节点。
//如果括号参数为 true ,则是深度拷贝,会复制节点本身以及里面所有的子节点。

  • 三种动态创建元素的区别
     document.write()
     element.innerHTML
     document.createElement()
    区别
  1. document.write 是直接将内容写入页面的内容流,但是文档流执行完毕,则它会导致页面全部重绘
  2. innerHTML 是将内容写入某个 DOM 节点,不会导致页面全部重绘
  3. innerHTML 创建多个元素效率更高(不要拼接字符串,采取数组形式拼接),结构稍微复杂
  4. createElement() 创建多个元素效率稍低一点点,但是结构更清晰
    总结:不同浏览器下,innerHTML 效率要比 creatElement 高