js笔记(DOM暑假12)

例1:不利用children将元素节点找出来
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>frame</title>
</head>
<body>
<div>
    123
    <!--this is -->
    <strong></strong>
    <span></span>
</div>
<script type="text/javascript">
    var div = document.getElementsByTagName('div')[0];
    function retElementChild(node){
        var temp = {
            length : 0,
            push : Array.prototype.push,
            splice : Array.prototype.splice,
        },
            child = node.childNodes;
            len = child.length;
        for(var i = 0;i < len;i++){
            if(child[i].nodeType === 1){
                temp.push(child[i]);
            }
        }
        return temp;
    }
    console.log(retElementChild(div));
</script>
</body>
</html>

4)attributes: Element节点的属性集合(属性节点),属性值value可以改,属性名name不可以改(但是一般不怎么用)
例1:
   <div id = "only" name = "that"></div>
    var div = document.getElementsByTagName('div')[0];
//div.attributes[0]  -->id="only"
//div.attributes[0].value -->"only"
//div.attributes[0].name -->"id"
//div.attributes  -->NamedNodeMap {0: id, 1: name, id: id, name: name, length: 2}
5)节点的一个方法 :Node.hasChildNodes() 判断标签内是不是有节点,有返回true,没有返回false
例1:
<div id = "only" name = "that">
    <!--this is comment-->  
</div>
//例题中有些部分省略了!
//打印div.hasChildNodes();返回true,因为含有注释节点
例2:
<div id = "only" name = "that"></div>
//部分省略
//打印div.hasChildNodes();返回false,因为里面什么都没有。但要是含有空格,那么也算文本节点,就返回flase了
2.节点的类型

元素节点   —— 1
属性节点   —— 2
文本节点   —— 3
注释节点   —— 8
document  —— 9
DocumentFragment  ——  11
  获取节点类型   nodeType 

82.DOM结构树
1.Document可以理解为构造函数,但是是系统留给自己的,咱们不能new它,
2.可以理解为document的构造函数是HTMLDocument然后在往上才是Document
3.DOM结构树就是给出了一系列继承关系
1)getElementById方法定义在Document.prototype上,即Element节点上不能使用。
2)getElementsByName方法定义在HTMLDocument.prototype上,即非html中的document以外不能使用(xml document,Element)
3)getElementsByTagName方法定义在Document.prototype 和 Element.prototype上
例1:
<div>
    <p>123</p>
</div>
<script type="text/javascript">
    var div = document.getElementsByTagName('div')[0];
    var p = div.getElementsByTagName('p')[0];
</script>

//这里的p可以被选中是因为div可以调用getElementsByTagNames。
//因为.getElementsByTagName方法定义在Document.prototype 和 Element.prototype上,而div属于Elements下的HTMLElement下,所以可以用
4)HTMLDocument.prototype定义了一些常用的属性,body,head,分别指代HTML文档中的<body><head>标签。
例1:
    document.getElementsByTagName('body');        <==>    document.body;         同理head也一样
    document.head;
5)Document.prototype上定义了documentElement属性,指代文档的根元素,在HTML文档中,他总是指代<html>元素
例2:
    document.documentElement;      <==>     document.getElementsByTagName('html');
总结:
document.documentElement       <==>html
document.body                             <==> body
document.head                             <==> head
6)getElementsByClassName、querySelectorAll、querySelector在Document,Element类中均有定义
也就是说idv也可以用,因为在Element中也有定义
4.DOM树也就是树形结构,而DOM结构树代表继承关系,代表原型链。
例1:封装函数,返回元素e的第n层祖先元素
<div>
    <p>123</p>
    <span></span>
</div>
<script type="text/javascript">
    var span = document.getElementsByTagName('span')[0  ];
    function retParent(e,n){
        var n = n || 0;            //首先进行容错,万一没传进n就让n = 0
        if(n == 0){
            return e;
        }
        for(var i = 0 ;i < n;i ++){
            e = e.parentNode;
        }
        return e;
    }

</script>

//调用函数retParent(span,4)     返回#document
//调用函数retParent(span,5);    返回null
//调用函数retParent(span,6);    报错,因为null没有原型也不能调用toString方法,所以报错
改错:for循环进行更改,循环条件更改为以下
for(var i = 0 ;e && i < n;i ++)
例2:封装函数,返回元素e的第n个兄弟元素节点,n为正,返回后面的兄弟元素节点,n为负,返回前面的,n为0,返回自己
解法1思路:利用if else判断n的正负,然后利用两个for循环实现寻找前面的兄弟节点还是后面的兄弟节点
解法2思路:利用while,循环条件是n不等于0和n不等于null,然后里面利用if else判断使用next还是previous,最后再n++或者n--就可以了。
不过这里得考虑ie兼容的情况,因为有的ie不能使用nextElementSibling,所以在里面还要再进行判断,判断要是nextElementSibling的话,就直接让e = e.nextElementSibling
如果没有那就是ie浏览器,就要使用nextSibling后,再利用nodeType判断是否是元素节点,不是的话重复直到找到元素节点,赋给e然后n++或者n--,最后返回e。
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>frame</title>
</head>
<body>
<div>
    <p>123</p>
    <span></span>
    <p>abc</p>
    <strong>name</strong>
