DOM总结
1:DOM - document object model 文档对象模型
作用:给我们提供了一些方法,让我们可以操作页面.
2: 获取标签对象的方式.
2.1:根据id名获取元素
console.log(document.getElementById("box"));
使用document.getElementById()获取元素失败时结果为null
注意:获取位置,如果在head中书写js代码获取元素,需要考虑标签 是否生成
2.2:根据标签名获取元素.
getElementsByTagName("div"),得到的是伪数组,要么遍历,要么给具体的 索引值.
3: js的入口函数.
window.onload = function () { };
作用:在入口函数内书写的代码会在页面完全加载(引入的文件,结构,图片,文件)后执行.
4:对标签进行样式设置操作
标签.style , 然后再访问具体的某个样式名
书写样式时,在css中加-的样式名,例如background-color,在js中需要将-去掉,并将后半部分的首字母大写
// font-size fontSize z-index zIndex
box.style.backgroundColor = "red";
5:文本操作.
标签.innerHTML
Innerhtml既可以设置文本,也识别标签.
6:DOM - 文档对象模型
前面我们说过只有对象才有属性和方法
通过观察我们发现,样式和文本操作均为通过属性的形式
使用DOM操作的标签以及其他内容均为对象形式
7:js中的事件:
js中的事件同样也是由三个部分组成
1 事件源(触发事件的元素)(被动)
2 事件类型(例如点击,鼠标移入)
3 事件处理程序(函数类型)
语法形式:
事件源.事件类型 = function(){
事件处理程序,当事件触发后,执行内部的所有代码;
}
8:操作标签自身支持的行内属性(id/title/class).
1:获取: 标签名.属性名 iv.id
设置: 标签名.属性名 = ”属性值”div.className = “current”
但是class比较的特殊,因为class是关键字,所以换成了className.
2:通过 标签.className = “abc” 设置的时候,需要将以前的类名带上,不然就会删除以前的类名了.
9:标签行内自定义属性的操作方式,无法通过标签.属性名的方式操作.
既可以设置标签行内的自定义属性,也可以设置标签自身支持的的行内属 性.但建议仅仅用作标签的行内自定义属性.
1 获取 标签.getAttribute(属性名);
console.log(box.getAttribute("hehe"));
console.log(box.getAttribute("id"));
2 设置 标签.setAttribute(要修改的属性名,修改成什么值)
box.setAttribute("hehe", "b");
3 移除 标签.removeAttribute(要移除的属性名)
box.removeAttribute("hehe")
box.removeAttribute("id").
10:事件内部的代码仅仅点击才执行,晚于页面的加载.其他加载完才执行.
解决方法:
1:自调用函数:
自调用函数(立即执行函数)的功能:
1 用于包裹作用域(模拟块级作用域).
2 减少全局变量的使用.
var lis = document.getElementsByTagName("li");
for (var i = 0; i < lis.length; i++) {
(function () {
var j = i;
lis[i].onclick = function () {
console.log(j);
};
})();
}
2:给DOM对象添加自定义的属性.(对象名.属性)
3:给标签添加行内的自定义属性.(setattribute/getAttribute/removeAttribute).
---------------------------------------------第二天------------------------------------------------------
11:DOM第二天有总结.
12:阻止默认的a标签的跳转,要在后面设置 return false.
Return false 可以阻止默认跳转.
13:鼠标的移入移出事件:
鼠标移入事件: onmouseover.
鼠标移出事件: onmouseout.
14:焦点事件:
onfocus 获取焦点事件:点击输入框时,光标在框内跳动
onblur 失去焦点事件:点击输入框以外,光标不跳到触发
15:表单操作内容,自带value属性,所以操作内容时直接使用value即可.
Input表单的默认值 value属性.
16:在所有表单的表单中,仅仅下拉菜单select的默认文本为innerHTML,其他的均为value.
17: 复选框是否选中 checked
checked 设置值为bool值,如果值为true,表示选中,false表示取消选中
注意点(不常用):如果设置的值不是bool值会进行隐式转换操作
cb.checked = "hehehe";
cb.checked = false;
-------------------------------------------第三天-------------------------------------------------
18:为什么会有兼容问题:
js中有许多的功能,但是某些功能无法在所有的浏览器中同时执行
针对这些功能,需要进行兼容性操作。
21: 文本操作.(都是属性)
Innerhtml 即可以生成文字,也可以生成标签
如果我们要给一个标签内部设置大量的文字信息,同样会进行内部的标签检索操作.
纯文本的设置:
①:innerText: IE提出的,兼容IE.
②:textcontent: 标准属性,但是低版本的IE(IE6/7/8)不支持.
22:ie总是出现兼容性的原因
1 浏览器升级麻烦
2 系统升级更麻烦
导致了ie会有多个版本同时在市面上存在,我们在书写代码时需要考虑到可能额会出现的兼容性问题,保证最大化的用户使用
23:能力检测:
检测当前这个功能是否可以使用,能用则用(看你行不行).
24:文本设置的兼容性:
先随意找到其中一个属性,进行使用,查看使用结果,可以用就用,不能用的话换另一个即可
if (typeof box.innerText == "string") {
//如果获取到了内容,为字符串,但是取值可能为空,所以直接利用隐式转换的方式不太严谨
box.innerText = "我是innerText设置的内容";
} else {
//不支持innerText,可以使用textContent
box.textContent = "我是textContent设置的内容";
}
25:通过style设置/获取的样式,仅仅是在行内显示,但是并不是所有的样式都是在行内.所有必须要通过其他的方式来获取样式.
①:getComputedStyle(). 获取计算后的样式(获取的样式值是标签最终生效的那个样式值). 标准方法,但是不兼容低版本的IE(IE6/7/8);
getComputedStyle(DOM对象).属性名 getComputedStyle(box, null).width
参数2,一会儿再说,先写一个null
获取结果为对象形式,是当前标签所有样式的集合
注意,此方法只可以进行样式值的获取,结果只读不可设置,结果为字符串,带单位
②: 标签.currentStyle IE自身支持,且得到得是对象.
标签.currentStyle.属性名 box.currentStyle.width.
③:DOM对象.getComputedStyle()与DOM对象.currentStyle的能力测试:
if (box.currentStyle) {
//只要进入了if,说明currentStyle的取值为对象,支持
console.log(box.currentStyle.width);
} else {
console.log(getComputedStyle(box, null).width);
}
26:
一次设置多个行内的样式属性值(不常用):
box.style.cssText = "width:100px;height:100px;background-color:red;";
27:设置样式的两种方式:
①:DOM对象.style.属性名 = 属性值.
②:DOM对象.className = 名字. 通过类名来修改样式
28:根据类名获取标签对象:
1:document.getElementsByClassName(类名);
但是低版本IE(IE6/7/8)不兼容,我们必须手写兼容程序:
获取标签对象中,仅仅有document.getElementsByTageName(标签名)/document.getElementById(ID名)是兼容IE的,所以在书写原生JS时最好使用tageName与ID的方式来获取标签对象.
书写能力检测:
//步骤1:进行能力检测
// if (document.getElementsByClassName) {
// //支持的代码
// document.getElementsByClassName("box");
// } else {
//如果进入到else,说明当前浏览器不支持此方法,自己书写功能实现。
//需求:根据给定的类名进行元素的获取
//1 获取body中的所有标签
var tags = document.body.getElementsByTagName("*");
var resultArr = [];//结果数组,用于保存获取到的标签
//2 检测当前某个标签的className属性的值
for (var i = 0; i < tags.length; i++) {
//3 取出当前某个标签的类名,用于检测
var oldCls = tags[i].className;
//4 验证时,需要考虑,如果取得的标签不是只有一个类名时,采用相等判断会导致不准确
//将标签的类名按照空格分割
var clsArr = oldCls.split(" ");
//5 遍历,查找指定的部分是否存在
for (var j = 0; j < clsArr.length; j++) {
//如果某个部分和指定类名相等,取出即可
if (clsArr[j] == "box") {
resultArr.push(tags[i]);
break;//跳出
}
}
}
console.log(resultArr);
// }
29:页面是如何显示的:
当一个页面被浏览器加载后需要执行以下几个基本步骤:
1 先解析html文件,将标签进行生成,根据每个标签之间的关系,生成一个树模型(节点树)
2 再解析css文件,将样式生成为样式树
3 将样式树和节点树合并,生成一个渲染树(页面等待进行绘制)
4 浏览器会根据渲染树将页面显示出来
4.1 排列:将每个标签确定尺寸和位置
4.2 绘制:将标签内部的内容显示出来(图片,颜色,文字)
现在我们的重点是上面的第一步
第一步会根据html标签生成节点树
作用为,生成每个html标签的对应的DOM对象,方便用户对标签的操作
作用2:一会儿我们要学习的新的访问关系
30: 节点:对节点树中的所有形式内容的统称(都可称为节点)
元素节点 :标签,页面元素
文本节点 :文本内容
属性节点 :标签的行内属性
注释节点 :注释
根节点 :document (DOM中的顶级对象,所有DOM的内容均为他下属内容)
31:节点访问总共分为两类:(都是属性)/都是属性/都是属性
①:上下级访问关系(父子关系);父节点/子节点
②:同级访问关系(兄弟关系);
32:上下级访问关系(都是属性):
①:父节点: 节点.parentNode
注意:任意节点,如果具有父节点parentNode的值,结果一定为元素节点(标签).
②:子节点:
节点.childNodes 获取所有子节点,但包括换行/空格等文本节点.
节点.children 获取所有元素子节点(常用)
节点.firstChild 获取第一个子节点,可能是文本节点.
节点.firstElementChild 获取第一个元素子节点.(不兼容低版本的IE,但是 不需要写兼容代码).可以用以下方式来替换: 节点.children[0];
节点.lastChild 获取最后一个子节点,可能是文本节点.
节点.lastElementChild 获取最后一个元素子节点,也不兼容低版本的IE,
不需要书写兼容代码,可以用这个来替换:
节点.children[节点.children.length - 1];
33:同级的访问关系(都是属性):
节点.previousSibling 前一个节点,但是会获取到换行空格等内容.
节点.previousElementSibling 前一个元素节点,低版本的IE不兼容.
节点.nextSibling 下一个节点,会获取到换行空格等内容.
节点.nextElementSibling 下一个元素节点,低版本的IE不兼容.
34:对象的比较,比较的是内存地址值.
每次生成对象,就会在堆内存中产生一个区域存放数据,会有一个内存地址值.
要两个对象相等,必须内部保存的指针相同才可以(实际上是同一个对象才行)
35:获取每个兄弟元素:
找父元素,再找所有的子元素,但是必须排除自己.
36:节点的移动:
1 标签.appendChild(要移动的节点) 追加子节点
效果:将传入的节点添加到调用节点内的所有子节点后面(最后)
A.appendChild(B); 将B 添加到A元素的子元素的最后面.
2 标签.insertBefore(要移动的节点,参考节点) 插入子节点
效果,将要移动的节点插入到指定的参考节点之前。
注意:参考节点必须为调用元素的子节点才可以使用。
A.insertBefore(B, C); 将B移动到元素A里面的元素C前面.
当没有传入第二个参数时,insertBefore()相当于appendChild();
------------------------------------------第四天-------------------------------------------------------
37:为什么要动态加载元素:
1:提高页面的响应速度(动态加载结构).
2:节省流量(动态加载图片).
38:动态加载元素的几种方式:
1:document.write(字符串); 字符串 = “<div>我是div</div>”
2:DOM对象.innerHTML = 字符串;
3:document.createElement(标签名);
39: document.write(字符串):
document.write(字符串)的方式基本不用,因为缺点是在太多:
①:无法指定位置添加:
②:如果将document.write在页面加载后使用,会导致页面所有内容被清除:
40:DOM对象.innerHTML = 字符串:
1):既可以更改内部的文本,也可以加载标签.
2):特点
①:会对标签内部的原有内容进行覆盖:
1.1:解决方法:取出原来的内容与需要生成的内容进行拼接,再一起生成.
box.innerHTML = box.innerHTML + "<div>我是div</div>";
box.innerHTML += "<div>我是div</div>";简化写法
1.2:因为是将旧标签替换为了新标签,所以原来旧标签的事件与自定义属性均不见了.
②:执行效率比较差:
查看用了多长事件的方法:
console.time("innerHTML的执行速度");
for (var i = 0; i < 2000; i++) {
box2.innerHTML += "<div></div>";
}
console.timeEnd("innerHTML的执行速度");
41:document.createElement(标签名)
在创建元素后不会立刻在页面中显示
如果想要在页面中显示,需要添加到页面中的某个位置(appendChild/insertBefore)
而且效率比较的高,与innerhtml的效率比例为1:1000:
总结:我们在使用document.createElement时,没有特定的使用场景,只要innerHTML不适用,均可使用document.createElement.
42:解决innerhtml创建元素效率低下的问题:
解决方法:可以使用字符串或者数组的替换方式,在循环中替代innerHTML,将最终结果一次设置给innerHTML属性.
代码优化后,执行时间为 2.7ms,大幅度的提高执行速度
console.time("innerHTML的执行速度");
for (var i = 0; i < 2000; i++) {
str += "<div></div>";
}
box.innerHTML = str;
console.timeEnd("innerHTML的执行速度");
43:几种创建元素的方式的总结:
直接用document.createElement(标签名)就好了,大量的创建我们后面会用模板的形式.
①:innerHTML的使用场景:
如果需要创建的结构大量重复并且结构比較复杂时,推荐使用innerHTML的方式(操作方式为字符串拼接,可以直接拷贝html中设计好的结构,直接使用).
②:document.createElement必须使用的场景:
要进行动态创建元素的位置上具有旧的标签,并且旧的标签可能具有事件时,必须使用此方式。
44:移除子节点:
父节点.removeChild(要删除的子节点);
45:onkeydown/onkeyup 事件
onkeydown 当键盘上的某个按键按下后,触发事件
onkeyup 当键盘上的某个按键按下后,按键抬起触发
获取输入框的内容时:
1 keydown无法获取到本次刚输入的内容部分
2 keyup可以获取到当前输入的结果(常用)
46: str.indexOf(“abc”) abc是否是str的一部分 返回true/false
使用indexOf的时候想要匹配成功,参数字符串必须比调用的字符串短
注意的点:使用空字符串对其他字符串进行匹配时,可以在开头立刻匹配成功
-------------------------------------------第五天----------------------------------------------
47: 克隆 标签.cloneNode(bool值)
需要克隆的标签不要设置id名.
默认值为false,false表示浅复制,只复制标签本身,不复制内部内容
true表示深复制,复制标签以及内部内容
无论哪种克隆方式(深复制或者浅复制)均无法复制标签的内容或内部的属性.
复制完的标签必须使用appendchild,或者insertbefore添加到具体的标签内,不然看不到.
48: 替换节点: replaceChild();
父节点.replaceChild(新节点,替换哪个子节点);
返回值,替换掉的节点会被返回,可以根据需求继续使用;
49:节点是对节点树中所有内容的统称(对页面中所有内容的统称)
1 元素节点
2 属性节点
3 文本节点
7 注释节点
9 document 根节点
每个节点都具有三个属性:
①:nodeType 用于标注某个节点的类型:
返回值为数值类型,1表示元素节点
②:nodeValue 用于表示节点的节点值
元素节点没有节点值属性,返回值为null
③:nodeName 用于显示节点名
nodeName属性对于元素节点来说,结果为标签名(在html中为大写形式,在xhtml中为小写形式)
50:总结:
[图片上传失败...(image-d355f4-1515936359360)]
-------------------------特效第一天-----------------------
51:offsetwidth/offsetheight
1: 标签对象.offsetwidth/offsetheight
2:是一个只读属性,没有px单位.可直接运算.
3:获取的盒子的真实大小: width/height+padding+border.
4:
[图片上传失败...(image-8cf329-1515936359359)]
52: 标签对象.style.width/height.
1:仅仅能获取/设置行内样式.
2:获取/设置的均是字符串,带px单位.
3:获取/设置的仅仅是 width.
4:
[图片上传失败...(image-d3da7d-1515936359359)]
53:总结:
获取宽度/高度的时候,用offsetWidth/offsetHeight
设置宽度/高度的时候,用style.width/style.height,记得带px单位.且为行内式
54:parentNode与offsetParent
1:标签对象.parentNode
标签对象.offsetParent
2: parentNode 找父类元素.
offsetParent 找最近的有定位的父元素.如果都没有,一直找到body.
55:标签对象.style.left/top.
1:给定位的盒子设置偏移的量.
2:仅仅能获取/设置行内样式.
3:获取/设置的均是字符串,带px单位.
4:
[图片上传失败...(image-151f37-1515936359359)]
56:标签对象.offsetLeft/offsetTop
1: offsetLeft: 自身左侧到offsetParent左侧的距离:left + margin-left
offsetTop:自身顶部到offsetParent顶部的距离 : top + margin-top
2:仅仅能获取,不能设置.且为数值类型.
3:
[图片上传失败...(image-9ffdb-1515936359358)]
57:总结.
获取操作:用offset系列
设置操作:用style.xxx进行设置。
[图片上传失败...(image-92ee70-1515936359358)]
58:getComputedStyle 获取计算后的样式
1:标签对象.getComputedStyle(ele,null)
2:传入两个参数,
第一个参数: 元素,需要获取的标签对象
第二个参数: 伪元素,null.
3:返回的是一个对象,后面需要.具体的属性.
[图片上传失败...(image-630c26-1515936359358)]
4:存在兼容问题:
element:获取谁的样式
attr: 获取的样式的属性名
function getStyle(element, attr) {
//能力检测
if(window.getComputedStyle) {
return window.getComputedStyle(element, null)[attr];
}else {
return element.currentStyle[attr];
}
}
59:节流阀步骤:
1. 定义节流阀开关
2. 判断阀门是否打开,只有打开了才能执行
3. 关闭阀门,不让其他人执行
4. 执行完动画之后,打开阀门
60:三大家族.
Offset家族
Scroll家族
Client家族.
61:Offset家族.
标签对象.offsetHeight/offsetWidth/offsetParent/offsetLeft/offsetTop
1:offset系列主要有:offsetHeight、offsetWidth、offsetParent、offsetLeft、offsetTop
2:特点:
获取的是元素真实的高度和宽度
获取到的是数值类型,方便计算
3:offsetHeight与offsetWidth是只读属性,不能设置。
offsetHeight = height + paddnig + border
offsetWidth = width + padding + border
4:与style.height/style.width区别.
只能获取行内样式
获取到的是字符串类型带px单位,需要转换
[图片上传失败...(image-71178d-1515936359357)]
62:scroll家族
(1): scroll家族用来获取盒子内容的大小和位置
scroll家族有:scrollWidth、scrollHeight、scrollLeft、scrollTop
(2):scrollWidth与scrollHeight是盒子内容的真实的宽度和高度。与和盒子大小无关,仅仅与盒子的内容有关系。
(3):scrollTop是盒子内容被滚动条卷去的头部的高度。scrollLeft是盒子内容被滚动条卷去的左侧的宽度。
[图片上传失败...(image-9b1a30-1515936359357)]
(4):onscroll事件,对于有滚动条的盒子,可以使用onscroll注册滚动事件,每滚动一像素,就会触发该事件。
var box = doucment.getElementById(“box”);
box.onscroll = function(){
//事件处理程序
}
:一般用来获取scrollLeft与scrollTop.但是有兼容性的问题,将其封装如下:
function scroll() {
return {
top: window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0,
left: window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0
};
}
//如何使用
console.log(scroll().top);//获取页面被卷去的头部的距离
console.log(scroll().left);//获取页面被卷去的左侧的距离
63:client家族.
(1):client家族用于获取盒子可视区的大小
client家族有clientWidth、clientHeight、clientLeft、clientTop
(2):如果内容没有超出盒子,clientWidth与scrollWidth相同.
[图片上传失败...(image-ad542d-1515936359357)]
(3):三大家族的对比
[图片上传失败...(image-6a7b14-1515936359357)]
64:onresize事件.
1:onresize事件会在窗口被调整大小的时候发生。
window.onresize = function(){
//事件处理程序
}
2:client系列一般用来获取页面的可视区宽高
但是存在兼容性问题,书写兼容如下:
function client() {
return {
width: window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth || 0,
height: window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight || 0
};
}
65:事件对象.
1:什么是事件对象:
在触发某个事件的时候,都会产生一个事件对象Event,这个对象中包含所有与事件相关的一些信息,包括触发事件的元素,事件的类型以及其他与事件相关的信息。
2:获取事件对象存在兼容性的问题.
btn.onclick = function(event){
//只要用到了事件对象,就要记得处理浏览器兼容性
event = event || window.event;
}
66:事件对象中属性.
1:在事件对象中我们经常用到的是鼠标位置信息与键盘码信息.
2:记录了鼠标位置信息的相关属性.
screenX与screenY:光标相对于屏幕左上角的水平位置与垂直位置。
clientX与clientY:光标相对于可视区左上角的水平位置和垂直位置。
pageX与pageY:光标相对于网页(文档document)左上角的水平位置与垂直位置(推荐使用)
[图片上传失败...(image-378c05-1515936359356)]
3:记录了键盘码的属性.
event.keyCode:键盘按下的那个键的键盘码
4:pageX与pageY存在兼容性的问题.
function getPage(event) {
return {
//在IE678中使用document.documentElement.scrollLeft就可以获取到scrollTop的值
x:event.pageX || event.clientX + document.documentElement.scrollLeft,
y:event.pageY || event.clientY + document.documentElement.scrollTop
}
}
67:on注册事件.
1:注册事件:
box.onclick = function(){//代码块}.
2:移除事件.
box.onclick = null.
3:同一个元素的同一个类型的事件,仅仅能注册一个,注册多个会产生覆盖.
68:addEventListener 绑定事件
1:语法.
第一个参数:事件的类型:click mouseover
第二个参数:函数,监听者,每次点击,这个函数就执行。
第三个参数:false
addEventListener(type, func, useCapture);
2:如果想让你注册的事件能够被移除就不能使用匿名函数.
function fn1() {
alert("hehe");
}
//如果想让注册的事件能移除,不能用匿名函数。
box.addEventListener("click", fn1, false);
69:removeEventListener. 移除事件.
1:要想被移除,就不能是匿名函数
2:语法:
第一个参数:参数类型
第二个参数:要移除的那个函数
第三个参数:false
removeEventListener(type, func, useCapture);
70:在IE6/7/8里面不支持addEventListener /removeEventListener.
仅仅有attachEvent与detachEvent
1:attachEvent的用法.
//type:事件类型 需要加上on onclick onmouseenter
//func:需要执行的那个事件
attachEvent(type, func)
2:detachEvent的用法.
//type:事件类型 需要加上on onclick onmouseenter
//func:需要执行的那个事件
detachEvent(type, func)
71:注册/移除事件的封装.
//添加事件
function addEvent(element, type, fn){
//能力检测
if(element.addEventListener){
element.addEventListener(type, fn, false);
}else if(element.attachEvent){
element.attachEvent("on"+type, fn);
}else {
//如果都不行,那就用on方式
element["on"+type] = fn;
}
}
//移除事件
function removeEvent(element, type, fn) {
if(element.removeEventListener){
element.removeEventListener(type, fn, false);
}else if(element.detachEvent){
element.detachEvent("on"+type, fn);
}else {
element["on"+type] = null;
}
}
72:常见的鼠标事件.
onmousedown:鼠标按下事件
onmouseup:鼠标弹起事件
onclick:单击事件
ondblclick:双击事件
onmouseover:鼠标经过事件
onmouseout:鼠标离开事件
onmousemove:鼠标移动事件
onfocus:鼠标获得焦点事件
onblur:鼠标失去焦点事件
73:常见的键盘事件.
onkeydown:键盘按下时触发
onkeyup:键盘弹起时触发
对于鼠标事件,事件对象中有一系列的XY记录了鼠标的位置信息。而键盘事件中,事件对象有一个event.keyCode属性,记录了按下去的键的键盘码.
74:正则表达式在笔记本与特效第五天的笔记上.