每天坚持看两章!慢点看,多理解!多练!
Chapter6 图片库改进版
首先要做兼容性检查,如下一点的代码。保证不兼容的老浏览器不会执行。
从可读性来说,不要把多项测试写在同一行上,例如return语句可以单独一行,并用花括号包裹起来。
1
2
3
4
5
6if (!document.getElementsByTagName) {
return false;
}
if (!document.getElementById) {
return false;
}如果想用js给某个网页添加行为,就不应该让js代码对这个网页的结构有任何依赖。
结构化程序设计备忘:
- 函数应该只有一个入口和一个出口。
- 但在实际工作中,过分拘泥于这项原则往往会使代码变得非常难以阅读。为了避免留下多个出口点而去改写那些if语句得化,函数的核心代码就可能会被掩埋在一层又一层的花括号里。
- 所以如果一个函数有多个出口,只要出口集中出现在函数的开头部分,就是可以接受的。
重复敲入比较长的变量名时,如
document.getElementById("imagegallery")
,可以另外给一个名字。选择有意义的单词命名,增加可读性,如
1 | var gallery = document.getElementById("imagegallery")` |
- 用for循环处理数组
1 | 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
19function 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 | window.onload = function(){ |
- 但是如果需要绑定的函数多了,还有另外一个更好的解决办法——addLoadEvent:
1 | function addLoadEvent(func){ |
这将把那些在页面加载完毕时执行的函数创建为一个队列。如:addLoadEvent(firstFunction);
和addLoadEvent(secondFunction);
如果showPic函数处理对象不存在,或者对象的description不存在,我们应该怎么做?
- 如果对象存在,即使description不存在我们也要能正常显示图片。
1
2
3if (!document.getElementById("placeholder")) {
return false;
}
- 如果对象存在,即使description不存在我们也要能正常显示图片。
- 把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.write
和innerHTML
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
8window.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
3var 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
8function 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处于同一个域中的数据,不能向其它域发送请求。