----------------------------------------------------------------------------------------------第一部分 DOM基本知识

一、定义:

    1、DOM: Document Object Model,是操作html和css的,是一系列对象的集合, 是html和xml的标准编程接口。

    2、document 代表着整个文档,但不是指整个html,确切说是document包含html。

二、增删改查:

 (1)、查询(选择多个元素的返回的是一个类数组)

    i、getElementById('idName');返回仅一个对象。

    P.S. 元素id 在Ie8以下的浏览器,不区分id大小写,而且也返回匹配name属性的元素

   ii、getElementsByTagName('标签名');返回该标签的所有的集合,可看做一个类数组,即使仅有一个,访问时也要用数组访问的方式

    iii、 getElementsByClassName('类名(也可以是用空格分隔的多个类名)');返回满足该类名的所有的集合,可看一个类数组,即使仅有一个,访问时也要用数组访问的方式

  

<div class = 'demo demo1'></div>
var divs = document.gerElementsByClassName('demo demo1');//true

  兼容问题:IE8 及 IE8以下 没有getElementsByClassName('')方法,或者说不兼容

   iv、getElementsByName('标签中属性name的值');返回满足该条件的所有的集合,可看做一个类数组,即使仅有一个,访问时也要用数组访问。

   局限:只有部分元素name生效(表单,表单元素,img,iframe); 

   v、此方法返回的是一个副本,即非实时,1. (a)、即通过其不可影响html和css的内容样式,不实用,但jquery中选择元素用的就是这种方法;(2)、选取的选取这一刻的dom,之后动态添加的也符合选取条件的dom选取不到;   2.在IE7 及IE7一下浏览器没有,不兼容

      通过css选择器的写法来选择dom节点

    a、 document.querySelector('Css选择器写法');返回的是满足条件的一组中的第一个。

    b、document.querySelectorAll('Css选择器写法');返回的满足要求的一组元素。  

   vi、document

    代表整个文档

   

 (2)、创建:

    i、document.createElement()  创建元素节点

    ii、document.createTextNode()  创建一个文本节点

    iii、document.createComment()  创建一个注释节点

    iv、document.createDocumentFragment()  创建一个dom文档碎片

 (3)、插入:

    i、parentNode.appendChild()    在parentNode中插入一个子元素节点,且插入的位置为最后一个子元素(较为常用的方法)

     限制:必须要先能获取到父节点

      初始dom结构为:

  

  <ul>
<li>1</li>
<li>2</li>
</ul>

      创建及插入操作:

  

var oUl = document.getElementsByTagName('ul')[0];
// 创建dom
var oLi = document.createElement('li');
oLi.setAttribute('class', 'insert');
var oText = document.createTextNode('3');
// 插入 文本节点插入oLi下,oLi元素节点插入oLi下
oLi.appendChild(oText);
oUl.appendChild(oLi);

    最终的dom结构:

<ul>
<li>1</li>
<li>2</li>
<!--增加的-->
<li class="insert">3</li>
</ul>

    ii、parentNode.insertBefore(a, b)    在b节点前插入a节点

  这就上demo代码了,上边的理解了,触类旁通,这个也就能理解,大同小异罢了

 (4)、删:

    parent.removeChild()  删除parent节点下的某个子节点,正好同appendChild方法相反

 (5)、替换:

    parent.replaceChild(new, origin)   用new节点来替换parent下的origin字节点

    我们利用上面添加的例子,我们改 oUl.appendChild(oLi); 为 oUl.replaceChild(oLi, oUl.children[0]); 则将oUl下的第一个子元素节点替换为我们创建的dom节点,如下dom结构

  <ul>
<!--替换的-->
<li class="insert">3</li>
<li>2</li>
</ul>

   

三、dom节点:

  (1)、 节点类型:

    元素节点 - 1, 属性节点 - 2, 文本节点 - 3, 注释节点 - 8, document节点 - 9, DocumentFragment节点 - 11

    在控制台,通过  节点名.nodeType 可返回节点类型,通过返回的节点类型判断,我们可以做很多事。

  (2)、 遍历节点的一些属性(任何类型dom节点):

    a.、parentNode  返回父节点

    b.、childNodes  返回子节点们(类数组)

    c、firstChild  第一个子节点

    d、 lastChild 最后一个子节点

    e、nextSibling 后一个兄弟节点

    f、previousSibling 前一个兄弟节点

  一个坑: 请问如下结果?

    

   <ul class="parent">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
