一、Web APIs
1、Web API
Web API 是浏览器提供的一套操作浏览器功能和页面元素的API(BOM 和 DOM)。
2、总结
- API 是为我们提供的一个接口,帮助我们实现某种功能
- Web API 主要是针对浏览器提供的接口,主要针对浏览器做交互效果。
- Web API 一般都有输入和输出(函数的传参和返回值),Web API 很多都是方法(函数)
二、DOM
1、DOM
文档对象模型(Document Object Model,简称 DOM),是W3C 组织推荐的处理可拓展标记语言(HTML 或者 XML)的标准编程接口。
DOM 树
- 文档:一个页面就是一个文档,DOM 中使用 document 表示
- 元素:页面中的所有标签都是元素,DOM 中使用 element 表示
- 节点:网页中的所有内容都是节点(标签、属性、文本、注释等),DOM 中使用 node 表示
DOM 把以上内容都看作是对象
2、获取元素
根据 ID 获取
使用 getElementById() 方法可以获取带有 ID 的元素对象。
示例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <div id="time">2024/3/15</div> <script> // 1.因为文档页面是从上往下加载,即先得有标签,所以script写在标签的下面 // 2.参数 id 是大小写敏感的字符串 // 3.返回的是一个元素对象 var timer = document.getElementById('time'); console.log(timer); console.log(typeof timer); // 4.console.dir 打印返回的对象 更好地查看里面的属性和方法 console.dir(timer) </script> </body> </html>
结果:
根据标签名获取
使用 getElementsByTagName() 方法可以返回带有指定标签名的对象的集合。
还可以获取某个(父元素)内部所有指定标签名的子元素:
element.getElementsByTagName('标签名');
注意:父元素必须是单个对象(必须指明是哪一个元素对象),获取的时候不包括父元素自己。
示例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <ul> <li>知否知否,应是绿...红...1</li> <li>知否知否,应是绿...红...2</li> <li>知否知否,应是绿...红...3</li> <li>知否知否,应是绿...红...4</li> </ul> <ol id="ol"> <li>十二生肖</li> <li>十二生肖</li> <li>十二生肖</li> <li>十二生肖</li> </ol> <script> // 1.返回的是 获取过来的元素的对象的集合 以伪数组的形式存储的 var lis = document.getElementsByTagName('li'); console.log(lis); console.log(lis[0]); // 2.依次打印里面的元素对象可以采取遍历的方式 for (var i = 0; i < lis.length; i++) { console.log(lis[i]); } // 3.如果页面中只有一个li 返回的还是伪数组的形式 // 4.如果页面中没有这个元素 返回的是还是空的伪数组的形式 // 5.element.getElementsByTagName('标签名'); 父元素必须是指定的单个元素 // var ol = document.getElementsByTagName('ol'); // [ol] // console.log(ol[0].getElementsByTagName('li')); var ol = document.getElementById('ol'); console.log(ol.getElementsByTagName('li')); </script> </body> </html>
结果:
通过 HTML5 新增的方法获取
document.getElementsByClassName('类名'); // 根据类名返回元素对象集合 document.querySelector('选择器'); // 根据指定选择器返回第一个元素对象 document.querySelectorAll('选择器'); // 根据指定选择器返回
示例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <div class="box">box1</div> <div class="box">box2</div> <div id="nav"> <ul> <li>首页</li> <li>产品</li> </ul> </div> <script> // 1.getElementsByClassName 根据类名获得某些元素集合 var box = document.getElementsByClassName('box'); console.log(box); // 2.querySelector 返回指定选择器的第一个元素对象 里面的选择器需要加符号 '.' / '#' var firstBox = document.querySelector('.box'); console.log(firstBox); var nav = document.querySelector('#nav'); console.log(nav); var li = document.querySelector('li'); console.log(li); // 3.querySelectorAll() 返回指定选择器的所有元素对象集合 var allBox = document.querySelectorAll('.box'); console.log(allBox); var lis = document.querySelectorAll('li') console.log(lis); </script> </body> </html>
结果:
获取特殊元素(body , html)
获取body元素
document.body // 返回body元素对象
获取html元素
document.documentElement // 返回html元素对象
示例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <script> // 1. 获取body元素 var bodyEle = document.body; console.log(bodyEle); console.dir(bodyEle) // 2. 获取html元素 // var htmlEle = document.html; var htmlEle = document.documentElement; console.log(htmlEle); </script> </body> </html>
结果:
3、事件基础
事件三要素
示例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <button id="btn">chop</button> <script> // 点击一个按钮,弹出对话框 // 1. 事件是有三部分组成 事件源 事件类型 事件处理程序 ————事件三要素 // (1) 事件源:事件被触发的对象 var btn = document.getElementById('btn'); // (2) 事件类型 如何触发 什么事件 比如:鼠标点击(onclick) 还是鼠标经过 还是键盘按下 // (3) 事件处理程序 通过一个函数赋值的方式完成 btn.onclick = function() { alert('That is a male dog!'); } </script> </body> </html>
结果:
执行事件的步骤
- 获取事件源
- 注册事件(绑定事件)
- 添加事件处理程序(采取函数赋值形式)
常见的鼠标事件
鼠标事件 触发事件 onclick 鼠标点击左键触发 onmouseover 鼠标经过触发 onmouseout 鼠标离开触发 onfocus 获得鼠标焦点触发 onblur 失去鼠标焦点触发 onmousemove 鼠标移动触发 onmouseup 鼠标弹起触发 onmousedown 鼠标按下触发
4、操作元素
改变元素内容
element.innerText
从起始位置到终止位置的内容,但去除 html 标签,同时空格和换行也会去掉
elememt.innerHTML
起始位置到终止位置的全部内容,包括 html 标签,同时保留空格和换行
示例一:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> div, p { width: 300px; height: 30px; line-height: 30px; color: #fff; background-color: pink; } </style> </head> <body> <button>显示当前系统时间</button> <div>某个时间</div> <p>123</p> <script> // 当我们点击了按钮,div里面的文字发生变化 // 1.获取元素 var btn = document.querySelector('button') var div = document.querySelector('div') // 2.注册事件 btn.onclick = function() { // div.innerText = '2024-03-17'; div.innerText = getDate(); } function getDate() { var date = new Date(); var year = date.getFullYear(); var month = date.getMonth() + 1; var dates = date.getDate(); var arr = ['星期日','星期一','星期二','星期三','星期四','星期五','星期六']; var day = date.getDay(); return '今天是:' + year + '年' + month + '月' + dates + '日' + arr[day]; } // 元素可以不用添加事件 var p = document.querySelector('p'); p.innerText = getDate(); </script> </body> </html>
结果一:
示例二:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <div></div> <p> i am god! <span>123</span> </p> <script> // innerText 和 innerHTML 的区别 // 1.innerText 不识别html标签 非标准 去除换行和空格 var div = document.querySelector('div'); // div.innerText = '<strong>Today is</strong> 2024'; // 2.innerHTML 识别html标签 W3C标准 保留换行和空格 div.innerHTML = '<strong>Today is</strong> 2024'; // 这两个元素是可读写的 可以获取元素里面的内容 var p = document.querySelector('p'); console.log(p.innerText); console.log(p.innerHTML); </script> </body> </html>
结果二:
常用元素的属性操作
innerText、innerHTML 改变元素内容 src、href id、alt、title
示例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> img { width: 300px; } </style> </head> <body> <button id="pic1">photo1</button> <button id="pic2">photo2</button> <img src="./images/网图1.jpg" alt="" title="网图1"> <script> // 修改元素属性 src // 1.获取元素 var pic1 = document.getElementById('pic1'); var pic2 = document.getElementById('pic2'); var img = document.querySelector('img'); // 2.注册事件 pic2.onclick = function() { img.src = 'images/网图2.jpg'; img.title = '网图2'; } pic1.onclick = function() { img.src = 'images/网图1.jpg'; img.title = '网图1'; } </script> </body> </html>
表单元素的属性操作
利用 DOM 可以操作如下表单元素的属性:
type、value、checked、selected、disable
示例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <button>按钮</button> <input type="text" value="输入内容"> <script> // 1.获取元素 var btn = document.querySelector('button'); var input = document.querySelector('input'); // 2.注册事件 处理程序 btn.onclick = function() { // input.innerHTML = '已点击'; 这个是普通盒子比如div标签里面的内容 // 表单里面的值 文字内容是通过 value 来修改的 input.value = '已点击'; // 如果想要某个表单被禁用,不能再点击——disable // btn.disabled = true; this.disabled = true; // this 指向的是事件函数的调用者 } </script> </body> </html>
结果:
样式属性操作
element.style 行内样式操作 elemen.className 类名样式操作
- 注意:
- JS 里面的样式采取驼峰命名法 比如:fontSize、backgroundColor
- JS 修改 style 样式操作,产生的是行内样式,css 权重比较高
- 如果样式修改较多,可以采取操作类名方式更改元素样式
- class因为是个保留字,因此使用className来操作元素类名属性
- className 会直接更改元素的类名,会覆盖原先的类名
示例一:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> div { width: 200px; height: 200px; background-color: pink; } </style> </head> <body> <div></div> <script> var div = document.querySelector('div'); div.onclick = function() { // div.style 里面的属性采取 驼峰命名法 this.style.backgroundColor = 'purple'; this.style.width = '250px'; } </script> </body> </html>
示例二:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> div { width: 100px; height: 100px; background-color: pink; } .change { background-color: purple; color: #fff; font-size: 25px; margin-top: 100px; } </style> </head> <body> <div class="first">文本</div> <script> // 1.使用 element.style 获取修改元素样式 如果 样式较少 或者 功能简单的情况下 使用 var test = document.querySelector('div'); test.onclick = function() { // this.style.backgroundColor = 'purple'; // this.style.color = '#fff'; // this.style.fontSize = '25px'; // this.style.marginTop = '100px'; // 让当前元素的类名改为了 change // 2.可以通过修改元素样式的className更改元素的样式适合于样式较多或者功能复杂的情况 // 3.保留原先的类名 // this.className = 'change'; this.className = 'first change'; } </script> </body> </html>
排他思想
- 所有元素全部清除样式
- 给当前元素设置样式
- 注意顺序不能颠倒
示例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <button>按钮1</button> <button>按钮2</button> <button>按钮3</button> <button>按钮4</button> <button>按钮5</button> <script> // 获取所有按钮元素 var btns = document.getElementsByTagName('button'); // btns得到的是伪数组 for (var i = 0; i < btns.length; i++) { btns[i].onclick = function() { // (1) 把所有的按钮背景颜色去掉 // (2) 然后才改变当前的背景颜色 for (var i = 0; i < btns.length; i++) { btns[i].style.backgroundColor = ''; } this.style.backgroundColor = 'pink'; } } </script> </body> </html>
自定义属性的操作
获取属性值
- element.属性 获取属性值
- element.getAttribute(‘属性’);
区别:
- element.属性 获取内置属性值(元素本身自带的属性)
- element.getAttribute(‘属性’); 主要获得自定义的属性(标准)
设置属性值
- element.属性 = ‘值’ 设置内置属性值
- element.setAttribute(‘属性’, ‘值’);
区别:
- element.属性 设置内置属性值
- element.setAttribute(‘属性’); 主要获得自定义的属性(标准)
移除属性
- element.removeAttribute(‘属性’);
示例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <div id="demo" index="1" class="nav"></div> <script> var div = document.querySelector('div'); // 1.获取元素的属性值 // (1) element.属性 console.log(div.id); // (2) element.getAttribute('属性') console.log(div.getAttribute('id')); console.log(div.getAttribute('index')); // 2.设置元素的属性值 // (1) element.属性 = '值' div.id = 'test'; div.className = 'navs'; // (2) element.setAttribute('属性', '值') 主要针对于自定义 div.setAttribute('index', 2); div.setAttribute('class', 'footer'); // 3.移除属性 div.removeAttribute('index'); </script> </body> </html>
H5自定义属性
自定义属性的目的:为了保存并使用数据,有些数据可以保存到页面中而不用·保存到数据库中。
自定义属性获取是通过getAttribute(‘属性’) 获取。
- 设置H5自定义属性
H5规定自定义属性data-开头作为属性名并且赋值。
比如<div data-index='1'></div>
或者使用 JS 设置
element.setAttribute('data-index', 2);
- 获取H5自定义属性
- 兼容性获取 element.getAttribute(‘index-index’);
- H5新增 element.dataset.index 或者 element.dataset==[‘index’]== ie 11 才开始支持
示例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <div getTime="20" data-index="2" data-list-name="andy"></div> <script> var div = document.querySelector('div'); console.log(div.getAttribute('getTime')); div.setAttribute('data-time', 20); console.log(div.getAttribute('data-index')); console.log(div.getAttribute('data-list-name')); // H5新增的获取自定义属性的方法 只能获取 data 开头的 // dataset 是一个集合,里面存放了所有以data开头的自定义属性 console.log(div.dataset); console.log(div.dataset.index); console.log(div.dataset['index']); // 如果自定义属性里面有多个-连接的单词,获取的时候采取 驼峰命名法 console.log(div.dataset.listName); console.log(div.dataset['listName']); </script> </body> </html>
结果:
5、节点操作
节点概述
一般地,节点至少有nodeType(节点类型)、nodeName(节点名称)、nodeValue(节点值)这三个基本属性。
- 元素节点 nodeType 为 1
- 属性节点 nodeType 为 2
- 文本节点 nodeType 为 3(文本节点包含文字、空格、换行等)
节点层级
利用 DOM 数可以把节点划分为不同的层级关系,常见的是父子兄层级关系。
父级节点
node.parentNode
示例:<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <div>我是div</div> <span>我是span</span> <ul> <li>我是li</li> <li>我是li</li> <li>我是li</li> <li>我是li</li> </ul> <div class="demo"> <div class="box"> <span class="erweima">x</span> </div> </div> <script> // 1.父节点 parentNode var erweima = document.querySelector('.erweima'); // var box = document.querySelector('.box'); // 如果找不到父节点就返回 null console.log(erweima.parentNode); </script> </body> </html>
结果:
子节点
parentNode.childNodes(标准)
parentNode.childNodes 返回包含指定节点的子节点的集合,该集合为即时更新的集合。
注意:返回值里面包含了所有的子节点,包括元素节点,文本节点等。
如果只想要获得里面的元素节点,则需要专门处理:var ul = document.querySelector('ul'); for (var i = 0; i < ul.childNodes.length; i++) { if (ul.childNodes[i].nodeType == 1) // ul.childNodes[i] 是元素节点 console.log(ul.childNodes[i]); }
parentNode.children(非标准)
parentNode.children 是一个只读属性,返回所有的子元素节点。它只返回子元素节点,其余节点不返回
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <div>我是div</div> <span>我是span</span> <ul> <li>我是li</li> <li>我是li</li> <li>我是li</li> <li>我是li</li> </ul> <ol> <li>我是li</li> <li>我是li</li> <li>我是li</li> <li>我是li</li> </ol> <div class="demo"> <div class="box"> <span class="erweima">x</span> </div> </div> <script> // DOM 提供的方法(API)获取 var ul = document.querySelector('ul'); var lis = ul.querySelectorAll('li'); // 1.子节点 cjildNodes 获取所有的子节点,包含:元素节点、文本节点等等 console.log(ul.childNodes); console.log(ul.childNodes[0].nodeType); console.log(ul.childNodes[1].nodeType); // 2.children 获取所有的子元素节点 console.log(ul.children); </script> </body> </html>
结果:
.
parentNode.firstChild
firstChild 返回第一个子节点,找不到则返回null。同样包含所有的节点。
parentNode.lastChild
lastChild 返回最后一个子节点,找不到则返回null。同样包含所有的节点。
parentNode.firstElementChild
firstElementChild 返回第一个子节点,找不到则返回null.
parentNode.lastElementChild
lastElementChild 返回最后一个子节点,找不到则返回null注意:上面两种方法都有兼容性问题,IE9 以上才支持。
示例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <ol> <li>我是li1</li> <li>我是li2</li> <li>我是li3</li> <li>我是li4</li> </ol> <script> var ol = document.querySelector('ol'); // 1.firstChild 第一个子节点 console.log(ol.firstChild); console.log(ol.lastChild); // 2.firstElementChild 返回第一个子元素节点 console.log(ol.firstElementChild); console.log(ol.lastElementChild); // 3.实际开发的写法 既没有兼容性问题又可以返回第一个子元素 console.log(ol.children[0]); console.log(ol.children[ol.children.length - 1]); </script> </body> </html> ``` 结果: <img src="C:/Users/lenvovo/Pictures/JS笔记/06-03.png" style="zoom:80%;" />
兄弟节点
node.nextSibling
nextSibling 返回当前元素的下一个兄弟节点,找不到则返回null。同样包含所有的节点。node.previousSibling
previousSibling 返回当前元素的上一个兄弟节点,找不到则返回null。同样包含所有的节点。node.nextElementSibling
nextElementSibling 返回当前元素的下一个兄弟元素节点,找不到则返回null。node.previousElementSibling
previousElementSibling 返回当前元素的上一个兄弟元素节点,找不到则返回null。注意:上面两种方法都有兼容性问题,IE9 以上才支持。
解决问题:(封装函数)
function getElementSibling(element) { var el = element; while (el == el.nextSibling) { if (el.nodeType === 1) { return el; } } return null; }
示例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <div>我是div</div> <span>我是span</span> <script> var div = document.querySelector('div'); // nextSibling 下一个兄弟节点 包含:元素节点和文本节点等 console.log(div.nextSibling); console.log(div.previousSibling); // nextElementSibling 下一个兄弟元素节点 console.log(div.nextElementSibling); console.log(div.previousElementSibling); </script> </body> </html>
结果:
创造节点
document.createElement('tagName')
添加节点
node.appendChild(child)
node.appendChild() 方法将一个节点添加到指定父节点列表末尾。类似于 css 里面的 after 伪元素。node.insertBefore(child, 指定元素)
node.insertBefore() 方法将一个节点添加到父节点的指定子节点前面。类似于 css 里面的 before 伪元素。
删除节点
node.removeChild(child)
node.removeChild() 方法从 DOM 中删除一个子节点,返回删除的节点。
示例;
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <button>删除</button> <ul> <li>熊大</li> <li>熊二</li> <li>光头强</li> </ul> <script> var ul = document.querySelector('ul'); var btn = document.querySelector('button'); // ul.removeChild(ul.children[0]); // 点击按钮删除子节点 btn.onclick = function() { if (ul.children.length == 0) { this.disabled = true; } else { ul.removeChild(ul.children[0]); } } </script> </body> </html>
复制节点(克隆节点)
node.cloneNode()
node.cloneNode() 方法返回调用该方法节点的一个副本,也称为克隆节点/拷贝节点注意:
- 如果括号参数为空或者为false,则是浅拷贝,即只克隆复制节点本身,不克隆里面的子节点。
- 如果括号参数为true,则是深度拷贝,会复制节点本身以及里面所有的子节点。
三种动态创建元素区别
document.write()
element.innerHTML()
document.createElement()
区别:
- document.write 是直接将内容写入页面的内容流,但是文档流执行完毕,则它会导致页面全部重绘
- innerHTML 是将内容写入某个 DOM 节点,不会导致页面全部重绘
- innerHTML 创建多个元素效率更高(不要拼接字符串,采取数组形式拼接),结构稍微复杂;
- createElement() 创建多个元素效率稍微低一点,但是结构更清晰
示例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <button>点击</button> <p>abc</p> <div class="inner"></div> <div class="create"></div> <script> // 1. 如果页面文档流加载完毕,再调用这句话会导致页面重绘 // var btn = document.querySelector('button'); // btn.onclick = function() { // document.write('<div>123</div>'); // } // 2 var inner = document.querySelector('.inner'); inner.innerHTML = '<a href="#">百度</a>'; inner.innerHTML = arr.join(''); // 3 var create = document.querySelector('.create'); var a = document.createElement('a'); create.appendChild(a); </script> </body> </html>
结果: