• Javascript DOM 编程艺术(第二版)读书笔记——DOM基础


    1.DOM是什么

    D=document(文档)

    O=object(对象)

    M=Model(模型)

    DOM又称节点树

    一些术语:

    parent(父)   child(子)   sibling(兄弟)   node(节点)  

    element node(元素节点)   text node(文本节点)   

    2.获取元素

    1.getElementById(与typeof操作符)

    //getElementById 与 typeof
    //typeof操作符可以告诉我们它的操作数是一个字符串、数值、函数、布尔值还是对象
    //getElementById会返回一个对象,且该调用只能有一个参数(id参数,且必须放在单引号或双引号里)
    alert(typeof  document.getElementById("test")  );

    注意,这里的Element是没有“s”结尾的!后面两个才有!

    按照书上的测试我们只能得出“document.getElementById("test")”的类型是一个对象,但实际上可以更进一步探讨这是个什么对象(是document对象么?): 

    alert( document.getElementById("test-id") );

    输出的结果是object HTMLDivElement,这明显不是document对象,至于这个对象和document有何不同,和DOM有什么关系,以后再说(查文档)。

    同时我也注意到,将这个方法返回的对象赋值给一个变量,该变量的类型将和右值类型相同:

    var test_id = document.getElementById("test-id");
    alert( test_id );
    //输出的结果也是object HTMLDivElement

     另外,我发现文档中称HTMLDivElement为“接口”而不是对象!为什么呢?后面要时刻注意对象、接口是什么东西,参考文章有:123

    2.getElementByTagName

    //getElementsByTagName
    //只接受标签名作为参数
    //返回一个对象数组(数组),每个对象分别对应document对象中的一个tag元素;所以我们可以使用数组对象的属性,比如length alert( document.getElementsByTagName("li").length );

    我得先看看这个返回的是什么:

    alert( document.getElementsByTagName("p") );
    //输出object HTMLCollection

    3.getElementsByClassName

    //getElementsByClassName
    //以空格来同时指定多个类名——由于返回的只有一个特殊的对象,理所当然的,这里返回的是同时具有testClass、testClassTwo类的标签。
    //只接受类名为参数
    alert( document.getElementsByClassName("testClass testClassTwo").length );

    同样的,我得先知道这个方法返回的是什么东西——这里返回的不是真正意义上的“数组”:

    alert( document.getElementsByClassName("test-class") );
    //输出的结果是HTMLCollection,这个对象不是Array(数组)而是一个特殊的对象数组,他也有“.length”这个方法,即返回集合中子元素的数目

    标记一下,为什么不是返回数组而是返回一个新定义的对象数组?肯定有原因。

    这里要注意,这个方法在IE8以下是无法使用的,我们必须借助“getElementsByTagName”来定义这个函数才能在老版本浏览器中使用,具体的方法见这篇文章,有些函数还看不懂,不知道这个实现的原理,以后要回头看懂它。P42

    4.返回的类型是什么,是一个很重要的问题。

      var test_id = document.getElementById("test-id");
      var test_items = test_id.getElementsByTagName("*");
      alert(test_items.length);
      //输出该id下有多少个标签

    这段代码将正确地输出id为“test-id”下有多少个标签,之所以能这样,是因为“getElementById”返回的是一个document的实例,所以第二行可以对“test_id”使用“getElementsByTagName”这个方法;同样地,因为“getElementsByTagName”返回的是一个特殊的对象,这个对象有“length”这个方法,所以我们才能在alert里面正确地输出。

    如果我们把第一行和第二行反过来用,比如“某些标签里面的id=test-id的标签有几个?”,就会出错了(这是个伪命题,直接找id就好了,不需要找“某些标签里面的id”)——首先就是“getElementsByTagName”返回的对象是没有“getElem....”这种方法的,其它的就更不用说了。

    同样地还能这么用:

    var test_id = document.getElementById("test-id");
    var test_items = test_id.getElementsByClassName("test-class");
    alert(test_items.length);
    //输出该id下有多少个“test-class”类的标签

    要意识到,文档中的每一个元素都是一个对象,DOM对这些不同的对象都定义了不同的一整套的方法和属性;

    getElementById返回一个对象,该对象对应文档里一个特定的元素节点。

    getElementsByClassName、getElementsByTagName返回一个对象数组,它们分别对应文档里的一组特定的元素节点——因为你一次只能改一个元素,所以你如果想借这个操作修改这个数组里某个具体元素的值,你就必须加下标!比如getElementsByClassName("p")[1](这里只是强调下标,实际上不一定是这么写的,真正的写法见下面的例子)之类。

    5.childNodes属性

    前面分别是获取某个id的元素、获取某个标签、获取某个类的元素,现在这个是获取任何一个元素的所有子元素:

    3.获取和设置属性

    1.getAttribute(获取)

    //getAttribute
    //为了方便,我只写body里的内容。
        <div id="test-id">
            <p title="oneTitle">hello word1</p>
                <h1 class="test-class">
                    <p>1</p> 
                    <p>2</p> 
                </h1>
            <p title="twoTitle">hello word3</p>
            <p>hello word4</p>
        </div>
        <script>
            var test_items = document.getElementsByTagName("p");
            for(var i = 0 ; i < test_items.length ; i++){
                alert( test_items[i].getAttribute("title") );
            }
        </script> 
    //输出的结果依次为:oneTitle、null、null、twoTitle、null

    学到这,我注意到:DOM分支下之所以有那么多的对象或者说是接口,其实都是为了针对不同抽象层级的操作而诞生的。比如,文档树里的各个节点的层级,我们操作的目标往往是各个节点的属性。因为不需要获取这个节点本身,所以这里的getAttribute不是document对象的一个方法——它只专注于实现属性相关的操作,所以被独立出来,所以我们这里可以看到,要想调用getAttribute,不能通过document对象调用,而是和其“联用”,即先获取到你想更改的标签的数组(第一行代码),然后再调用节点抽象层级的对象的方法getAttribute(第二行script代码——顺带一说,这里的节点抽象层级的对象其实就是指前面提到的HTMLCollection)。

    上面一段的可以简单概括为:getAttribute方法是属于HTMLCollection对象的,而HTMLCollection对象是由document对象中的getElementsByTagName等方法返回的结果。

    其次,要注意到上面这段代码的输出中有“null”,在Javascript里,null的意思是“没有值”。(个别浏览器会在输出null对话框的时候输出空白对话框)

    2.setAttribute(设置)

    //setAttribute
    //为了方便,只给出body内的代码
    <div id="test-id">
            <p title="oneTitle">hello word1</p>
                <h1 class="test-class">
                    <p>1</p> 
                    <p>2</p> 
                </h1>
            <p title="twoTitle">hello word3</p>
            <p>hello word4</p>
        </div>
        <script>
            var test_id = document.getElementById("test-id");
            alert( test_id.getAttribute("title") );
            test_id.setAttribute("title","test-title");
            //测试是否修改了
            alert( test_id.getAttribute("title") );  
    </script>

     setAttribute实际操作是这样的:

    1.当对象属性值为null时(可能有点奇怪,但就是这样:属性没设置就相当于属性不存在,而属性不存在就是属性=null),先创建这个属性,然后设置它的值。

    2.当属性的值存在时,覆盖掉它。

    通过setAttribute对文档做出修改后,浏览器的开发者模式看到的源代码中属性的值并没有改变——其做出的修改不会反映在文档本身的源代码里,是“表里不一”的,这种思想源自DOM的工作模式:先加载文档的静态内容,再动态刷新,动态刷新不影响文档的静态内容。这也是DOM的真正威力:对页面内容进行刷新却不需要在浏览器里刷新页面。——————仔细想想,这是一连串的影响造成的。浏览器解析步骤的开始就是下载HTML文档,生成文档树,然后再渲染CSS、JS,如果JS改了HTML文档,那么浏览器就需要从头开始,也就是整个页面都要重新渲染一次,而这个代价出现的原因居然是修改某个属性值?所以干脆变成“动态刷新”。

  • 相关阅读:
    POJ1811 Prime Test
    HDU3864 D_num
    HDU2138 How many prime numbers
    SPOJ1812 LCS2
    SPOJ1811 LCS
    SPOJ8222 NSUBSTR
    BZOJ4237 稻草人
    洛谷P3601 签到题
    ThreadLocal 线程的私有内存
    netty in action 笔记 二
  • 原文地址:https://www.cnblogs.com/wuduojia/p/8379454.html
Copyright © 2020-2023  润新知