</div>
<script type="text/javascript">
    var span = document.getElementsByTagName('span')[0];
    function retSibling(e, n) {
        var n = n || 0;
        if (n == 0) {
            return e;
        }
        while (e && n != 0) {
            if (n > 0) {
                if (e.nextElementSibling) {
                    e = e.nextElementSibling;
                }
                else {
                    for (e = e.nextSibling; e && e.nodeType != 1; e = e.nextSibling) {
/*这里e&&e.nodeType !=1 两个条件不能更换位置,因为要是e是null的话先判断e.nodeType!=1的话是报错的*/
                    }
                }
/*注释部分就是等价于for循环判断条件的部分
                e = e.Sibling;
                if (e && e.nodeType != 1) {
                    e = e.nextSibling;
                }
                if (e && e.nodeType != 1) {
                    e = e.nextSibling;
                }*/
                n--;
            }
            else {
                if (e.previousElementSibling) {
                    e = e.previousElementSibling;
                }
                else {
                    for (e = e.previousSibling; e && e.nodeType != 1; e = e.previousSibling) {

                    }
                }
                n++;
            }
        }
        return e;
    }
</script>
</body>
</html>

例3:.编辑函数,封装children功能,解决以前部分浏览器的兼容性问题 
解题思路:在原型上定义一个函数,然后遍历所有子节点,然后判断节点类型,当节点类型 = 1时代表元素节点,然后放进容器中,然后返回。
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>frame</title>
</head>
<body>
<div>
    <p>123</p>
    <span></span>
    <p>abc</p>
    <strong>name</strong>
</div>
<script type="text/javascript">
    var div = document.getElementsByTagName('div')[0];   
/*只要是带s后面就必须带括号[],要是不带,选出的是类数组,类数组不能成组操作*/
    Element.prototype.retChild = function (){
        var child = this.childNodes;
            len = child.length;
        var obj = {
            "length" : 0,
            "push" : Array.prototype.push,
        }
/*        这里有效率优化的问题,为什么在上面定义一个child和len,因为要是直接定义在for循环中,系统不会保存结果,每循环一次就要计算this.childNodes和length,每次都需要算,浪费很多效率,但是将childNodes和length保存到变量里,就会提高效率,不用每次都计算,直接使用就行
        for(var i = 0; i < this.childNodes.length; i ++){ }*/
        for(var i = 0; i < len; i++){
            if(child[i].nodeType == 1){
                obj.push(child[i]);
            }
        }
        return obj;
    }
</script>
</body>
</html>

例4:自己封装hasChildren()方法,不可用children属性,就是判断是否有元素子节点
解题思路:先将方法定义在Element原型上,然后函数里面将子节点类数进行遍历,若有节点类型等于1,那么返回true,没有的话返回false
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>frame</title>
</head>
<body>
<div>
    <p>123</p>
    <span></span>
    <p>abc</p>
    <strong>name</strong>
</div>
<script type="text/javascript">
    Element.prototype.hasChild = function (){
        var child = this.childNodes;
            len = child.length;
        for(var i = 0; i < len; i ++){
            if(child[i].nodeType == 1){
                return true;
            }
        }
        return false;
    }
    var div = document.getElementsByTagName('div')[0];
</script>
</body>
</html>


85.DOM基本操作(接78,查后面)
1.增
创建元素:document.createElement();
创建文本: document.createTextNode();
创建注释document.createComment();
创建文档碎片:document.createDocumentFragment();
例:
    var p =document.createElement('p');
    var text = document.createTextNode('content');
    var comment = document.createComment('this is a comment');
2.插入节点----剪切操作
1)PARENTNODE.appendChild();  
例1:动态的创建一个DOM树
    var p =document.createElement('p');
    var text = document.createTextNode('content');
    var comment = document.createComment('this is a comment');
    //先将创建的节点放进p中,再将p插入到body中
    p.appendChild(text);
    p.appendChild(comment);
    document.body.appendChild(p);
2)PARENTNODE.insertBefore(a, b);      insert a before b
例1:创建p标签,并将p插入到span前。
    var p =document.createElement('p');
    var div = document.getElementsByTagName('div')[0];
    var span = document.getElementsByTagName('span')[0];
    div.insertBefore(p,span);
3.删除:parent.removeChild();(其实是剪切)
例1:看着div中确实没有span了,但是你要是保留出来,在控制台还是可以打印出来的
    var span1 = div.removeChild(span);
例2:利用它可以实现在这个标签里的子标签放入到另一个标签中(利用removeChild和appendChild)
    var div = document.getElementsByTagName('div')[0];
    var div1 = document.getElementsByTagName('div')[1];
    var span = document.getElementsByTagName('span')[0];
    div1.appendChild(div.removeChild(span));
