什么是DOM:

DOM ,全称 Document Object Model
文档对象模型。

JS中通过DOM来对HTML文档进行操作。
只要理解了DOM就可以随心所欲的操作WEB页面。

文档	文档表示的就是整个的HTML网页文档。
对象	对象表示将网页中的每一个部分都转换为了一个对象。
模型	使用模型来表示对象之间的关系,这样方便我们获取对象。

节点

节点Node ,是构成我们网页的最基本的组成部分,网页中的每一个部分都可以称为是一个节点。
比如:html标签、属性、文本、注释、整个文档等都是一个节点。

虽然都是节点,但是实际上他们的具体类型是不同的。
比如:标签我们称为元素节点、属性称为属性节点、文本称为文本节点、文档称为文档节点。

节点的类型不同,属性和方法也都不尽相同。

Node——构成HTML文档最基本的单元。

常用节点分为四类:
	文档节点 :整个HTML文档
	元素节点 :HTML文档中的HTML标签
	属性节点 :元素的属性
	文本节点 :HTML标签中的文本内容
节点的属性
文档节点(document)
文档节点document ,代表的是整个HTML文档,网页中的所有节点都是它的子节点。

document对象作为window对象的属性存在的,我们不用获取可以直接使用。

通过该对象我们可以在整个文档内访问查找节点对象,并可以通过该对象创建各种节点对象。
元素节点(Element)
HTML中的各种标签都是元素节点,这也是我们最常用的一个节点。

浏览器会将页面中所有的标签都转换为一个元素节点,

我们可以通过document的方法来获取元素节点。<br>比如:根据id属性值获取一个元素节点对象。

document.getElementById()
文本节点(Text)
文本节点表示的是HTML标签以外的文本内容,任意非HTML的文本都是文本节点。

它包括可以字面解释的纯文本内容。
文本节点一般是作为元素节点的子节点存在的。

获取文本节点时,一般先要获取元素节点。
再通过元素节点获取文本节点。
例如:获取元素节点的第一个子节点,一般为文本节点
元素节点.firstChild;
属性节点(Attr)
属性节点表示的是标签中的一个一个的属性,
这里要注意的是属性节点并非是元素节点的子节点,而是元素节点的一部分。

可以通过元素节点来获取指定的属性节点。

例如:元素节点.getAttributeNode("属性名");

注意:我们一般不使用属性节点。

文档的加载

浏览器在加载一个页面时,是按照自上向下的顺序加载的,读取到一行就运行一行,
如果将script标签写到页面的上边,在代码执行时,
页面还没有加载,DOM对象也没有加载,会导致无法获取到DOM对象。

onload事件会在整个页面加载完成之后才触发,为window绑定一个onload事件,
该事件对应的响应函数将会在页面加载完成之后执行,
这样可以确保我们的代码执行时所有的DOM对象已经加载完毕了。

将js代码编写到页面的下部就是为了可以在页面加载完毕以后再执行js代码。

window.onload = function(){
	var btn = document.getElementById("btn");
	btn.onclick = function(){
		alert("hello");
	};
};

获取元素节点

通过document对象调用

getElementById() 		通过id属性获取一个元素节点对象
getElementsByTagName()  通过标签名获取一组元素节点对象
getElementsByName()     通过name属性获取一组元素节点对象

获取元素节点的子节点

通过具体的元素节点调用

getElementsByTagName()
    方法 返回当前节点的指定标签名后代节点
    可以根据标签名来获取一组元素节点对象
    这个方法会给我们返回一个类数组对象,
    所有查询到的元素都会封装到对象中
    即使查询到的元素只有一个,也会封装到数组中返回

childNodes
    属性 ,表示当前节点的所有子节点
    childNodes属性会获取包括文本节点在内的所有节点
    根据DOM标签与标签间空白也会当成文本节点
	注意:在IE8及以下的浏览器中,不会将空白文本当成子节点

firstChild
    属性 ,表示当前节点的第一个子节点 (包括空白文本节点)

