zoukankan      html  css  js  c++  java
  • 读书笔记:JavaScript DOM 编程艺术(第二版)

    读完还是能学到很多的基础知识,这里记录下,方便回顾与及时查阅。

    内容也有自己的一些补充。

    JavaScript DOM 编程艺术(第二版)

    1、JavaScript简史

    JavaScript由Netscape公司与Sun公司合作开发,在JavaScript之前,web浏览器只是显示文本文档的软件,JavaScript之后,网页内容不再局限于枯燥的文本,交互性显著改善。在JavaScript的第一个版本,即JavaScript 1.0版本,出现在1995年推出的Netscape Navigator 2浏览器中。

    在JavaScript 1.0发布时,浏览器市场主要是Netscape Navigator,后来IE开始追赶,微软在IE3时发布了自己的VBScript语言,同时以JScript为名发布了JavaScript的第一个版本,并很快追上了Netscape的步伐。面对微软的竞争,Netscape与Sun公司联合ECMA(欧洲计算机制造商协会)对JavaScript语言进行了标准化,于是出现了ECMAScript语言,这是同一种语言的另一个名字。

    到了1996年,JavaScript、ECMAScript、JScript--随便怎么称呼,已经站稳了脚本,Netscape与微软的第三版浏览器都不同程度的支持JavaScript 1.1语言。

    在JavaScript早期版本向程序员提供了查询和操控Web文档某些内容的手段,比如:

    document.images[2]
    dodument.forms['details']
    

    现在人们通常把这种试验性质的初级DOM称为“第0级DOM”(DOM level 0),在还未形成统一标准的初级阶段,“第0级DOM”的常见用途是翻转图片和验证表单数据。

    在1997年6月,Netscape Navigator 4发布,10月,IE4发布。这两个早起版本都对他们的浏览器进行了改进,大幅扩展了DOM,同时也接触到一个新名词:DHTML。

    不幸的是,NN4和IE4浏览器使用了两种不兼容的DOM。程序员要写两套代码。

    NN4中DOM元素为层,层有唯一的ID:

    document.layers['myElement']
    

    而微软的DOM需要这样引用:

    document.all['myElement']
    

    就在DOM产生分歧,浏览器厂商大战时,W3C推出了一个标准化的DOM,令人欣慰的事,Netscape与微软以及其他浏览器制造商都接受了新的标准,并于1998年10月完成了“第1级DOM”(DOM Level 1)。

    二、JavaScript语法

    三、DOM

    DOM:Document Object Model 文档对象模型

    JavaScript中的对象分为三种:

    1、用户定义对象:由程序员创建的对象
    2、內建对象:内建在JavaScript语言中的对象,如Array、Math和Date等
    3、宿主对象:由宿主环境(浏览器)提供的对象,如window、document

    window对象对应着浏览器窗口本身,这个对象的属性和方法通常称为BOM(浏览器文档模型)。

    3.4 节点

    先看三种:元素节点、文本节点、属性节点

    <p class="info">my name is Gavin</p>
    

    标签的名字就是元素的名字,这里面有一个元素节点p,一个文本节点“my name is Gavin”,以及一个属性节点class="info"。

    属性节点总是被包含在元素节点中,并不是所有的元素节点都有属性节点,在所有的属性都被元素包含。

    3.5 获取元素

    • getElementById()
    • getElementsByTagName()
    • getElementsByClassName() -- HTML5 DOM

    其中getElementById()返回一个对象,getElementsByTagName()与getElementsByClassName()返回一个对象数组。

    每个节点都是一个对象。

    3.6 获取和设置属性

    • object.getAttribute( attribute )
    • object.setAttribute( attribute, value )

    四、案例研究:JavaScript图片库

    setAttribute方法是“第一级DOM”(DOM level 1)的组成部分,可以设置任意元素的节点的任意属性。在“第一级DOM”出现之前,还可以用另外一个方法设置大部分元素的属性,这个方法到现在仍然有效。

    img.src = 'xxx'
    
    // 等价
    img.setAttribute( 'src', 'xxx' );
    

    使用“第一级DOM”的优势是:

    • 不用特别记忆哪些属性可以用DOM之前的方法设置
    • 可移植性好,DOM用于任何一种标记语言,通用API。

    4.4.1 childNodes

    node.childNodes 获取任何一个元素的所有子元素

    4.4.2 nodeType属性

    nodeTyoe总共有12种可取值,但其中仅有3个具有实用价值。

    • 元素节点的nodeType属性值是1
    • 属性节点的nodeType属性值是2
    • 文本节点的nodeType属性值是3

    4.4.5 nodeValue属性

    如果要改变一个文本节点的值,那就实用DOM提供的nodeValue属性,它用来得到(和设置)一个节点的值。

    element.nodeValue
    

    注意,文本节点可能是其他节点的子节点,在获取时尤其注意:

    <p>my name is Gavin.</p>
    
    <script>
    var oP = document.getElementsByTagName('p');
    oP[0].nodeValue; // null
    op[0].childNodes[0].nodeValue; // my name is Gavin.
    </script>
    

    4.4.6 firstChild 和 lastChild

    node.childNodes[0] === node.firstChild
    node.childNodes[ node.childNodes.length - 1 ] === node.lastChild
    

    补充:nextSibling、previousSibling:兄弟节点

    五、最佳实践

    • 平稳退化
    • javascript:伪协议
    • 结构与样式分离
    • 渐进增强
    • 分离JavaScript
    • 向后兼容
      • 对象检测

          if ( !xxx ) return false;
        
      • 浏览器嗅探

    • 性能考虑
      • 尽量少访问DOM和尽量减少标记
        • 文档标记少,则DOM树规模少,遍历查找更快速
      • 合并和放置脚本:脚本放到body最后,可以让页面更快
      • 压缩脚本

    "真"协议用来在因特网上的计算机之间传输数据包,如HTTP协议(http://)、FTP协议(ftp://)等,伪协议是一个非标准化的协议,javascript:伪协议可以让我们通过一个链接来调用JavaScript函数。

    通过伪协议来调用JavaScript函数的做法非常不好,不是最佳实践。

    六、案例研究:图片库改进版

    6.6 键盘访问

    对于视力残疾的用户往往看不清屏幕上的鼠标指针,他们往往更喜欢使用键盘。众所周知,不使用鼠标也可以浏览web。键盘上的tab键可以让我们从这个链接移动到另一个链接,然后按下回车键启用当前链接。

    在键盘事件中有一个onkeypress事件,按下键盘的任何一个键都会触发onkeypress事件,但这个键很容易出现问题,因为即使按下tab键也会触发该事件!

    onclick事件更聪明,用tab键移到链接上,按下回车键,链接也能访问。

    6.8 DOM Core 和 HTML - DOM

    • getElementById
    • getElementsByTagName
    • getAttribute
    • setAttribute

    这些都是DOM Core的组成部分,他们并不专属于JavaScript,任何支持DOM的程序设计语言都可以使用它们。

    而对于

    • element.onclick
    • element.forms
    • element.src

    这些属性属于HTML DOM,在DOM Core出现很久之前就已经为人们所熟悉了。

    大多数情况下,同样的操作即可以使用DOM Core实现也可以用HTML DOM实现。HTML DOM通过更加简短,只能用来处理HTML文档。

    七、动态创建标记

    7.1 一些传统方法

    • document.write()
    • innderHTML

    MIME类型application/xhtml+xml与document.write()不兼容,浏览器呈现这种XHTML文档时不会执行document.write()方法。

    另外,document.write()最大的问题是不能进行结构与行为分离。

    备注:关于document.write()主要有两种使用方式:

    第一种:当页面加载完成后,浏览器输出流自动关闭,此时进行document.write()方法将打开一个新的输出流,它将清除当前页面内容。

    第二种:调用document.write()方法在窗口中打开窗口,框架中产生新文档,这种方式必须用document.close()关闭,并且继续使用document.write()写入的内容不会清除文档,而是继续追加。

    element.innerHTML 方法可以读写元素的内容。几乎所有的浏览器都支持innerHTML,但这个属性不是W3C DOM的标准属性,现在已经在HTML5规范中,始于IE4浏览器。

    和document.write()类似,innerHTML也是HTML专有属性,不能用于其他标记语言文档,在MIME类型为application/xhtml+xml的XHMLT文档中,该属性会被忽略。

    7.2 DOM 方法

    • createElement( nodeName ) -- 创建元素节点
    • createTextNode( text ) -- 创建文本节点
    • appendChild( child ) -- 把创建的节点插入到文档节点树中

    通过createElement与createTextNode只是创建文档碎片,只有执行appendChild才会插入到文档中。

    appendChild除了可以把文档碎片插入到文档树中,还可以连接文档碎片。

    比如:

    var p = document.createElement('p');
    var text = document.createTextNode('my name is Gavin.');
    p.appendChild( text );
    document.body.appendChild( p );
    
    • insertBefore -- 在现有元素前插入元素

        parentElement.insertBefore( newElement, targetElement );
      

    没有insertAfter方法,可以结合insertBefore来实现

    function insertAfter ( newElement, targetElement ) {
    	var parent = targetElement.parentNode;
    	if ( parent.lastChild == targetElement ) {
    		parent.appendChild( newElement );
    	} else {
    		parent.insertBefore( newElement, targetElement.nextSiblings );
    	}
    } 
    

    7.4 ajax

    ajax的技术核心是XMLHttpRequest。在微软较早的IE5中以ActiveX对象的形式实现了一个名叫XMLHTTP的对象,在较早IE中,创建对象的方式为:

    var request = new ActiveXObject("Msxml2.XMLHTTP.3.0");
    

    在其他浏览器上的创建方式为:

    var request = new XMLHttpRequest();
    

    更烦的是,不同IE版本中使用的XMLHTTP对象不完全相同,为了兼容所有浏览器,需要这样写:

    function getHttpObject() {
    	if ( typeof XMLHttpRequest == 'undefined ) {
    		XMLHttpRequest = function () {
    			try {
    				return new ActiveXObject("Msxml2.XMLHTTP.6.0");
    			} cache ( e ) {}
    			
    			try {
    				return  new ActiveXObject("Msxml2.XMLHTTP.3.0");
    			} cache ( e ) {}
    			
    			try {
    				return  new ActiveXObject("Msxml2.XMLHTTP");
    			} cache ( e ) {}		
    		}
    	}
    	return new XMLHttpRequest();
    }
    

    XMLHttpRequest对象由许多方法,最有用的是open方法,该方法有三个参数,第一个是请求类型:GETPOSTSEND,第二个是请求地址,第三个表示是否异步请求。

    request.open( 'GET', 'xxx.json', true );
    request.onreadystatechange = function () {}
    request.send();
    

    onreadystatechange事件XMLHttpRequest返回响应时触发。

    返回响应时,浏览器会在不同阶段更新readyState的值,它有5个可能值:

    • 0 表示未初始化
    • 1 表示正在加载
    • 2 表示加载完毕
    • 3 表示正在交互
    • 4 表示完成

    如果readyState属性值变成了4,则说明服务器已经发回了数据。

    访问服务器发送回来的数据需要通过两个属性,一个是responseText,这个用于保存文本字符串形式的数据,另一个是responseXML属性,用于保存Content-Type头部中指定为“text/xml”的数据,这其实是一个DocumentFragment对象。你可以使用各种方法来操作这个DOM对象,这也是XMLHttpRequest中有XML的原因。

    八、充实文档的内容

    渐进增强则必然支持平稳退化

    8.3.1 选用HTML、XHTML还是HTML5

    不管使用哪一种标记,必须要与DOCTYPE声明保持一致。

    XHMLT比HTML的规则更严格。比如在写属性时,HTML允许使用大写字母,也可以使用小写字母,XHTML却要求所有的标签名和属性名都必须使用小写字母。

    备注:关于HTML、XHTML、HTML5的区别,可以看这篇文档:

    HTML4,HTML5,XHTML 之间有什么区别?

    在HTML早起,W3C成立之前,基本没有标准,标准都在在实现中定义的。一直从HTML2.0到4.0、4.01,这种情况下,HTML标准不是很规范,浏览器也对HTML页面的错误相当宽容。导致HTML作者也出了很多错误的HTML页面。

    后来W3C意识到这个问题,开始制定标准,为了规范HTML,W3C结合XML制定了XHTML1.0标准,按照XML的要求规范HTML,并定义了一个新MIME Type:application/xhtml+xml,W3C的初衷是对这个MIME TYPE的浏览器实行强制错误检查,如果页面有错误,就要显示错误。很多开发者拒绝使用这个MIME TYPE,W3C不得已,在XHTML1.0后附加了一个附录C。允许开发者使用XHTML来写页面,同时使用原来的MIME TYPE:application/html。这个MIME TYPE不会触发浏览器的强制错误检查。

    W3C随后在XHTML1.1中取消了附录C,即使用XHTML1.1标准的页面必须使用新的MIME TYPE。但并没有多少人使用。

    有了XHTML的教训,WHATWG和W3C在制定下一代HTML标准,也就是HTML5的时候,就将向后兼容作为一个很重要的原则。HTML5加入了很多特性,但最重要的特性是,不会break已有的网页。你可以将网页的第一行改为<!DOCTYPE html>,他就成了一个HTML5页面,可以照常在浏览器中显示。

    <!DOCTYPE html>总共才15个字符,这个声明同时也支持HTML与XHTML标记。

    某些浏览器要根据DOCTYPE来决定使用标准模式,还是兼容模式来呈现页面,兼容模式意味着浏览器要模仿早起浏览器的“怪异行为”,并允许不规范的页面也能正常工作。一般来说,我们都应该坚持使用标准模式,避免触发兼容模式,HTML5的DOCTYPE默认就是标准模式。

    此外还有XHTML5,即用XML的规则来编写HTML5。

    九、CSS-DOM

    9.2 Style属性

    文档中的每个元素都是一个对象,每个对象都有各种各样的属性,比如:parentNode、childNodes、firstChild、lastChild、nextSibling、previousSibling等,表示节点的关心信息。

    还有一些属性:nodeName、nodeValue、nodeType,表示节点的类型信息。

    除此之外,还有一个style属性,表示节点的样式信息。

    9.2.1 获取样式

    element.style.color
    

    对于font-family,在获取的时候会出错,原因为:JavaScript中连字符-为减法运算,所以会理解为获取font属性,然后对family做减法运算,而family此时为变量,但我们并没有声明这个变量,继而引发错误。

    // 错误写法!!
    element.style.font-family;
    

    当引用一个中间带减号的CSS属性时,DOM要求使用驼峰命名法:

    // 正确写法
    element.style.fontFamily;
    

    不管有多有连字符,一律采用驼峰写法:比如magrin-top-width,写为:marginTopWidth。

    style属性只能返回内联样式。

    9.2.2 设置样式

    element.style.property = value;
    

    9.3 用DOM解耦本设置样式

    :first-child,:last-child选择器是CSS2中的
    :nth-child()和:nth-of-type()是CSS3中的

    在使用CSS时,不要人云亦云的认为表格都是不好的,虽然用表格布局不是好主意,但利用表格来显示数据却是理所当然的。

    9.4 className 属性

    // 读
    element.className
    
    // 写
    element.className = value
    

    className在设置的时候是替换(而不是追加)。可以利用字符串拼接,达到追加的效果

    element.clssName += ' info';
    

    十、用JavaScript实现动画效果

    十一、HTML5

    HTML5是HTML语言当前及未来的新标准,HTML规范从HTML4到XHTML,再到Web Apps1.0,最后又回到HTML5,整个过程充满了艰辛与争议。

    在结构层,HTML5添加了很多新的标记元素,如<section><article><header><footer>等。

    HTML5还提供了更多的交互即媒体元素,如<canvas><audio><video>

    表单也进行了增强,新增了颜色选择器数据选择器滑动条进度条等。

    还有很多新的JavaScript API,比如:GeolocationStorageDrag-and-DropSocket以及多线程等。

    另外,通过新的MIME TYPE,HTML5保持了向后兼容,就算写代码很不规范,也没问题。

    参考链接:

    十二、综合示例

    附录 JavaScript库

    所谓库,就是可重用的代码包,具有如下的一些优点:

    • 库代码经过了大量的用户的测试和验证
    • 库能够很容易的与已有的开发框架集成
    • 可为大多数日常琐碎的DOM变成工作提供了方便,简洁的方案,每个函数都能节省很多行代码
    • 库很好的解决了跨浏览器的问题,让你更省心

    库也存在问题:

    • 库是别人写的,不是自己编写的,不了解内部机制,很难调试bug或由它导致的问题
    • 要使用库,就要把它集中到脚本中,增加页面加载负担
    • 混合使用多个库可能会造成冲突,同时也会造成功能浪费

    A1:选择合适的库

    在选择时,建议考虑如下问题:

    • 它具有你需要的所有功能吗?
    • 它的功能是否比你想要的还多?
    • 它是模块化的吗?
    • 它的支持情况怎么样?
    • 它有文档吗?
    • 它的许可合适吗?

    A1.2 内容分发网络

    一定要尽可能想办法减少网页文档的大小,并让浏览器缓存文件。除此之外,当然还要让用户尽可能的加载到页面。

    内容分发网络(CDN,Content Delevery Network)可以解决分布共享库的问题。CDN是一个由服务器构成的网络,这个网络的用户就是分散存储一些公共的内容。CND的每台服务器都包含库的一份副本,这些服务器分布在世界上不同的国家和地区,以便达到和利用带宽和加快下载的目的。

    浏览器访问库的时候使用一个公共的URL,而CDN的地层则通过地理位置最近、速度最快的服务器提供相应的文件,从而解决了整个系统中的瓶颈问题。

    这些文件是共享的,当用户从一个站点跳到另一个站点,他们就不用再重复的下载相同的文件了。

  • 相关阅读:
    成都Uber优步司机快速注册攻略(外地车牌也可加入,不用现场培训)
    uber司机 如何提高评分、接单率、成单率?
    uber奖励和账单详解
    优步uber司机常见问题与答案(成都地区官方)
    成都优步uber司机第四组奖励政策
    疯狂的补贴,广州司机都被Uber触动
    scheme 宏macro写法
    scheme 模拟queue
    scheme I/0 输入输出操作
    scheme递归
  • 原文地址:https://www.cnblogs.com/yangyoucun/p/6218404.html
Copyright © 2011-2022 走看看