读《编写可维护的JavaScript》第五章总结

第五章 UI层的松耦合

5.1 什么是松耦合

在Web开发中,用户界面是由三个彼此隔离又相互作用的层定义的:

  • HTML是用来定义页面的数据和语义
  • CSS用来给页面添加样式
  • JavaScript用来给页面添加行为

我们的目标:确保对一个组件的修改不会经常性地影响其他部分。

结果:

  1.    遇到和文本或结构相关的问题,通过查找HTML即可定位
  2.    当发生了样式相关的问题,你知道问题出现在CSS中
  3.    对于那些行为相关的问题,你直接去JavaScript中找到问题所在

5.2 将JavaScript从CSS中抽离

IE8和更早版本的浏览器有一个特性:CSS表达式(CSS expression)。(读者本人看了此书才知道- -)

它的特点是:允许你将JavaScript直接插入到CSS中。然而历史中毕竟是有糟粕的。

一句话:杜绝使用

5.3 将CSS从JavaScript中抽离

这个读者本人就经常见了。。一些只是把JS当做脚本语言的后端人员会经常性的这样写。

        // 不好的写法
        element.style.color = "red";
        element.style.left = "10px";
        element.style.top = "100px";
        element.style.visibility = "visibility";

然而最佳操作的方法是 操作CSS的className

        // 好的写法 - 原生方法
        element.className +=" reveal";
        
        // 好的写法 - HTML5
        element.classList.add("reveal");
        
        // 好的写法 - YUI
        Y.one(element).addClass("reveal");
        
        // 好的写法 - jQuery
        $(element).addClass("reveal");
        
        // 好的写法 - Dojo
        dojo.addClass(element, "reveal");

 理由:由于CSS的className可以成为css和JavaScript之间通信的桥梁,在页面的生命周期中,JS可以随意添加和删除元素的className而不必直接操作样式,以便保持和CSS的松耦合。

5.4 将JavaScript从html抽离

 这个部分也是老生常谈了。。估计很少有人现在这样写了吧。。

<button onclick="doSomething()" id="action-btn">Click me</button>

 

作者推荐的,也是众多书中有的写法:

        function doSomething() {
            // 代码
         }
        var btn = document.getElementById("action-btn");
        btn.addListener(btn, "click", doSomething);

 

IE8以及早期版本浏览器不支持addEventListener()函数,因此你需要一个标准的函数将这些差异性做封装。

       function addListener(target, type, handler) {
            if (target.addEventListener) {
                target.addEventListener(type, handler, false);
            } else if (target.attachEvent) {
                target.attachEvent("on" + type, handler);
            } else {
                target["on" + type] = handler;
            }
        }

 如果你用了JavaScript类库,可以使用类库提供的方法来给元素挂载事件处理程序。这里给出了一些流行的类库的示例代码。

        // YUI
        Y.one("#action-btn").on("click", doSomething);

        // jQuery
        $("#action-btn").on("click", doSomething);

        // Dojo
        var btn = dojo.byId("action-btn");
        dojo.connect(btn, "click", doSomething);

 ②  另外,作者本人也不推荐使用<script>标签方式包含JavaScript代码(不过在紧急调试时这仍然是一种好办法,正式环境当然隔离好了!)

5.5 将HTML从JavaScript中抽离

作者将重头戏放到了最后,我在做上一个项目的时候,采取的拼html方式。这种方式不用说,很low。类似于以下这种的:

 

你会发现需要转义,HTML和JS混在一起,如果要修改的话需要修改多处,所以,作者推荐了三种方式将HTML从JavaScript中抽离:

5.5.1 方法1 :从服务器加载

这种方法是将模板置于远程服务器,然后用Ajax技术去取,方法类似于下面的:

// YUI
function loadDialog(name, oncomplete) {
    Y.one("#dlg-holder").load("js/dialog" + name, oncomplete);
}

// jQuery
function loadDialog(name, oncomplete) {
    $.one("#dlg-holder").load("js/dialog" + name, oncomplete);
} 

 

当你需要注入大段不经常改变的HTML代码到页面中时,这种方式是非常有帮助的。对于少量的标签段,你可以考虑采用客户端模板。

PS: 本人感觉这种方法也low- -因为作者本人后面加了一句:出于性能原因,将大量没用的标签放入内存或DOM中是很糟糕的做法。这也就直接说明了这种方式并不适合动态模板。

5.5.2 方法二:简单客户端模板

客户端模板是一些带“插槽”的标签片段,这些插槽会被JavaScript程序替换为数据以保证模板的完整可用。

// 这段模板包含%s占位符,这个位置的文本会被程序替换掉
<
li><a href="%s">%s</a></li>

 

本质上讲,我们不希望在JavaScript中嵌入模板文本,那放哪呢?作者提供了俩种方法。

  • 在HTML注释中包含模板文本。
        <ul id="mylist">
            <%--<li><a href="%s">%s</a></li>--%>
        </ul>
  • 或者是带自定义type属性的<script>元素,浏览器会默认将<script>元素的内容识别为JavaScript代码,但你可以通过给type赋值为浏览器不识别的类型,从而来告诉浏览器这不是一段JavaScript脚本。
        <script type="text/x-my-template" id="list-item">
            <li><a href="%s">%s</a></li>
        </script>

     

一旦取出了模板,剩下的事就好办了,用JS把每个%s替换成数据就OK了~。

PS:此方法和上面的方法都是针对简单格式的,并无太多转义,我偏好傻瓜式的作者推荐的方法三(第三方插件),它提供的成熟的解决方案大大方便了程序员。

5.5.3 方法三:复杂客户端模板

如果你想用一些更健壮的模板,可以考虑诸如Handlebars所提供的解决方案。

具体可以去它的官网上查看。非常强大,功能也五花八门的。

 PS:本人还木有接触关于前端框架的东东。。只是听微雨惊尘老师说,前端框架自带解决这个问题的功能,希望自己可以尽快接触~

 

posted @ 2016-01-12 13:50  谢巴奥  阅读(152)  评论(0编辑  收藏  举报