firstElementChild
    获取当前元素的第一个子元素
	firstElementChild不支持IE8及以下的浏览器,如果需要兼容他们尽量不要使用

lastChild
    属性 ,表示当前节点的最后一个子节点

获取父节点和兄弟节点

通过具体的节点调用

parentNode
    属性 ,表示当前节点的父节点

previousSibling
    属性 ,表示当前节点的前一个兄弟节点

previousElementSibling
    获取前一个兄弟元素,
	IE8及以下不支持

nextSibling
    属性 ,表示当前节点的后一个兄弟节点

元素节点的属性

获取: 元素对象.属性名
    例: element.value
    	element.id
    	element.className
设置 ; 元素对象.属性名 =新的值
    例:element.value = “hello”
    	element.id = “id01”
    	element.className = “newClass”

其他属性

nodeValue
    文本节点可以通过nodeValue属性获取和设置文本节点的内容

innerHTML
    元素节点通过该属性获取和设置标签内部的html代码
    对于自结束标签,这个属性没有意义,
    如果需要读取元素节点属性,直接使用
        元素.属性名。
    例子:
        元素.id
        元素.name
        元素.value

	注意:class属性不能采用这种方式,
		 读取class属性时需要使用 元素.className

innerText
    该属性可以获取到元素内部的文本内容,
    它和innerHTML类似,不同的是它会自动将html去除

dom查询的其他的方法

document.documentElement
    保存的是html根标签

document.all
    代表页面中所有的元素

getElementsByClassName()
    根据元素的class属性值查询一组元素节点对象
    可以根据class属性值获取一组元素节点对象,
	但是该方法不支持IE8及以下的浏览器

使用CSS选择器进行查询

document.querySelector()
    需要一个选择器的字符串作为参数,
    可以根据一个CSS选择器来查询一个元素节点对象。
    虽然IE8中没有getElementsByClassName()
    但是可以使用querySelector()代替
    使用该方法总会返回唯一的一个元素,
    如果满足条件的元素有多个,那么它只会返回第一个。

document.querySelectorAll()
    该方法和querySelector()用法类似,
    不同的是它会将符合条件的元素封装到一个数组中返回
    即使符合条件的元素只有一个,它也会返回数组

注意:
    使用CSS选择器进行查询的方法是静态方法
    如果DOM结构发生改变,操作DOM时,需要重新获取

dom增删改

document.createElement()
    可以用于创建一个元素节点对象,它需要一个标签名作为参数,
    将会根据该标签名创建元素节点对象,并将创建好的对象作为返回值返回。

document.createTextNode()
    可以用来创建一个文本节点对象,需要一个文本内容作为参数,
    将会根据该内容创建文本节点,并将新的节点返回

appendChild()
    向一个父节点中添加一个新的子节点
    语法:父节点.appendChild(子节点);

insertBefore()
    可以在指定的子节点前插入新的子节点
    语法:父节点.insertBefore(新节点,旧节点);

replaceChild()
    可以使用指定的子节点替换已有的子节点
    语法:父节点.replaceChild(新节点,旧节点);

removeChild()
    可以删除一个子节点
    语法:
        父节点.removeChild(子节点);
     	子节点.parentNode.removeChild(子节点);

使用innerHTML也可以完成DOM的增删改的相关操作
一般我们会两种方式结合使用

使用DOM操作CSS

通过JS修改元素的样式:(修改的是内联样式)

语法:元素.style.样式名 = 样式值

注意:如果CSS的样式名中含有-,
      这种名称在JS中是不合法的比如background-color
      需要将这种样式名修改为驼峰命名法,去掉-,
      然后将-后的字母大写,backgroundColor

我们通过style属性设置的样式都是内联样式,
内联样式有较高的优先级,
所以通过JS修改的样式往往会立即显示。
但是如果在样式中写了!important,
则此时样式会有最高的优先级,
即使通过JS也不能覆盖该样式,
此时将会导致JS修改样式失效。
所以尽量不要为样式添加!important

读取元素的样式(兼容性问题)