</ul> <script>
var oPar = document.getElementsByTagName('ul')[0];
var oChild = oPar.childNodes;
console.log(oChild.length); // 6 or 13
</script>

 

    答案其实是13,为什么呢?因为dom节点有好多种,有元素节点,属性节点,文本节点等等,现在你应该有点明白了,我们来打印oChild来看看

    

console.log(oChilds); // [text, li, text, li, text, li, text, li, text, li, text, li, text]

    所以这就很容易得到解释了,第一个li前的空格和换行作为一个文本节点,第一个li是一个元素节点,后面5个li情况一样, 然后是最后一个li的后面形成一个文本节点,所以一共是6*2 + 1 = 13个dom节点

    下面这道题如果你能得到正确答案,说明你理解了,哈

  

 <ul class="parent"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li> <li>6</li>
</ul>
//同样问ul下有几个dom节点?

    你想的很对,骚年,就是8个dom节点,6个li元素节点 + 第5个li后空格形成一个文本节点 + 最后一个li后换行形成一个文本节点 = 8个dom节点,嘿嘿

 (3)、 遍历元素节点的一些属性(除children慎用)(只针对元素节点)

    a、parentElement 返回父级 元素节点(IE不兼容)

    b、children 返回子级的 元素节点

    c、childElementCount == node.children.length(IE不兼容)

    d、firstElementChild 返回第一个子级 元素节点(IE不兼容)

    e、lastElementChild 返回最后一个子级 元素节点(IE不兼容)

    f、nextElementSibling 返回后一个兄弟 元素节点(IE不兼容)

    g、previousElementSibling 返回前一个兄弟 元素节点(IE不兼容)

    

    看到这你可能会想,好多方法啊,这要怎么记住啊,好痛苦,但细心的你会发现这些方法和上面的方法是如此的相似,所以只要上面的方法都记住了,下面的自然也就能掌握。

    首先这些方法是用来遍历元素节点(过滤了其他类型的节点),你可能想我可以用这些方法来解决上面那该死的问题,但是这些方法有很多IE都不兼容,仅仅children好用一些,

 那怎么办呢?通过JS我们自己封装这些方法让它兼容IE就可以了,而过滤通过nodeType来判断选择就可以。

     

  (4)、 dom节点的一些属性:

    a、nodeName(只读,不可写)(元素的标签以大写形式表示)

    b、nodeValue(可读可写)(仅文本节点 和 注释节点有)

    c、attributes 属性节点类数组集合

    d、nodeType 该节点的类型,只读

   (5)、节点方法:

    hasChildNodes(), 判断是否该节点存在子节点(所有类型的)。

  (6)、DOM结构树:dom元素的继承关系,阐述了dom上一些方法的来源

  类似对象原型的关系,上级是下级的原型,而每一个都为一个构造函数,而上级为其原型。可这样理解

  

  a、Node代表所有节点类型;

  b、 Document理解为继承Node的一个构造函数,而document是Document构造函数的事例对象,继承了Document.prototype上的所有方法。但浏览器是禁止我们使用Doucment来通过new操作符来创建,  但如果我们在Document.prototype上增加属性,我们可以通过document来查看。

  

Document.prototype.abc = 'abc';
console.log(document.abc); // abc

  HTMLDocument,有上边的图,我们不难猜出HTMLDocument是继承自Document的。这样说,Document下有两个,分别为XMLDocument和HTMLDocument,其文件后缀名分别为.xml和.html,则如果是xml文件,则其中的document为XMLDocument的实例对象,若是html文件,则其中的document为HTMLDocument的实例对象。  

   c、CharacterData同Document一样是继承自Node的一个对象,而Text和Comment则继承自CharacterData,然后所有的文本节点则继承自Text,而所有的注释节点则继承自Comment。

     d、Element是继承自Node的对象,而HTMLElement则继承自Element,然后所有的元素节点都继承自HTMLElement

   e、Attr是继承自Node的对象,而所有的属性节点则都继承自Attr

