美文网首页
[笔记6]JavaScript DOM编程艺术_最佳实践

[笔记6]JavaScript DOM编程艺术_最佳实践

作者: fumier | 来源:发表于2017-01-19 23:43 被阅读29次

    本章内容

    • 平稳退化 确保网页在没有JS的情况下也能正常工作。
    • 分离JS 把网页的结构和内容与JS脚本的动作行为分开
    • 向后兼容性 确保老版本的浏览器不会因为你的JS脚本而死掉
    • 性能考虑 确定脚本执行的性能最优

    平稳退化

    如果正确地使用了JS脚本,就可以让访问者在他们的浏览器不支持JS的情况下仍能顺利地浏览你的网站,这就是平稳退化

    JS使用window对象的open()方法来创建新的浏览器窗口。这个方法有三个参数:window.open(url,name,features)

    • url新窗口里打开的网页的URL地址
    • 新窗口的名字,可以在代码里通过这个名字与新窗口进行通信。
    • 以逗号分隔的字符串。其内容是新窗口的各种属性。
    function popUp(winURL) {
        window.open(winURL,"popUp","width=320,height=480");
    }
    

    调用popUp函数的一个办法就是使用伪协议。
    真协议用来在因特网上的计算机之间传递数据包,如http协议、ftp协议。伪协议是一种非标准化的协议。“javascript:”伪协议让我们通过一个链接来调用JS函数。

    具体做法:

    <a href="javascript:popUp('http://www.baidu.com/');">Example</a>
    

    这条语句在支持“javascript:”伪协议的浏览器中运行正常,较老的浏览器则会尝试打开链接失败,支持这种伪协议但禁用了JS功能的浏览器会什么也不做。

    总之,在html文档里通过javascript:伪协议调用JavaScript代码的做法非常不好。

    内嵌的事件处理函数

    把onclick事件处理函数作为属性嵌入a标签,改处理函数将在onclick事件发生时调用图片切换函数。

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

    因为在上面这条HTML指令里使用了return false语句,这个链接不会被真的打开。“#”符号是一个仅供文档内部使用的链接符号。把href属性值设置为“#”只是为了创建一个空链接。实际工作全部由onclick属性负责完成。

    但是上面的技巧都不能平稳的退化,如果用户已经禁用了浏览器的JS功能,这样的链接毫无用处。

    具体到popUp()函数,为其中的JS代码预留出退路很简单。在链接里把href属性设置为真实存在的URL地址,让它成为一个有效的链接。

    <a href="http://www.example.com/" onclick="popUp('http://www.example.com';return false;)">Example</a>
    //-------------用this简化一下-------------//
    <a href="http://www.example.com/" onclick="popUp(this.getAttribute('href');return false;)">Example</a>
    //-------------更简单的方式-------------//
    <a href="http://www.example.com/" onclick="popUp(this.href);return false">Example</a>
    

    在本书此前介绍的所有技巧当中,这个技巧最有用,但是它还有改进的余地。最明显的不足时:每当需要打开新窗口时,就不得不把一些JS代码嵌入标记文档中。如果能把事件处理函数在内的所有JS代码全都放在外部文件里,这个技巧将更加完善

    向CSS学习

    CSS是一项了不起的技术。CSS可以让人们对网站设计工作中的各个方面做出严格细致的控制。

    标记良好的内容就是一切

    PS:上面这句话深有感触。

    分离JS

    JS语言不要求事件必须在HTML文档里处理。我们可以在外部JS文件里吧一个事件添加到HTML文档中的某个元素上。element.event=action...
    关键是怎样才能把应该获得这个事件的元素确定下来。这个问题可以利用class或者id来解决。

    如果想把一个事件添加到某个带有特定id属性的元素上,用getElementById就可以解决问题:getElementById(id).event=action。如果事件涉及到多个元素,我们可以用getElmentsByTagName和getAttribute把事件添加到有着特定属性的一组元素上。

    具体步骤:

    • 把文档里的所有链接全放入一个数组里。
    • 遍历数组。
    • 如果某个链接的class属性等于popup,就表示这个链接在被点击时应该调用popUp()函数。

    于是,

    • 把这个链接的href属性值传递给popUp()函数;
    • 取消这个链接的默认行为,不让这个链接把访问者带离当前窗口。
    var links=document.getElementByTagName("a");
    for(var i=0;i<links.length;i++){
    if(links[i].getAttribute("class")=="popup"){
        links[i].onclick=function(){
          popUp(this.getAttribute("href"));
          return false;
         }
    }
    }
    

    如果把上面这段代码存入外部JS文件中,它们将无法正常运行。因为代码的第一行是var links=document.getElementsByTagName("a");这句话将在JS文件被加载时立刻执行。如果JS文件是从HTML文档的< head>部分用<script>标签调用的,它将在HTML文档之前加载到浏览器里。同样,如果标签位于文档底部</body>之前,就不能保证哪个文件最先结束加载(浏览器可能加载多个),因为脚本加载时文档可能不完整,所以模型也不完整,没有完整的DOM,getElementByTagName等方法就不能正常工作。必须让这些代码在HTML文档全部加载到浏览器之后马上开始执行。

    HTML文档加载完毕时将触发一个事件,文档将被加载到一个浏览器窗口里,document对象又是window对象。当window对象触发onload事件时,document对象已经存在

    window.onload=prepareLinks;
    funciton prepareLinks(){
         var links=document.getElementsByTagName("a");
         for(var i=0;i<links.length;i++){
             if(links[i].getAttribute("class")=="popup"){
                links[i].onclick=function(){
                 popUp(this.getAttribute("href"));
                 return false;
                }
             }
          }
    }
    

    向后兼容

    对象检测

    判断浏览器是否对DOM支持,最简单的解决方案是,检测浏览器对JS的支持程度。解决方案:只要把某个方法打包在一个if语句中,就可以根据这条if语句的条件表达式的求值结果是true还是false来决定采取怎样的行动。这种检测称为对象检测。

    例如,如果有一个使用了getElementById()方法的函数,就可以在调用getElementById()方法之前先检查用户所使用的浏览器是否支持这个方法。**在使用对象检测时,一定要删掉方法后面的圆括号,如果不删掉,测试的将是方法的结果。无论方法是否存在。

    function myFunction(){
         if(document.getElementById){
          statements using getElementById
         }
    }
    

    为了避免上面的方法,增加逻辑的深度,可以使用下面的方式。

    if(!getElementById){
       return false;
    }
    //------------如果要检测多个方法或着属性是否存在,可以使用“逻辑或”
    if(!getElementById||!getElementByTagBName){
       return false;
    }
    

    上面的例子增加JS是否支持DOM的语句如下:

    window.onload=prepareLinks;
    function prepareLinks(){
    if (!document.getElementsByTagName) {return false;}
    var links=document.getElementsByTagName("a");
    for (var i = 0; i < links.length; i++) {
        if(links[i].getAttribute("class")=="popup")
        {
            links[i].onclick=function(){
                popUp(this.getAttribute("href"));
                return false;
            }
        }   
    }
    }
    

    浏览器嗅探技术

    浏览器嗅探 指通过提取浏览器供应商提供的信息来解决向后兼容问题。从理论上讲,可以通过JS代码检索关于浏览器品牌和版本的信息,这些信息可以用来改善JS脚本代码的向后兼容性。

    PS:浏览器嗅探技术充满风险,逐渐被对象检测技术所取代。主要是两个原因,一个是浏览器会撒谎,你无法获得准确的版本或者品牌信息。第二是浏览器嗅探器脚本是对版本信息进行精确匹配,版本信息变化太快,脚本所做的修好会比较多。

    性能考虑

    尽量少访问DOM和尽量减少标记

    访问DOM方式对脚本性能会产生非常大的影响。不管什么时候,只要查询DOM中某些元素,浏览器都会搜索整个DOM树,从中查找可能匹配的元素。
    另一个需要注意的地方,就是要尽量减少文档中的标记数量。过多不必要的元素只会增加DOM树的规模,进而增加遍历DOM树以查找特定元素的时间。

    合并和放置脚本

    将多个js文件合并到一个文件中,这样就可以减少加载页面时发送的请求数量。而减少请求数量通常都是在性能优化时首先要考虑的。

    把所有script标签都放到文档的末尾,body标记之前,就可以让页面变得更快。

    压缩脚本

    压缩脚本可以加快加载速度。

    所谓压缩脚本,指的是把脚本文件中不必要的字节,如空格和注释,统统删掉,从而达到压缩文件的目的。精简后的代码虽然不容易看懂,却能大幅减少文件大小。多数情况下,你应该有两个版本。一个是工作副本,可以修改代码并添加注释;另一个是精简副本,用于放在站点上。通常为了将精简版本与非精简版本区分开,最好在精简副本的文件名上加上min字符。

    推荐的几个代表性的代码压缩工具:

    相关文章

      网友评论

          本文标题:[笔记6]JavaScript DOM编程艺术_最佳实践

          本文链接:https://www.haomeiwen.com/subject/nsczmttx.html