目录
- 一、Web APIs介绍
- 1、API
- 2、Web API
 
- 二、DOM
- 1、DOM树
- 2、获取元素
- 3、事件基础
- 4、操作元素属性
- 5、节点(node)操作
 
- 三、以上内容总结
- 四、小案例
一、Web APIs介绍
JS的组成:ECMAScript(基础语法)、DOM(页面文档模型)和BOM(浏览器文档模型)
 基础语法为后面做铺垫,Web API是JS的应用,大量使用JS基础语法做交互效果
1、API
API(应用程序编程接口Application Programming Interface):是预先定义的函数:API是给程序员提供的一种工具,帮助我们实现想要完成的功能,会用即可,不必纠结内部如何实现
2、Web API
Web API是浏览器提供的一套操作浏览器功能和页面元素的API(BOM和DOM)
Web API主要是针对于浏览器提供的接口,主要针对于浏览器做交互效果
Web API一般都有输入和输出(函数的传参和返回值),Web API很多都是方法(函数)
二、DOM
文档对象模型(Document Object Model):是W3C组织推荐的处理可扩展标记语言(HTML或XML)的标准编程接口
1、DOM树

 文档:一个页面就是一个文档,DOM中使用document来表示
 元素:页面中的所有标签都是元素,DOM中使用element来表示
 节点:网页中的所有内容都是节点(标签、属性、文本、注释等),DOM中使用node表示
 DOM把以上内容都看做是对象,DOM在实际开发中主要用来操作元素
2、获取元素
《1》根据ID获取
document.getElementById('id');
使用console.dir()可以打印我们获取的元素对象,更好的查看对象里面的属性和方法。
《2》根据标签名获取
 getElementByTagName()方法可以返回带有指定标签名的对象的集合
document.getElementByTagName('标签名');
注意:
 得到的是一个对象集合,想要操作里面的元素就需要遍历
 得到元素对象是动态的
 如果获取不到元素,则返回空的伪数组(因为获取不到对象)
还可以获取某个元素的所有指定标签名的子元素
element.getElementByTagName('标签名');
注意:父元素必须是单个对象(必须指明是哪一个元素对象),获取时不包括父元素自己
<div>
  <p>1111</p>
  <p>222</p>
  <p>333</p>
</div>
<script>
	var div = document.getElementsByTagName("div");
	var a = div[0].getElementsByTagName("p");
	console.log(a);
	console.dir(a);
</script>
《3》HTML5新增
document.getElementByClassName('类名');   // 根据类名返回元素对象集合
document.querySelector('选择器'); // 根据指定选择器返回第一个元素
document.querySelectorAll('选择器'); // 根据指定选择器返回
注意:querySelector和querySelectorAll里面的选择器需要加符号
《4》特殊元素获取
 获取body元素和获取html元素
document.body;  // 返回body元素对象
document.documentElement  // 返回html元素对象
3、事件基础
JS使我们有能力创造动态页面,而事件是可以被JS侦测到的行为。(触发–响应机制)
 常见的鼠标事件
| 鼠标事件 | 触发条件 | 
|---|---|
| onclick | 鼠标点击左键触发 | 
| onmouseover | 鼠标经过触发 | 
| onmouseout | 鼠标离开触发 | 
| onfocus | 获得鼠标焦点触发 | 
| onblur | 失去鼠标焦点触发 | 
| onmousemove | 鼠标移动触发 | 
| onmouseup | 鼠标弹起触发 | 
| onmousedown | 鼠标按下触发 | 
4、操作元素属性
DOM操作可以改变页面内容、结构和样式
《1》改变元素内容
element.innerText; // 去掉html标签、空格和换行
element.innerHTML  // 包括html,同时保留空格和换行
《2》常用元素的属性操作
innerText、innerHTML、src、href、id、alt、title
《3》表单元素的属性操作
type、value、checked、selected、disabled
《4》样式属性操作
 可以通过 JS 修改元素的大小、颜色、位置等样式
 JS 修改 style 样式操作,产生的是行内样式,CSS 权重比较高
element.style   // 行内样式操作
element.className  // 类名样式操作
注意:
 如果样式修改较多,可以采取操作类名方式更改元素样式
 className 会直接更改元素的类名,会覆盖原先的类名
 
 《5》自定义属性的操作
① 获取属性
element.属性  // 获取内置属性
element.getAttribute('属性')  // 获得自定义的属性
② 操作属性值
element.属性 = '值'
element.setAttribute('属性','值')  // 设置自定义属性值
③ 移除属性
element.removeAttribute('属性')
《6》H5自定义属性
 自定义属性目的:是为了保存并使用数据。有些数据可以保存到页面中而不用保存到数据库中。
 H5规定自定义属性data-开头做为属性名并且赋值。
 ① 兼容性获取 element.getAttribute(‘data-index’);
 ② H5新增 element.dataset.index 或者 element.dataset[‘index’]  IE11才开始支持
5、节点(node)操作
一般地,节点至少拥有nodeType(节点类型)、nodeName(节点名称)和nodeValue(节点值)这三个
 基本属性。
 元素节点 nodeType 为 1,属性节点 nodeType 为 2,文本节点 nodeType 为 3(文本节点包含文字、空格、换行等)
在实际开发中,节点操作主要操作的是元素节点
DOM 树把节点划分为不同的层级关系,常见的是父子兄层级关系。
 《1》父级节点
node.parentNode   
注意:返回某节点的父节点,是最近的一个父节点,如果指定的节点没有父节点则返回null
《2》子节点
 ① 第一种:
parentNode.childNodes(标准)  // 返回包含指定节点的子节点的集合,该集合为即时更新的集合
parentNode.firstChild  // 返回第一个子节点,找不到返回null,包含所有的节点
parentNode.lastChild  // 返回最后一个子节点,找不到返回null,包含所有的节点
注意:返回值里面包含了所有的子节点,包含元素节点,文本节点等
 如果只想要获得里面的元素节点,则需要专门处理。所以一般不提倡使用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(非标准)   // 是一个只读属性,返回所有的子元素节点。它只返回子元素节点,其余节点不返回 
// 以下两方法IE9以上才支持
parentNode.firstElementChild  // 返回第一个子元素节点,找不到返回null
parentNode.lastElementChild // 返回最后一个子元素节点,找不到返回null
想要得到第一个或最后一个子元素节点,实际开发中解决方案:
 1. 如果想要第一个子元素节点,可以使用 parentNode.chilren[0] 
 如果想要最后一个子元素节点,可以使用parentNode.chilren[parentNode.chilren.length - 1]
《3》兄弟节点
node.nextSibling  //  返回当前元素的下一个兄弟元素节点,找不到返回null,包含所有的节点
node.previousSibling // 返回当前元素的上一个兄弟元素节点,找不到返回null,包含所有的节点
// IE9以上支持
node.nextElementSibling // 返回当前元素下一个兄弟元素节点
node.previousElementSibling // 返回当前元素上一个兄弟节点
兼容性问题解决方案
// 封装一个兼容性的函数
function getNextElementSibling(element) {
	var el = element;
	while (el = el.nextSibling) {
		if (el.nodeType === 1) {
			return el;
		}
	}
	return null;
} 
《4》创建节点(动态创建元素节点)
document.createElement('tagName');
《5》添加节点
node.appendChild(child)  // 将一个节点添加到指定父节点的子节点列表的末尾(类似于css里面的after伪元素)
node。insertBefore(child,指定元素) // 添加到父节点的指定子节点前面(类似于的before伪元素)
《6》删除节点
node.removeChild(child)  // 返回删除的节点
《7》复制节点
node.cloneNode()  // 法返回调用该方法的节点的一个副本
注意:
 ① 如果括号参数为空或者为 false ,则是浅拷贝,即只克隆复制节点本身,不克隆里面的子节点。
 ② 如果括号参数为 true ,则是深度拷贝,会复制节点本身以及里面所有的子
《8》三种动态创建元素的区别
| 方法 | 特点 | 
|---|---|
| document.write() | 直接将内容写入页面的内容流,但是 文档执行完毕,则会导致页面全部重绘 | 
| element.innerHTML() | 将内容写入某某个DOM节点,页面不重绘, 创建多个元素效率更高(不要拼接字符串,采用数组形式拼接),结构稍微复杂 | 
| document.createElement() | 创建多个元素效率低一些,但是 结构更清晰 | 
三、以上内容总结
为了能够使JS操作HTML,JS有一套自己的DOM编程接口;对于HTML来说,DOM使html形成了一颗DOM树
关于DOM操作,主要是针对元素的操作,主要有创建、增、删、改、查、属性操作、事件操作
1、创建
document.write
innerHTML
createElement
2、增
appendChild
insertBefore
3、删
removeChild
4、改
src、href、title等  // 修改元素属性
innerHTML、innerText  //  修改普通元素内容
value、type、disable等  // 修改表单元素
style、className // 修改元素样式
5、查
getElementById、getElementsByTagName // DOM提供的API方法,不推荐
querySelector、querySelectorAll // H5新增,提倡
parentNode(父)、children(子)、previousElementSibling、nextElementSibling(兄)// 利用节点获取元素,提倡
6、属性操作
setAttribute	// 设置dom的属性值
getAttribute	// 得到dom的属性值
removeAttribute  // 移出属性
7、事件操作
| 鼠标事件 | 触发条件 | 
|---|---|
| onclick | 鼠标点击左键触发 | 
| onmouseover | 鼠标经过触发 | 
| onmouseout | 鼠标离开触发 | 
| onfocus | 获得鼠标焦点触发 | 
| onblur | 失去鼠标焦点触发 | 
| onmousemove | 鼠标移动触发 | 
| onmouseup | 鼠标弹起触发 | 
| onmousedown | 鼠标按下触发 | 
四、小案例
(添加/删除留言)
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        
        body {
            padding: 100px;
        }
        
        textarea {
            width: 200px;
            height: 100px;
            border: 1px solid pink;
            outline: none;
            resize: none;
        }
        
        ul {
            margin-top: 50px;
        }
        
        li {
            width: 300px;
            padding: 5px;
            background-color: rgb(245, 209, 243);
            color: red;
            font-size: 14px;
            margin: 15px 0;
        }
        
        li a {
            float: right;
        }
    </style>
</head>
<body>
    <textarea name="" id=""></textarea>
    <button>发布</button>
    <ul>
    </ul>
    <script>
        // 1. 获取元素
        var btn = document.querySelector('button');
        var text = document.querySelector('textarea');
        var ul = document.querySelector('ul');
        // 2. 注册事件
        btn.onclick = function() {
            if (text.value == '') {
                alert('您没有输入内容');
                return false;
            } else {
                // console.log(text.value);
                // (1) 创建元素
                var li = document.createElement('li');
                // 先有li 才能赋值
                li.innerHTML = text.value + "<a href='javascript:;'>删除</a>";
                // (2) 添加元素
                // ul.appendChild(li);
                ul.insertBefore(li, ul.children[0]);
                // (3) 删除元素 删除的是当前链接的li  它的父亲
                var as = document.querySelectorAll('a');
                for (var i = 0; i < as.length; i++) {
                    as[i].onclick = function() {
                        // node.removeChild(child); 删除的是 li 当前a所在的li  this.parentNode;
                        ul.removeChild(this.parentNode);
                    }
                }
            }
        }
    </script>
</body>
</html>



















