zoukankan      html  css  js  c++  java
  • DOM编程艺术--渐进式学习DOM(上)

    什么是DOM?

    • DOM(Document Object Model),直译为文档对象模型

    D, O, M分别是什么?

    • D - document(文档):DOM的作用就是把你的网页文档转换成一个文档对象。这个过程发生在你创建的网页加载到Web浏览器的时候。
    • O - object(对象):正如同window对象对应浏览器窗口本身,其对象的属性和方法统称为BOM,document对象的主要功能就是处理网页内容。这是DOM最常用的对象。
    • M - model(模型):DOM把一份文档表示为一棵树。这棵树由一个个“节点”组成。它的根节点是html

    有哪些节点?

    • 元素节点:可以理解为HTML中的标签。
    • 文本节点:填充元素节点的文本内容。一般为元素节点的第一个子节点。
    • 属性节点:元素的属性也会作为节点。

    获取这些节点的方法有哪些?

    • getElementById( ):返回与id属性对应的对象(一个)。   //文档中每一个元素都是对象
    • getElementByTagName( ):返回有给定标签的对象数组。可以用通配符*返回文档中的每一个元素。
    • getElementByClassName( ):返回给定class的对象数组。可以指定多个类名(用空格分隔),顺序和数量都不重要。

    => id与TagName和ClassName可以搭配使用。

    如何操作属性节点?

    • getAttribute( ):通过属性名字查询。他不通过document,而是通过元素节点对象调用。没有的属性会返回null值。
    • setAttribute( ):不仅能更新已有的属性值,还能设置新属性。

    => 在修改后查看源代码看到的仍是改变前的属性值,setAttribute做出的修改不会反映在文档本身的源代码里。因为DOM的工作模式是先加载文档的静态内容(源文件),再动态刷新(setAttribute在这里发挥作用)。动态刷新不影响文档的静态内容。这也体现了DOM的威力:对页面内容进行刷新却不需要在浏览器中刷新页面。

    一个JavaScript的图片库案例

    这个图片库实例简单应用了刚刚学到的内容。

    gallary.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <script type="text/javascript" src="./scripts/showPic.js"></script>
        <link rel="stylesheet" href="./styles/layout.css">
        <title>Gallary</title>
    </head>
    <body>
        <h1>This is a gallary.</h1>
        <ul>
            <li>
                <a href="./images/strawberry.jpg" onclick="showPic(this); return false;" title="This is a kind of delicious fruit.">Strawberry</a>
            </li>
            <li>
                <a href="./images/leaf.jpg" onclick="showPic(this); return false;" title="This is a living leaf.">Leaf</a>
            </li>
            <li>
                <a href="./images/sky.jpg" onclick="showPic(this); return false;" title="This is a really beautiful sky.">Sky</a>
            </li>
        </ul>
        <img id="placeholder" src="./images/placeholder.jpg">
        <p id="description">Choose a picture.</p>
    </body>
    </html>

    showPic.js

    function showPic(whichpic){
        var source = whichpic.getAttribute("href");
        var placeholder = document.getElementById("placeholder");
        placeholder.setAttribute("src", source);
        var text = document.getElementById("description");
        var description = whichpic.getAttribute("title");
        text.firstChild.nodeValue = description;
    }

    效果图:

    知识点拓展

    • return false:事件处理函数中,被调用的JavaScript代码可以返回一个值。比如这里的onClick( )函数,他的返回值是布尔类型的,表示“这个链接是否被点击了”。这里的return false表示让链接显示为未被点击(不打开新的窗口)。
    • childNodes属性:获取一个元素的所有子元素(数组)。返回的数组包含所有类型的节点,甚至包括空格和换行符。
    • 想让函数在页面加载时执行,可以使用onload事件处理函数。
    • nodeType属性:判断获得的节点是哪种属性。他的值是一个数字,元素节点(1)/属性节点(2)/文本节点(3)
    • nodeValue属性:表示文本节点的值。注意元素节点的nodeValue属性为null。文本节点可以表示为对应元素节点的第一个子节点。利用这个可以修改文本节点的值。
    • firstChild和lastChild属性:第一个子节点和最后一个子节点。

    基于性能的考虑--DOM的优化方案

    平稳退化

    即在浏览器不支持JavaScript的时候仍能顺利浏览这个网站。

    比如在图片库例子中,我们考虑需要点击链接打开一个窗口的情况,有几种方法可以实现呢?这些方法可以做到平稳退化吗?

    window.open( ) + "javascript:"伪协议

    window.open(url, name, features),三个参数都是可选的,分别是想要打开网页的地址,新窗口的名字,新窗口的各种属性。

    function popUp(winURL){
        window.open(winURL, "popUp", "width=320, height=480");
    }
    //调用popUp函数
    <a href="javascript:popUp('http://www.example.com');">Example</a>

    这样做在支持伪协议的浏览器中正常运行,较老的浏览器会去试图打开链接但失败,支持伪协议但禁用了JS的浏览器什么都不会做。这显然没有做到平稳退化。

    内嵌的事件处理函数

    <a href="#" onclick="popUp('http://www.example.com'); return false;">Example</a>

    这个例子也没达到平稳退化的效果。如果浏览器禁用了JS,这个链接将毫无作用。

    平稳退化的例子

    首先来了解为什么要追求平稳退化:如果你的网站不能平稳退化,他在搜索引擎的排名会大受损害。

    <a href="http://www.example.com" onclick="popUp(this.href; return false)">Example</a>

    当JS被禁用时这个功能依旧可用,只是被打了点折扣。

    渐进增强

    向CSS学习,将JavaScript与HTML用外部文件的方式分离开来。

    在我们的图片库例子中,内嵌的事件处理函数使得HTML代码中出现了JS,我们需要把他们分离开来。

    var link = document.getElementByTagName("a");
    for (var i=0; i<link.length; i++){
        if(link[i].getAttribute("class") == "popup"){
            link[i].onclick = function(){
                popUp(this.getAttribute("href"));
                return false;
            }
        }
    }

    这样只需要给ul增加一个class属性,就可以把列表中所有a元素的事件处理函数绑定了。

    向后兼容

    需要保证浏览器的能力是否到达可以理解每一行代码的能力。

    对象检测

    用if语句去判断。

    if (!document.getElementByTagName)    return false;

    这个语句表示如果不支持getElementByTagName方式,直接返回false。

    浏览器嗅探技术

    通过浏览器供应商提供的信息来解决向后兼容的问题。但这么做风险很大,浏览器有时会撒谎,嗅探脚本会因为需要适应于多种浏览器而复杂,测试时对版本号的精确要求也使得每次出现新版本就要修改。这种方法已经逐渐被对象检测取代。

    性能考虑

    1. 尽量少的访问DOM和减少标记(过多的元素会增大DOM树的规模,增加遍历DOM以查找特定元素的时间)。
    2. 合并和放置脚本,合并到一个脚本文件中,可以减少加载页面发送请求的数量。这也是性能优化中最先要考虑的。
    3. 压缩脚本文件。

    DOM还能做什么?动态创建标记的开始

    前面学到的方法是对已经存在的元素进行修改,接下来我们可以进一步操纵DOM,利用他创建标记。

    创建标记的传统方法

    document.write

    最大的缺点就是违背了“行为与表现分离”的原则。并且容易导致验证错误。

    <script>
        document.write("<p>This is a inserted.</p>");
    </script>

    <script>后面的<p>很容易被误认为是标签,但这是非法的。实际上这个<p>只是字符串的组成部分而已。

    且MIME类型与document.write不兼容。应该尽量避免使用document.write方法。

    innerHtml属性

    可以读取也可以写入。带标签的情况下,读取是以字符串形式显示的(即标签也显示出来),而写入是以HTML标记语言显示的。使用这个属性会将原有的内容完全覆盖。

    这个方式可以让你不用在<body>中插入<script>,即JS代码从标记中分离出来了。但是仍然不兼容MIME类型。

    DOM方法

    使用DOM方法,你并不是在创建标记,而是在改变DOM节点树。

    createElement方法

    可以创建出一个孤儿节点。这种节点被称为“文档碎片”。他有nodeType属性和nodeName属性(即标记的名称)。还需要把他插入到节点树中去。

    *创建了节点之后立刻赋给一个对象是好习惯哟。

    appendChild方法

    经过这一步,你创建的节点就有了家族关系。但他依旧没有内容。

    parent.appendChild(child);

    createTextNode方法

    可以创建一个文本节点。最后你还需要把文本节点作为被创建元素节点的子节点挂上去哟。

    其他的方法扩展

    insertBefore( ):将一个新元素插到一个现有元素前面。两个参数分别是目标元素,父元素。

    不需要搞清楚父元素究竟是哪一个,只需要使用元素的parentNode属性就好了。

    => DOM并没有给我们提供insertAfter函数,但我们可以利用现有的工具写一个。

    function insertAfter(newElement, targetElement){
        var parent = targetElement.parentNode;
        if (parent.lastChild == targetElement){
            parent.appendChild(newElement);
        }else{
            parent.insertBefore(newElement, targetElement.nextSibling);
        }
    }
  • 相关阅读:
    cf C. Vasya and Robot
    zoj 3805 Machine
    cf B. Vasya and Public Transport
    cf D. Queue
    cf C. Find Maximum
    cf B. Two Heaps
    cf C. Jeff and Rounding
    cf B. Jeff and Periods
    cf A. Jeff and Digits
    I Think I Need a Houseboat
  • 原文地址:https://www.cnblogs.com/hermionepeng/p/13255806.html
Copyright © 2011-2022 走看看