currentStyle:
    获取元素的当前显示的样式
    语法:元素.currentStyle.样式名
    它可以用来读取当前元素正在显示的样式,
    如果当前元素没有设置该样式,则获取它的默认值
	currentStyle只有IE浏览器支持,其他的浏览器都不支持

getComputedStyle()
    在其他浏览器中可以使用getComputedStyle()这个方法
    来获取元素当前的样式
    这个方法是window的方法,可以直接使用
    需要两个参数:
    	第一个:要获取样式的元素
    	第二个:可以传递一个伪元素,一般都传null
    该方法会返回一个对象,对象中封装了当前元素对应的样式
    可以通过对象.样式名来读取样式
    如果获取的样式没有设置,则会获取到真实的值,而不是默认值
    比如:没有设置width,它不会获取到auto,而是一个长度
	但是该方法不支持IE8及以下的浏览器

通过currentStyle和getComputedStyle()读取到的样式都是只读的,
不能修改,如果要修改必须通过style属性

// 读取元素的样式(兼容方式代码)
/*
* 定义一个函数,用来获取指定元素的当前的样式
* 参数:
* 		el: 要获取样式的元素
* 		name: 要获取的样式名
*/

function getStyle(el , name){
	if(window.getComputedStyle){
		// 正常浏览器的方式,具有getComputedStyle()方法
		return getComputedStyle(el , null)[name];
	}else{
		// IE8的方式,没有getComputedStyle()方法
		return el.currentStyle[name];
	}
	// return window.getComputedStyle?getComputedStyle(obj , null)[name]:obj.currentStyle[name];
}

其他样式操作的属性

clientWidth
clientHeight
    这两个属性可以获取元素的可见宽度和高度
    这些属性都是不带px的,返回都是一个数字,可以直接进行计算
    会获取元素宽度和高度,包括内容区和内边距
    这些属性都是只读的,不能修改

offsetWidth
offsetHeight
    获取元素的整个的宽度和高度,
    包括内容区、内边距和边框

offsetParent
    可以用来获取当前元素的定位父元素
    会获取到离当前元素最近的开启了定位的祖先元素
    如果所有的祖先元素都没有开启定位,则返回body

offsetLeft
    当前元素相对于其定位父元素的水平偏移量
offsetTop
    当前元素相对于其定位父元素的垂直偏移量

scrollWidth
scrollHeight
    可以获取元素整个滚动区域的宽度和高度

scrollLeft
    可以获取水平滚动条滚动的距离
scrollTop
    可以获取垂直滚动条滚动的距离

当满足
    scrollHeight - scrollTop == clientHeight
    说明垂直滚动条滚动到底了
当满足
    scrollWidth - scrollLeft == clientWidth
    说明水平滚动条滚动到底

定时器

定时调用
JS的程序的执行速度是非常非常快的,如果希望一段程序,
可以每间隔一段时间执行一次,可以使用定时调用。

setInterval()
    定时调用,可以将一个函数,每隔一段时间执行一次
    参数:
    	1.回调函数,该函数会每隔一段时间被调用一次
    	2.每次调用间隔的时间,单位是毫秒
    返回值:
    	返回一个Number类型的数据;
    	这个数字用来作为定时器的唯一标识

clearInterval()
    可以用来关闭一个定时器;
    该方法中需要一个定时器的标识作为参数,
    这样将关闭标识对应的定时器;
    clearInterval()可以接收任意参数,
    如果参数是一个有效的定时器的标识,
	则停止对应的定时器,
	如果参数不是一个有效的标识,则什么也不做。
	// clearInterval(timer);
延时调用
setTimeout()
延时调用一个函数不会马上执行,而是隔一段时间以后再执行,而且只会执行一次;
延时调用和定时调用的区别,定时调用会执行多次,而延时调用只会执行一次;
延时调用和定时调用实际上是可以互相代替的,在开发中可以根据自己需要去选择
使用clearTimeout()来关闭一个延时调用

var timer = setTimeout(function(){
	console.log(num++);
},3000);
//使用clearTimeout()来关闭一个延时调用
clearTimeout(timer);
10-07 11:32