如果理解对象原型链继承机制的话,这些应该很好理解的

    (7)、DOM基本操作的一些注意事项

    i、getElementById方法定义在Document.prototype上,即Element节点上不能使用。

    ii、getElementsByName方法定义在HTMLDocument.prototype上,即除html中的document以外不能使用(xml document,Element)

    iii、getElementsByTagName方法定义在Document.prototype 和 Element.prototype上,则docuemnt和element都可使用

    iv、HTMLDocument.prototype定义了一些常用的属性,body,head,分别指代HTML文档中的<body><head>标签,所以直接用document.body和docuemtn.head即可访问body和head标签

    v、Document.prototype上定义了documentElement属性,指代文档的根元素,在HTML文档中,他总是指代<html>元素

    vi、getElementsByClassName、querySelectorAll、querySelector在Document,Element类中均有定义

       

     (8)、element节点的一些属性:

        i、innerHTML   代表的是该element节点下html内容

        ii、innerText(火狐不兼容) / textContent(老版本IE不好使)   代表的是该element节点下的文本内容

     (9)、Element节点的一些方法

        i、ele.setAttribute()  写element的一些属性

        ii、ele.getAttribute()  读element下的一些属性

小总结:

  1、获取dom节点常用的方法:

    getElementById('idName'); 只能id用

    getElementsByTagName(''); 都能用,无兼容

    getElementsByClassName(''); 都能用, IE8及以下不兼容

  2、document.body  => body

    document.head => head

    document.documentElement => html

四、以上内容的简单实践:

  1、模仿实现chldren方法

    

//重写children
Element.prototype.retChild = function(){
var child = this.childNodes,
len = child.length,
obj = {
'length' : 0,
'push' : Array.prototype.push
}
for(var i = 0; i < len; i++ ) {
if(child[i].nodeType == 1){
obj.push(child[i]);
}
}
return obj;
}

  

Element.prototype.retChildren = function(){
var arrObj = {
length: 0,
push: Array.prototype.push
} for(var node = this.firstChild; node; node = node.nextSibling){
if(node.nodeType == 1){
arrObj.push(node);
}
}
return arrObj;
}

  2、封装函数,返回元素e的第n层祖先元素节点

 Element.prototype.findIndexParent = function (n){
var ret = this.parentNode? this.parentNode : this;
while(--n) {
if(!ret.parentNode) {
return ret;
}
ret = ret.parentNode;
}
return ret;
}

  3、封装函数,返回元素e的第n个兄弟节点,n为正,返回后面的兄弟节点,n为负,返回前面的,n为0,返回自己

 //    封装函数,返回元素e的第n个兄弟节点,n为正,返回后面的兄弟节点,n为负,返回前面的,n为0,返回自己
Element.prototype.retIndexSibling = function (n) {
var ret = this;
// n === 0
if(n === 0) {
return this;
}
// n !=== 0
while(n) {
ret = n > 0? ret.nextSibling : ret.previousSibling;
// 没有n个兄弟元素节点,则返回本身
if(!ret) {
return this;
}
ret.nodeType === 1 && n > 0 && n--;
ret.nodeType === 1 && n < 0 && n++;
}
return ret;
}

  4、请编写一段JavaScript脚本生成下面这段DOM结构。要求:使用标准的DOM方法或属性。提示 dom.className 可以读写class

    <div class="example">
       <p class="slogan">text</p>
    </div>

//    创建div标签 且添加属性
var oDiv = document.createElement('div');
oDiv.className = 'example';
// 创建p标签 且添加属性 填充内容
var oP = document.createElement('p');
oP.className = 'slogan';
oP.innerHTML = 'text';
// 按顺序插入
oDiv.appendChild(oP);
document.body.appendChild(oDiv);

  5、封装函数insertAfter();功能类似insertBefore();提示:可忽略老版本浏览器,直接在Element.prototype上编程

  

    //封装insertAfter()