//把第一个div中的span标签放入第二个div中

4)替换 :parent.replaceChild(new, origin);
例1:将div中span标签换成了p标签,并且用span1接受换出来的span标签,所以这个也不是真正意义上的删除(但是之前讲的有一个delete那个是真的删除了)
    var p =document.createElement('p');
    var div = document.getElementsByTagName('div')[0];
    var span = document.getElementsByTagName('span')[0];
    var span1 = div.replaceChild(p,span);
//在DOM中,暂时没有真正意义上的删除,只有剪切

86.DOM基本操作
1.ELement节点(元素节点)的一些属性
1)innerHTML
例1:div.innerHTML可以打印出div中的东西,也可以更改div中的东西,并且覆盖原有的。
利用这个可以直接通过字符串拼接生成一个结构
<div>
<span>1234</span>
</div>
<script type="text/javascript">
    var div = document.getElementsByTagName('div')[0];
    div.innerHTML = "abc";
    div.innerHTML = "<div>123</div>";          //会被正常识别为语法格式作为html的代码
</script>
例2:可以实现添加在html中四个span标签,每个内容依次为0,1,2,3
    var div = document.getElementsByTagName('div')[0];
    for(var i = 0; i < 4; i++){
        div.innerHTML += ("<span>" + i +"</span>");    
/*+=效率是极低极低的,字符串连接也是低效,因为它是栈操作,不是散列,要是使用innerHTML的话不用+=,效率还是可以的,不会太低,最好是不要用+=*/
    }

例3(随便提的):就是给出一系列字符串,要求把这个字符串填到div中
解题思路1:利用数组,将字符串填到数组中,然后利用join将其连接起来成为一个大字符串,然后一起利用innerHTML=.....将它放进去
解题思路2:还是数组,然后用appendChild一个一个放在div中
2)innerText(火狐不兼容) / textContent(老版本IE不好使),其实功能一样的,但是它俩在Chome上都是好使的。
例1:
<div>
    <span>123</span>
</div>
<script type="text/javascript">
    var div = document.getElementsByTagName('div')[0];
</script>
在使用div.innerText = 234,那么div中所有的东西都不见了,只有自己赋进去的值。所以在换内容的时候一定要精准到自己身上,比如span,那就精准到span身上,而不是父元素。
html发展过程中将很多标签语义化了,例如b标签就是加粗的作用,后来的strong标签也是加粗,但是strong标签很语义化,很好理解
所以像那种语义化不好的标签像b标签,i标签等,咱们都将它作为自定义标签了,在它初始化时更改后赋予了新的意义
例2:
<div>
    <span>123</span>
    <b><i>加粗</i></b>
</div>
<script type="text/javascript">
    var div = document.getElementsByTagName('div')[0];
</script>
//控制台打印div.innerText会将div中所有文本都抽出来,不管是子标签还是子孙标签,所以结果就是"123   加粗"
//总结innerText就是取的时候和平取,但是赋的时候全覆盖,和textContent一样的
2.Element节点的一些方法
1)ele.setAttribute();
作用:可以在自己添加的属性上绑定数据
例1:
<div>
    <span>123</span>
    <b><i>加粗</i></b>
</div>
<script type="text/javascript">
    var div = document.getElementsByTagName('div')[0];
    div.setAttribute('id','demo');  /*大致理解就是div设置特性,名是id值是demo,也就证明了可以通过js动态的改变js行间的属性*/
    div.setAttribute('data-log','2');

</script>
//结果就是如下,也就是没有的话就添加,有的话就改变。也可以设置自己定义的属性和值
<div id="demo" data-log="2">
    <span>123</span>
    <b><i>加粗</i></b>
</div>

//还有上面出现的data-log可以用来在网页中代表某个部分,然后看用户点击那个部分次数多,然后将对应的data-log值返回给后台,然后进行优化等
//一般操作的是属性的值,取的也是特定属性名下对应的值,在一个元素上,一个特性只能有一个,再设置会覆盖的,所以返回的是特定的数据,只能有一个。
例2:一个100px红色的正方形区域,实现鼠标一点击就换个颜色
解题思路1(初学者):    demo2.style.backgroundColor = "green"; 
解题思路2:class不一定作为选择元素用,可以代表一种特定的功能,然后设置一个change-color类,设置背景颜色属性为粉色,然后再动态改变class的值为change-color就行了
//所以,以后改变一个元素的样式时,我们以改变它class为优先级最高的选择,以直接改变它自身属性为最后选择
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>frame</title>
    <style type="text/css">
        .demo2{
            height:100px;
            width: 100px;
            background-color: red;
        }
        .change-color{
            background-color: pink;
        }
    </style>
</head>
<body>
<div class="demo2">           //在这里,改变背景颜色通过setAttbute()动态更改class的值,而不是直接更改属性的方法
</div>
<script type="text/javascript">
    /*demo2.style.backgroundColor = "green";*/
</script>
</body>
</html>

猜你喜欢

转载自blog.csdn.net/LFY836126/article/details/82054548