Dom编程艺术学习笔记3

每天坚持看两章!慢点看,多理解!多练!

Chapter6 图片库改进版

  • 首先要做兼容性检查,如下一点的代码。保证不兼容的老浏览器不会执行。

  • 从可读性来说,不要把多项测试写在同一行上,例如return语句可以单独一行,并用花括号包裹起来。

    1
    2
    3
    4
    5
    6
    if (!document.getElementsByTagName) {
    return false;
    }
    if (!document.getElementById) {
    return false;
    }
  • 如果想用js给某个网页添加行为,就不应该让js代码对这个网页的结构有任何依赖。

  • 结构化程序设计备忘:

    • 函数应该只有一个入口和一个出口。
    • 但在实际工作中,过分拘泥于这项原则往往会使代码变得非常难以阅读。为了避免留下多个出口点而去改写那些if语句得化,函数的核心代码就可能会被掩埋在一层又一层的花括号里。
    • 所以如果一个函数有多个出口,只要出口集中出现在函数的开头部分,就是可以接受的。
  • 重复敲入比较长的变量名时,如document.getElementById("imagegallery"),可以另外给一个名字。选择有意义的单词命名,增加可读性,如

1
2
var gallery = document.getElementById("imagegallery")`
var links = gallery.getElementsByTagName("a");
  • 用for循环处理数组
1
2
3
for (var i=0; i < links.length; i++) {
//
}
  • 把links数组看成一个节点列表(node list)更准确,这是一个由DOM节点构成的集合。

  • links[i].onclick = function() {}定义了一个匿名函数:一种在代码执行时创建函数的办法。这个匿名函数里的所有语句都将在link[i]元素被点击时执行。

  • 传递给showPic函数的参数——this关键字,代表此时与onclick方法相关联的那个元素。就是说this代表links[i]。

  • 禁用有关链接的默认行为return false(之前重复过好几次了)。

  • 代码清单

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    function prepareGallery(){
    if (!document.getElementsByTagName) {
    return false;
    }
    if (!document.getElementById) {
    return false;
    }
    if (!document.getElementById("imagegallery")) {
    return false;
    }
    var gallery = document.getElementById("imagegallery");
    var links = gallery.getElementsByTagName("a");
    for (var i=0; i < links.length; i++){
    links[i].onclick = function() {
    showPic(this);
    return false;
    }
    }
    }
  • onload事件,如果有多个函数想在页面加载完毕时立即执行,我们可以这样:

1
2
3
4
5
window.onload = function(){
firstFunction();
secondFunction();
//...
}
  • 但是如果需要绑定的函数多了,还有另外一个更好的解决办法——addLoadEvent:
1
2
3
4
5
6
7
8
9
10
11
function addLoadEvent(func){
var oldonload = window.onload;
if (typeof window.onload != 'function') {
window.onload = func;
} else {
window.onload = function() {
oldonload();
func();
}
}
}

这将把那些在页面加载完毕时执行的函数创建为一个队列。如:addLoadEvent(firstFunction);addLoadEvent(secondFunction);

  • 如果showPic函数处理对象不存在,或者对象的description不存在,我们应该怎么做?

    • 如果对象存在,即使description不存在我们也要能正常显示图片。
      1
      2
      3
      if (!document.getElementById("placeholder")) {
      return false;
      }
- 把description改变的语句放到if语句中,将成为可选项,如果存在则更新,否则忽略。
  • 三元操作符:varible = condition ? if true : if false;是if/else语句的一种变体形式,比较简短,但是逻辑关系表达的不明显。

  • getElementById,getElementsByTagName,setAttribute,getAttribute等方法都是DOM Core的组成部分,支持DOM的任何一种语言都可以使用。

  • 了解HTML-DOM,比较精简。

Chapter6总结:

  • 尽量让js代码不在依赖于没有保证的假设,因此需要引入多项测试和检查,从而使js代码能够平稳退化。
  • 不使用onkeypress事件处理函数,使js代码的可访问性得以保证。
  • 把事件处理函数从标记文档分离到外部的js文件,让js代码不再依赖于HTML文档的内容和结构。

Chapter7 动态创建标记

传统方法:document.writeinnerHTML

  • document.write的最大缺点是违背了”行为应该与表现分离”的原则。把结构、行为和样式分开永远都是一个好主意。避免在<body>部分乱用<script>标签,避免使用document.write方法。

  • innerHTML不是W3C标准的组成部分。innerHTML毫无细节可言,想要获得细节,就必须使用DOM方法和属性。

    标准化的DOM就像手术刀一样精细,innerHTML属性则像是一把大锤那样粗放。

  • 需要一大段HTML代码插入网页,innerHTML属性更适用。它既支持读取,又支持写入。但是利用这个技术无法区分”插入一段HTML内容”和”替换一段HTML内容”。

  • innerHTML属性要比document.write()方法更值得推荐。它可以把js代码从标记中分离出来,不过innerHTML属性和document.write()一样属于HTML专有属性,不能用于其它标记文档,不如标准的DOM应用广泛。

DOM方法:createElement,appendChild,createTextNode

  • 从DOM的角度思考问题,一颗文档就是一棵节点树:在节点树上添加内容,就必须插入心得节点;添加一些标记到文档,就必须插入一些元素节点。

  • 创建一个新的元素:document.createElement(nodeName)如创建一个p元素——var para = document.createElement("P"),把新建的一个元素赋给一个变量。这个时候para还只是文档碎片(document fragment),还无法显示在浏览器的窗口里,但是已经具备了自己的DOM属性。如下验证代码:

    1
    2
    3
    4
    5
    6
    7
    8
    window.onload = function() {
    var para = document.createElement("p");
    var info = "nodeName: ";
    info+= para.nodeName;
    info+= " nodeType: ";
    info+= para.nodeType;
    alert(info);
    }
  • 把新节点加入节点树:parent.appendChild(child)

    1
    2
    3
    var para = document.createElement("p");
    var testdiv = document.getElementById("testdiv");
    testdiv.appendChild(para);
  • createTextNode创建文本节点:document.createTextNode(text),如

    1
    2
    3
    //...接上一段
    var txt = document.createTextNode("Hello World");
    para.appendChild(txt);
  • 在已有元素前插入一个新元素:insertBefore()。需要注意三点

    • 新元素:你想插入的元素(newElement).
    • 目标元素:你想把这个新元素插入到哪个元素(targetElement)之前。.
    • 父元素:目标元素的父元素(parentElement).
      调用语法:parentElement.insertBefore(newElement,targetElement)
  • 在DOM里,元素节点的父元素必须是另一个元素节点(属性节点和文本节点的字元素不允许是元素节点)

  • insertAfter()方法模拟:(和addLoadEvent()一样的常用函数)

    1
    2
    3
    4
    5
    6
    7
    8
    function insertAfter(newElement,targetElement) {
    var parent = targetElement.parentNode;
    if (parent.lastChild == targetElement) {
    parent.appendChild(newElement);
    } else {
    parent.insertBefore(newElement,targetElement.nextSibling);
    }
    }

Ajax

异步加载页面内容技术,主要优势:对页面的请求以异步方式发送到服务器。

  • Ajax的核心就是XMLHttpRequest对象,它充当客户端和服务器之间的中间人角色。
  • 在为onreadystatechange指定函数引用时,不要在函数名后面加括号。因为加括号表示立即调用函数。
  • 在使用Ajax时,要注意同源策略。使用XMLHttpRequset对象发送的请求职能访问与其所在的HTML处于同一个域中的数据,不能向其它域发送请求。
坚持原创技术分享,您的支持将鼓励我继续创作!