JavaScript 基础4 BOM和DOM
- BOM
- DOM
- 1.文档对象模型DOM(document Object Model)
- 2、节点的种类
- 3、查找元素节点
- 3.1.getElementById方法
- 8、setAttribute、getAttribute、removeAttribute方法
- 9、firstChild和lastChild属性
- 10、DOM节点(节点属性)
- 11、childNodes
- 12、parentNode、previousSibling、nextSibling和ownerDocument属性
- 13、一些补充
- 14、attributes属性(了解)
- 15、忽略空白节点
- 16、节点操作
- 17. this
- 18. offset系列
- 19.文档碎片问题
- 20. 遍历
BOM
1、BOM的概念和定义 (browser object model浏览器对象模型)
- Bom 就是浏览器的对象【模型】,我们如何操控这个对象模型?
提起BOM就不得不提起JavaScript的构成。 - ECMAScript为JavaScript的核心,但是要是在浏览器中使用JavaScript,那么JavaScript需要听从BOM的调遣。
2、系统对话框
- window 方法 (一般情况下window可以省略)
浏览器可以通过alert()、confirm()和prompt()方法可以调用系统对话框向用户显示信息。 - alert() 弹出警告框
- confirm() 弹出一个带确定和取消的提示框
返回值:如果点击确定,返回true
如果点击取消,返回false - prompt() 弹出一个带输入框的提示框
第一个参数:面板上显示的内容
第二个参数:输入框里面的默认(可以不传入)
返回值:点击确定,返回输入框中的内容
点击取消,返回null。
//弹出警告
alert(“Lee”); //直接弹出警告框 window.alert() window可省略
//提示框
//确定和取消
confirm(“请确定或者取消”);
if(confirm((“请确定或者取消”)){
alert(“您按了确定!”); //按确定返回true
}else{
alert(“您按了取消!”) //按取消返回false
}
//输入带输入提示框
var num = prompt(“请输入一个数字”, 0); //两个参数,一个提示,一个值
alert(num); //得到输入的值
3、open方法
- window.open() 方法可以导航到一个特定的URL,也可以打开一个新的浏览器窗口,一般可以接受三个参数:
- 要加载的URL
- 窗口的名称或者窗口的目标
- 一个特性的字符串
open(“http://www.baidu.com”); //新建页面并打开百度
open(“http://www.baidu.com”, “baidu”); //新建页面并命名窗口并打开百度
open(“http://www.baidu.com”, “_parent”); //在本页窗口打开,_blank是新建
【注】不命名会每次打开新窗口,命名的第一次打开新窗口,之后在这个窗口中加载。
第三个参数字符串中的参数说明:
open('http://www.baidu.com','baidu','width=400,height=400,top=200,left=200’);
//open本身返回子窗口的window对象
var box = open();
box.alert(''); //可以指定弹出的窗口执行 alert();
4、延时器
- setTimeout() 指定的时间过后执行代码
function box(){
alert(“Lee”);
}
setTimeout(box, 1000); //直接传入函数名即可
setTimeout(function(){ //推荐做法,匿名函数
alert(“Lee”);
}, 1000);
- 【注】直接使用函数传入的方法,扩展性好,性能更佳。
上述方法会返回唯一标识符,可以通过它来取消超时调用。
要取消尚未执行的超时调用计划,可以调用**clearTimeout()**方法并将相应的超时调用ID作为参数传递给它。
clearTimeout(timer);
5、location对象(地址栏)
location是BOM对象之一,它提供了与当前窗口中加载的文档有关的信息,还提供了一些导航功能。
- location对象是window对象的属性,也是document对象的属性;
- 所以window.location和document.location等效。
5.1.location对象的属性
-
url:统一资源定位符。
-
协议://IP(域名)/:端口号/路径/?查询字符串#锚点
location.hash = ‘#1’; //设置#后的字符串,并跳转
alert(location.hash); //获取#后的字符串
location.port = 8888; //设置端口号,并跳转
alert(location.port); //获取当前端口号
location.hostname = ‘Lee’ ; //设置主机名,并跳转
alert(location.hostname); //获取主机名
location.pathname = ‘Lee’; //设置当前路径,并跳转
alert(location.pathname); //获取当前路径
location.protocal = “ftp:”; //设置协议,没有跳转
alert(location.protocal); //获取当前协议
location.search = “?id=5”; //设置?后面的字符串,并跳转
alert(location.search); //获取?后面的字符串
location.href = “http://www.baidu.com”; //设置跳转的URL,并跳转
alert(location.href); //获取当前的URL
5.2.location对象的方法
- location.assign(‘http://www.baidu.com’); //跳转到指定的URL,在当前窗口跳转带这个url
- location.reload(); //最有效的重新加载,有可能缓存加载
- location.reload(true); //强制加载,从服务器源头重新加载
- location.replace(“http://www.baidu.com”); //在当前窗口替换成新的url。不会产生历史记录。
6、history对象:掌管当前窗口历史记录
-
【history对象】
history对象是window对象的属性,它保存这用户上网的记录,从窗口被打开的那一刻算起。 -
属性
history.length; //history对象中的记录数 -
方法
history.back(); //前往浏览器历史条目前一个URL,类似后退
history.forward(); //前往浏览器历史条目下一个URL,类似前进
history.go(num); //浏览器在history对象中向前或向后- 参数: 0 刷新当前页面
正整数 前进n条记录
负整数 后退n条记录
- 参数: 0 刷新当前页面
DOM
1.文档对象模型DOM(document Object Model)
-
DOM 是 W3C(万维网联盟)的标准。DOM 定义了访问 HTML 和 XML 文档的标准:
-
“W3C 文档对象模型 (DOM) 是中立于平台和语言的接口,它允许程序和脚本动态地访问和更新文档的内容、结构和样式。”
- HTML-页面结构
- css-页面样式
- javascript –页面行为操作
-
DOM 中的三个字母,
- D(文档)可以理解为整个 Web 加载的网页文档;
- O(对象)可 以理解为类似 window 对象之类的东西,可以调用属性和方法,这里我们说的是 document 对象;
- M(模型)可以理解为网页文档的树型结构。
所谓DOM就是以家族的形式描述HTML 节点有 父子 兄弟
注:在JavaScript里真的这么叫!!!只不过加上了节点两个字称作父子节点,兄弟节点。
- 加载 HTML 页面时,Web 浏览器生成一个树型结构,用来表示页面内部结构。DOM 将 这种树型结构称为节点组成的节点树。
2、节点的种类
3、查找元素节点
-
document.getElementById(id);
-
node.getElementsByTagName(标签名);
- 功能:从node节点开始,通过标签名获取符合条件的元素节点。
- 返回值:伪数组/类数组
-
node.getElementsByClassName(class名字) (IE8以下不兼容)
- 功能:通过class名字获取符合条件的元素节点。
-
document.getElementsByName(name属性的值);
- 功能:通过name属性的值获取符合条件的元素节点。
- 【注】一般使用在表单元素里。
3.1.getElementById方法
- getElementById()方法,接受一个参数:获取元素的 ID。
- 如果找到相应的元素则返回该 元素的 HTMLDivElement 对象,如果不存在,则返回 null。
document.getElementById('box'); //获取 id 为 box 的元素节点
- PS:上面的例子,默认情况返回 null,这无关是否存在 id="box"的标签,而是执行顺序 问题。解决方法:
- 把 script 调用标签移到 html 末尾即可;
- 使用 onload 事件来处理 JS,等 待 html 加载完毕再加载 onload 事件里的 JS。
window.onload=function() { //预加载 html 后执行
document.getElementById('box'); //id具有唯一性
};
//可以通过 if(document.getElementById) //来判断是否支持
3.2.元素节点属性
当我们通过 getElementById()获取到特定元素节点时,这个节点对象就被我们获取到了, 而通过这个节点对象,我们可以访问它的一系列属性。
document.getElementById(‘box’).tagName; //DIV
document.getElementById(‘box’).innerHTML; //测试 Div
3.3.元素节点的HTML属性
- document.getElementById(‘box’).id; //获取 id
- document.getElementById(‘box’).id=‘person’; //设置 id
- document.getElementById(‘box’).title; //获取 title
- document.getElementById(‘box’).title=‘标题’ //设置 title
- document.getElementById(‘box’).style; //获取 CSSStyleDeclaration 对象
- document.getElementById(‘box’).style.color; //获取 style 对象中 color 的值
- document.getElementById(‘box’).style.color=‘red’; //设置 style 对象中 color 的值
- document.getElementById(‘box’).className; //获取 class
- document.getElementById(‘box’).className=‘box’; //设置 class
- alert(document.getElementById(‘box’).bbb); //获取自定义属性的值,不支持
4、getElementsByTagName()方法(标签名)
- getElementsByTagName()方法将返回 一个数组(伪、类数组)HTMLCollection(NodeList),这个数组保存着所有相同元素名的节点列表。
document.getElementsByTagName('li'); //获取所有 li 元素,返回数组
document.getElementsByTagName('li')[0]; //获取第一个 li 元素
document.getElementsByTagName('li').item(0) //获取第一个 li 元素,HTMLLIElement
document.getElementsByTagName('li').length; //获取所有 li 元素的数目
PS:不管是 getElementById 还是 getElementsByTagName,在传递参数的时候,并不是 所有浏览器都必须区分大小写,为了防止不必要的错误和麻烦,我们必须坚持养成区分大小 写的习惯。
5、getElementsByName()方法
- getElementsByName()方法可以获取相同名称(name)的元素,返回一个对象数组 HTMLCollection(NodeList)。
- 一般使用在表单元素里
document.getElementsByName('add') //获取 input 元素
document.getElementsByName('add')[0].value //获取 input 元素的 value 值
- PS:可以获取到具有属性name并name相同的不同元素节点,但是一定要注意该元素节点是否支持name属性。
6、getElementsByClassName()方法
IE8以下该方法无法使用。
7、querySelector
document.querySelector()
- 返回值:一个元素节点,找到符合条件的第一个元素节点。
- 参数:字符串 CSS选择器格式字符串。对于多个选择器,使用逗号隔开,返回一个匹配的元素。
var node = document.querySelector("ol .box");
var node = document.querySelector("[name=hello]");
node.style.backgroundColor = 'red';
document.querySelectorAll()
- 返回值:返回值,是一个伪数组。
- 参数:字符串 CSS选择器格式字符串。
// var nodes = document.querySelectorAll('#ul1');
// var nodes = document.querySelectorAll('ol li');
// var nodes = document.querySelectorAll('ol .box');
var nodes = document.querySelectorAll('ul [name=hello]');
alert(nodes.length);
for(var i = 0; i < nodes.length; i++){
nodes[i].style.backgroundColor = 'red';
}
7.1、获取当前有效样式
- getStyle(elem, “attr”)
- getComputedStyle(elem)[“attr”]
- return elem.currentStyle ? elem.currentStyle[attr] : getComputedStyle(elem)[attr];
这里做了浏览器兼容处理- 查找指定元素指定CSS属性的值
- @param elem 指定的元素
- @param attr 指定的CSS属性
- @return 返回对指定元素查找到的CSS属性值
- 查找指定元素指定CSS属性的值
function getStyle(elem, attr) {
return elem.currentStyle ? elem.currentStyle[attr] : getComputedStyle(elem)[attr];
}
window.onload = function(){
var box = document.getElementById("div_id");
//alert(box.currentStyle["color"]);
alert(getComputedStyle(box)["color"]); //火狐支持 谷歌safari
}
7.2 设置样式
- style.xxx方式设置css样式。
var oBtn = document.getElementById("btn1");
oBtn.onclick = function(){
oDiv.style.backgroundColor = 'orange';
oDiv.style.height = '500px';
7.3 跨浏览器的兼容
function getStyle(node, cssStyle){
return node.currentStyle ? node.currentStyle[cssStyle] : getComputedStyle(node)[cssStyle];
}
8、setAttribute、getAttribute、removeAttribute方法
- getAttribute
- getAttribute()方法将获取元素中某个属性的值。它和直接使用.属性获取属性值的方法有 一定区别。
- document.getElementById(‘box’).getAttribute(‘id’);//获取元素的 id 值
- document.getElementById(‘box’).id; //获取元素的 id 值
- document.getElementById(‘box’).getAttribute(‘mydiv’);//获取元素的自定义属性值
- document.getElementById(‘box’).mydiv; //获取元素的自定义属性值
- document.getElementById(‘box’).getAttribute(‘class’);//获取元素的 class 值
- document.getElementById(‘box’).getAttribute(‘className’);
- 1、class的访问
- 2、支持自定义属性
-
/* alert(oDiv.className); alert(oDiv.getAttribute("class")); */ /* alert(oDiv.xxx); alert(oDiv.getAttribute("xxx")); */ // oDiv.className = 'box4'; /* oDiv.zzz = 'ooo'; alert(oDiv.zzz); */ /* oDiv.setAttribute("class", 'box5'); oDiv.setAttribute("zzz", 'ooo'); */ oDiv.className = ''; oDiv.removeAttribute("title");`
- setAttribute
- setAttribute()方法将设置元素中某个属性和值。它需要接受两个参数:属性名和值。如果属性本身已存在,那么就会被覆盖。
- document.getElementById(‘box’).setAttribute(‘align’,‘center’);//设置属性和值
- document.getElementById(‘box’).setAttribute(‘bbb’,‘ccc’);//设置自定义的属性和值
- removeAttribute
- removeAttribute() 可以移除 HTML 属性。
- document.getElementById(‘box’).removeAttribute(‘style’);//移除属性
9、firstChild和lastChild属性
firstChild 用于获取当前元素节点的第一个子节点,相当于 childNodes[0];
lastChild 用于获取当前元素节点的最后一个子节点,相当于
childNodes[box.childNodes.length- 1]
alert(box.firstChild.nodeValue); //获取第一个子节点的文本内容
alert(box.lastChild.nodeValue); //获取最后一个子节点的文本内容
10、DOM节点(节点属性)
- 节点可以分为元素节点、属性节点和文本节点
- 节点又有三个非常有用的属性, 分别为:nodeName、nodeType 和 nodeValue
document.getElementById(‘box’).nodeType; //1,元素节点
11、childNodes
-
childNodes 访问当前节点下所有的子节点
-
firstChild 访问子节点中的首位
-
lastChild 访问子节点中的最后一位
-
nextSibling 访问当前节点兄弟节点中的下一个节点
-
previousSibling 访问当前节点兄弟节点中的上一个节点
-
【注】上述这些属性都包含文本节点
-
【注】下述这些方法只获取子节点中的元素节点。(IE8以下不兼容)
- children
- firstElementChild
- lastElementChild
- nextElementtSibling
- previousElementSibling
-
nodeType nodeName nodeValue
-
元素节点 1 标签名 null
-
属性节点 2 属性名 属性值
-
文本节点 3 #text 文本内容
childeNodes 属性可以获取某一个元素节点的所有子节点,这些子节点包含元素子节点 和文本子节点。
var box=document.getElementById(‘box'); //获取一个元素节点
alert(box.childNodes.length); //获取这个元素节点的**所有子节点**
alert(box.childNodes[0]); //获取第一个子节点对象
PS:使用 childNodes[n]返回子节点对象的时候,
有可能返回的是元素子节点,比如 HTMLElement;
也有可能返回的是文本子节点,比如 Text。
- 元素子节点可以使用 nodeName 或者 tagName 获取标签名称
- 文本子节点可以使用 nodeValue 获取
for(vari=0;i<box.childNodes.length;i++){
//判断是元素节点,输出元素标签名
if(box.childNodes[i].nodeType===1){
alert('元素节点:'+ box.childNodes[i].nodeName);
//判断是文本节点,输出文本内容
}else if(box.childNodes[i].nodeType===3){
alert('文本节点:'+ box.childNodes[i].nodeValue);
}
}
- 空格、回车、换行 看不见,是字符。
- 【注】获取当前节点的父节点通过parentNode获取。
- 【注】获取当前整个页面的根节点 document
11.1.innerHTML和nodeValue的区别
- innerHTML 获取标签间内容 会解析标签
- innerText 获取标签间纯文本 不会解析标签,设置纯文本
- outerHTML 从外标签开始到外标签结束 会解析标签
PS:在获取到文本节点的时候,是无法使用 innerHTML 这个属性输出文本内容的。这个非标准的属性必须在获取元素节点的时候,才能输出里面包含的文本。
- alert(box.innerHTML); //innerHTML 和 nodeValue 第一个区别
- box.childNodes[0].nodeValue; //innerHTML 和 nodeValue 第一个区别
- PS:innerHTML 和 nodeValue 第一个区别,就是取值的。那么第二个区别就是赋值的时 候,nodeValue 会把包含在文本里的 HTML 转义成特殊字符,从而达到形成单纯文本的效果。
- box.childNodes[0].nodeValue=‘abc’;
//结果为:abc - box.innerHTML=‘abc’;
//结果为:abc 加粗
12、parentNode、previousSibling、nextSibling和ownerDocument属性
- ownerDocument 属性返回该节点的文档对象根节点,返回的对象相当于 document。
- alert(box.ownerDocument=== document); //true,根节点
- parentNode、previousSibling、nextSibling 属性
- parentNode //属性返回该节点的父节点,
- previousSibling //属性返回该节点的前一个同级节点,
- nextSibling //属性返回该节点的后一个同级节点。
- alert(box.parentNode.nodeName); //获取父节点的标签名
- alert(box.lastChild.previousSibling); //获取前一个同级节点
- alert(box.firstChild.nextSibling); //获取后一个同级节点
父子节点:
兄弟节点:
13、一些补充
IE6-8 | IE9-10 Chrome FireFox |
---|---|
firstChild 第一个节点 | firstElementChild 第一个节点 |
lastChild最后一个节点、 | lastElementChild 最后一个节点 |
nextSibling 下一同级节点 | nextElementtSibling 下一同级节点 |
previousSibling 上一同级节点 | previousElementSibling 上一同级节点 |
14、attributes属性(了解)
attributes 属性返回该节点的属性节点集合。
box.attributes //NamedNodeMap
box.attributes.length; //返回属性节点个数
box.attributes[0]; //Attr,返回最后一个属性节点
box.attributes[0].nodeType; //2,节点类型
box.attributes[0].nodeValue; //属性值
box.attributes[‘id’]; //Attr,返回属性为 id 的节点
box.attributes.getNamedItem(‘id’); //Attr
alert(oDiv.attributes.getNamedItem("title").nodeName);
alert(oDiv.attributes.getNamedItem("title").nodeType);
alert(oDiv.attributes.getNamedItem("title").nodeValue);
alert(oDiv.attributes["title"].nodeName);
alert(oDiv.attributes["title"].nodeType);
alert(oDiv.attributes["title"].nodeValue);
15、忽略空白节点
var body= document.getElementsByTagName('body')[0];//获取 body 元素节点
alert(body.childNodes.length); //得到子节点个数,
PS:在非 IE 中,标准的 DOM 具有识别空白文本节点的功能,所以在火狐浏览器是 7 个,而 IE 自动忽略了,如果要保持一致的子元素节点,需要手工忽略掉它。
- 方法1:
function filterSpaceNode(nodes){
var ret=[]; //新数组
for(vari=0;i<nodes.length;i++) {
//如果识别到空白文本节点,就不添加数组
if(nodes[i].nodeType== 3&&/^\s+$/.test(nodes[i].nodeValue))
continue; //把每次的元素节点,添加到数组里 ret.push(nodes[i]);
}
return ret;
}
PS:上面的方法,采用的忽略空白文件节点的方法,把得到元素节点累加到数组里返 回。那么还有一种做法是,直接删除空位文件节点即可
- 方法2:
function filterSpaceNode(nodes){
for(vari=0;i<nodes.length;i++) {
if(nodes[i].nodeType== 3&&/^\s+$/.test(nodes[i].nodeValue)){
//得到空白节点之后,移到父节点上,删除子节点 nodes[i].parentNode.removeChild(nodes[i]);
}
}
return nodes;
}
16、节点操作
DOM 不单单可以查找节点,也可以创建节点、复制节点、插入节点、删除节点和替换 节点。
-
write()
write()方法可以把任意字符串插入到文档中去。
document.write('<p>这是一个段落!</p>')'; //输出任意字符串
-
createElement()方法
createElement() 方法可以创建一个元素节点。 -
document.createElement(‘p’); //创建一个元素节
document.write()【注】会覆盖页面上原有的内容。 -
createElement()
格式:document.createElement()
参数:标签名
返回值:创建好的这个节点 -
appendChild()
格式:node1.appendChild(node2);
功能:将node2节点插入到node1节点子节点的末尾 -
createTextNode()
格式:document.createTextNode(文本);
功能:创建文本节点(纯文本) -
insertBefore()
格式:box1.parentNode.insertBefore(box2, box1);
功能:将box2添加到box1的前面 -
replaceChild()
格式:box1.parentNode.replaceChild(box2, box1);
功能:用box2节点将box1节点替换掉。 -
cloneNode()
格式:node.cloneNode() 克隆节点本身
格式2:node.cloneNode(true); 克隆节点本身和子节点
返回值:克隆出来的新节点 -
removeChild()
格式:box.parentNode.removeChild(box);
功能:将box节点从页面上删除,用父节点调用删除 -
appendChild()
appendChild()方法讲一个新节点添加到某个节点的子节点列表的末尾上。
var box=document.getElementById(‘box’); //获取某一个元素节点
var p=document.createElement('p'); //创建一个新元素节点<p>
box.appendChild(p); //把新元素节点<p>添加子节点末尾
17. this
- this概念:只要封装函数,任何一个函数系统都会内置一个叫做this的变量,
- this变量存储的是地址,是当前函数主人的地址。
【注】this永远指向当前函数的主人。函数的主人要通过当前上下文去判断。
this类似于现实生活中,用到的"我"。
18. offset系列
- 眼睛能看到的实际的宽高
- offsetWidth
- offsetHeight
window.onload = function(){
var oDiv = document.getElementById("div1");
// alert(getStyle(oDiv, "width"));
// alert(oDiv.offsetWidth); //width + border + padding (眼睛能看到的实际的宽)
}
- 眼睛能看到实际距离第一个有定位的父节点的距离。
- offsetLeft
- offsetTop
window.onload = function(){
var oDiv2 = document.getElementById("div2");
// alert(getStyle(oDiv2, "left")); //auto
alert(oDiv2.offsetLeft); //眼睛能看到实际距离第一个有定位的父节点的距离。
}
19.文档碎片问题
- 先创建好10W个节点,将10W节点查入到一个节点上,最后将这1个节点添加到页面上,这样速度快。
/*
创建10W个节点,添加到页面上
*/
window.onload = function(){
console.time("test1");
//test1:120 毫秒 - 倒计时结束
for(var i = 0; i < 100000; i++){
var newDiv = document.createElement("div");
document.body.appendChild(newDiv);
}
console.timeEnd("test1");
/*
先创建好10W个节点,将10W节点查入到一个节点上,最后将这1个节点添加到页面上
*/
//test2:78 毫秒 - 倒计时结束 文档碎片
console.time("test2");
var node = document.createElement("div");
for(var i = 0; i < 100000; i++){
var newDiv = document.createElement("div");
node.appendChild(newDiv);
}
document.body.appendChild(node);
console.timeEnd("test2");
}
20. 遍历
- 数组:
- for循环
- for…in快速遍历
- forEach
var arr = [10, 20, 30, 40, 50];
for(var i = 0; i < arr.length; i++){
document.write("for, " + i + ", " + arr[i] + "<br/>");
}
for(var i in arr){
document.write("forin, " + i + ", " + arr[i] + "<br/>");
}
arr.forEach(function(item, index, arr){
document.write("forEach, " + index + ", " + item + "<br/>");
});
- 对象遍历
//对象遍历
var person = {
username: "钢铁侠",
age: 18,
sex: "男"
};
//对象遍历 for...in
for(var i in person){
// i 是当前遍历到的属性
document.write("对象遍历:" + i + ", " + person[i] + "<br/>");
}
- 延时器
/*
延迟对应毫秒数以后,有且仅执行一次
*/
var timer = setTimeout(function(){
alert("hello world");
}, 4000);
window.onload = function(){
var oBtn = document.getElementById("btn1");
oBtn.onclick = function(){
clearTimeout(timer);
}
}