Element.prototype.insertAfter = function(targetNode, afterNode){
var nextSib = afterNode.nextElementSibling;
      //如果父节点没有子元素或afterNode不存在的容错处理
if(this.children.length <= 1 || !nextSib){
this.appendChild(afterNode);
}else {
this.insertBefore(targetNode, nextSib);
}
}

  6、封装remove(); 使得child.remove()直接可以销毁自身

Element.prototype.remove = function (){
// 像那些属性节点,注释节点,文本节点等等根本不可能做父节点,所以可以说parentNode返回的一般都是父元素节点
var definedParent = this.parentNode;
definedParent.removeChild(this);
}

  7、将目标节点内部的节点顺序逆序。
    eg:<div> <a></a> <em></em></div>

//    将所有子元素逆序
Element.prototype.reverseChildren = function () {
var children = this.children;
var len = children.length;
for(var i = 0; i < len; i++) {
this.insertBefore(children[i], children[len - i - 1]);
this.insertBefore(children[len - i - 1], children[i]);
}
}

  8、parentElement 返回父级 元素节点(IE不兼容),  个人直接用node.parentNode就可以了,感觉除了元素节点外,其他类型节点都不适合做父节点

  9、childElementCount (IE不兼容),  我们直接用node.children.length代替他即可解决不兼容问题

  10、firstElementChild 返回第一个子级 元素节点(IE不兼容),我们用node.children[0]即可

  11、lastElementChild 返回最后一个子级 元素节点(IE不兼容), 我们用直接返回node.dhildren的最后一个元素就可

  12、nextElementSibling 返回后一个兄弟 元素节点(IE不兼容),js封装

  

    //  返回后一个兄弟 元素节点
Element.prototype.nextEleSibling = function () {
// 利用for循环的赋初值, 判断, 调整, 循环 这四种特性
for(var ret = this.nextSibling; ret && ret.nodeType !== 1; ret = ret.nextSibling) {}
return ret;
}

  13、previousElementSibling 返回前一个兄弟 元素节点(IE不兼容), js封装, 原理同上

//  返回前一个兄弟 元素节点
Element.prototype.nextEleSibling = function () {
// 利用for循环的赋初值, 判断, 调整, 循环 这四种特性
for(var ret = this.previousSibling; ret && ret.nodeType !== 1; ret = ret.previousSibling) {}
return ret;
}

    

  

--------------------------------------------------------------------第一部分 end

------------------------------------------------------------------------------------------------------------------------------------第二部分 DOM操作

一、DOM操作:https://www.cnblogs.com/Walker-lyl/p/5250091.html

  

  1、基本操作

  3、css脚本化

  4、事件

  

--------------------------------------------------------------------第二部分 end

-------------------------------------------------------------------第三部分 JS加载

一、异步加载

  时间线

  

-------------------------------------------------------------------第三部分 end

总结: 在我看来DOM的大概可以分为DOM基础知识、DOM操作、JS记载三部分,然后再细分即可,这是在写博客时想出来的,不管对不对,能够让自己记住并理解知识点就可以,等到理解更深再说,学习的快乐莫过于遇到困难后的坚持,直到解决问题,甚至有些自己的独特理解,不能仅仅为了以后找工作而学,而是因为自己的兴趣才学,因为自己想学才培养这方面的兴趣,在我们不能真正理解一个东西时,我们没资格说我们对其没兴趣,因为我们根本就不了解,还谈何是否有兴趣呢。

--------------------------------------------------------------------end

  

    

Js之DOM(一)的更多相关文章

  1. js的DOM对象

    1.js的Array对象           ** 创建数组(三种)                          - var arr1 = [1,2,3];                    ...

  2. python学习笔记十三 JS,Dom(进阶篇)

    JS介绍 JavaScript 是属于网络的脚本语言!JavaScript 被数百万计的网页用来改进设计.验证表单.检测浏览器.创建cookies,以及更多的应用:JavaScript 是因特网上最流 ...

  3. 框架操作DOM和原生js操作DOM比较

    问题引出 对于Angular和React操作DOM的速度,和原生js操作DOM的速度进行了一个比较: 一个同学做的demo 代码如下: <!DOCTYPE html> <html n ...

  4. JavaScript基础15——js的DOM对象

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  5. jQuery对象与JS原生dom对象之间的转换

    jQuery就是JS的一个扩展库,工具库,提供很多方便快捷的方法,所以将JS对象转换为jQuery对象后,能更方便地操作这个对象.但是jQuery对象也不是万能的,有一些JS对象有的能,jQuery对 ...

  6. JS1 js获取dom元素方法

     js获取dom元素方法  1.通过ID选取元素(getElementById) 1)使用方法:document.getElementById("domId")         其 ...

  7. JS的DOM操作及动画

    JS的DOM操作DOM:Document Object ModelBOM:Bowers(浏览器) Object Model找到元素:var a=document.getElementById(&quo ...

  8. js操作DOM对象

    js操作DOM对象  (Document Object Model)文档对象模型 nodeType返回值 1:元素节点 2:属性节点 3:文本节点 8:注释节点 9: 文档节点 nodeName 节点 ...

  9. DOM是什么?有什么用处?js与DOM啥关系?

    本文转载于:https://blog.csdn.net/u012155729/article/details/78135393 转载仅供自己后期学习 DOM简介大家都想知道dom是什么,翻了各种文档, ...

  10. 继续JS之DOM对象二

    前面在JS之DOM中我们知道了属性操作,下面我们来了解一下节点操作.很重要!! 一.节点操作 创建节点:var ele_a = document.createElement('a');添加节点:ele ...

随机推荐

  1. 戏说PHP的嵌套函数

    PHP很早就支持嵌套函数了.并是不PHP5.3有闭包时才有的.然而,它却不是象JS,AS那样的闭包嵌套.即它的嵌套函数根本无闭包模式的逃脱. PHP嵌套函数有一些特别之处.最特别的是,当外部函数被调用 ...

  2. How to Notify Command to evaluate in mvvmlight

    How to Raize Command to evalituate in mvvm In mvvmlight, we bind our control to the relaycommand obj ...

  3. Python实现nb(朴素贝叶斯)

    Python实现nb(朴素贝叶斯) 运行环境 Pyhton3 numpy科学计算模块 计算过程 st=>start: 开始 op1=>operation: 读入数据 op2=>ope ...

  4. ios 唯一标示符

    大家知道苹果每部 iOS 设备都有一个 UDID,它就像设备的身份证一样,记录着设备的名称.类型甚至一些关于用户的私人信息.通常情况下,UDID 的一个最大功能就是帮助广告发布商向特定用户推送定向广告 ...

  5. [shell基础]——awk命令

    关于awk awk是一个强大的文本分析工具,相对于grep的查找.sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大. 简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开 ...

  6. vim替换及多行注释命令

    1.多行注释: . 进入命令行模式,按ctrl + v进入 visual block模式,然后按j, 或者k选中多行,把需要注释的行标记起来 . 按大写字母I,再插入注释符,例如// . 按esc键就 ...

  7. zookeeper数据迁移

    在不停机的情况下,实现集群之间数据迁移代码: private void create(ZooKeeper zk1, ZooKeeper zk2, String path) throws Excepti ...

  8. Daily Scrum2

    今天我们小组开会内容分为以下部分: part 1: 之前的失败教训: part 2: 针对Anti-spam and anti-abuse module模块的任务分工: part 3: 之后小组成员必 ...

  9. Tomcat配置HTTPS方式生成安全证书

    在Tomcat 6中配置SSL双向认证是相当容易的,本文将介绍如何使用JDK的keytool来为Tomcat配置双向SSL认证.并实现批量生成证书 系统需求:JDK 5.0Tomcat 6.0.16启 ...

  10. Beta版软件说明书

    软件使用说明书 一.    软件概述 本软件面向广大简易图片使用者,旨在为用户提供简单方便的不对其他软件产生依赖的截图软件,可以脱机使用. 二.    运行环境 个人电脑,Windows7操作系统,. ...