可维护的Javascript 编写指南-解耦UI层
回到目录
本节规则比较好掌握,实用,就是一句话:该写的哪的,就应该写在哪。
这句话解释下:Dom的css样式,就应该写在css样式表里,js代码就该写在js代码中。
让我正式给各位看官介绍下主要内容吧。
- 不要在Css中写js
- 不要在Js中写Css
- 不要在Html中写js
在做过项目中,遵循上面三点的少之又少。
那为啥还要这么要求呢?
目的只有一个就是解耦代码,便于维护,特别是针对那么多页面,多js的项目。
不要在Css中写js
/* 不推荐的代码 如果expression出错,在浏览器很难跟踪问题 */ .box { width:expression(document.body.offsetWidth+"px"); }
不要在Js中写Css
在页面中出现Css需要进行样式调整时,不需要考虑Js代码,只需要去改css就可以了。
// 不推荐 element.style.color="red"; // 不推荐 element.style.color="red"; element.style.left="10px"; element.style.top="10px"; element.style.visibility="visible";
// 不推荐 element.style.cssText = "color: red; left: 10px; top: 100px; visibility: hidden";
需要样式调整的,可以在Css中定义class
.reveal { color: red; left: 10px; top: 100px; visibility: visible; }
然后在Js中,可以通过操作class控制样式调整
// 推荐 - 原生 element.className += " reveal"; // 推荐 - HTML5 element.classList.add("reveal"); // 推荐 - jQuery $(element).addClass("reveal");
这样一来,样式一旦需要调整,可直接通过css修改
不要在Html中写Js
一个页面经常有多个js代码,也就造就了多个js同时操作一个Dom,同一个事件。
<!-- 不推荐 --> <button onclick="doSomething()" id="action-btn">Click Me</button>
这是常见的写法,这种写法在很多场景下,应用都没问题。但是有几个不易发现的问题
首先,当按钮被点击时,doSomething()事件必须存在,否则,Js就报错.doSomething()可能是从外部Js中加载的,或者出现在Html代码后面。无论哪种方式,用户都可以在函数可用之前单击按钮,造成一个JavaScript错误。出现Js错误,直接导致按钮操作不了,这两种情况下是不可取的。
第二个问题是维护问题。如果你想改变doSomething()的名字吗?当点击按钮的时候,调用一个不同的函数会发生什么?在这两种情况下,你都在修改JavaScript和HTML;这就是紧密耦合代码的本质。
因此把事件绑定,直接写在<script></script>里,才是上策。
function doSomething()
{ // code } var btn = document.getElementById("action-btn"); btn.addEventListener("click", doSomething, false); // 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; } }
目前,Jquery是常用的Js库,你可以这样写:
function doSomeThing() { // code } $("#btn1").on("click",doSomeThing); //或者 $(document).on("#btn1","click",doSomeThing);
另外,最好不要单独把方法的引用放在Js中
<!-- 不推荐 --> <script> doSomething(); </script>
避免把HTML掺杂在Js中
- 简单客户端模版
- 复杂的客户端模版
前面提倡,不要把Js写在HTML中,同理,不要把Html写在Js中。坚持JS,HTML,CSS解耦,对后期页面维护,debug都有更好的作用。
// 这是项目中常见的代码,并不推荐这样用 var div = document.getElementById("my-div"); div.innerHTML = "<h3>Error</h3><p>Invalid e-mail address.</p>";
简单客户端模版
将模版直接固定,每次生成时,都是通过调用方法,去生成HTML
function sprintf(text) { var i=1, args=arguments; return text.replace(/%s/g , function() { return (i < args.length) ? args[i++] : ""; }); } var templateText='<li><a href="%s">%s</a></li>'; var result=sprintf(templateText, "/item/4", "Fourth item");
还可以这样写
<html lang="en" xmlns="http://www.w3.org/1999/xhtml"> <head> <meta charset="utf-8" /> <title></title> <script> function sprintf(text) { var i = 1, args = arguments; return text.replace(/%s/g, function () { return (i < args.length) ? args[i++] : ""; }); } function addItem(url, text) { var mylist = document.getElementById("mylist"), templateText = mylist.firstChild.nodeValue, result = sprintf(templateText, url, text); mylist.innerHTML += result; } addItem("/item/4", "Fourth item"); </script> </head> <body> <ul id="mylist"> <!--<li><a href="%s">%s</a></li>--> <li><a href="/item/1">First item</a></li> <li><a href="/item/2">Second item</a></li> <li><a href="/item/3">Third item</a></li> </ul> </body> </html>
另一种写法
<html lang="en" xmlns="http://www.w3.org/1999/xhtml"> <head> <meta charset="utf-8" /> <title></title> <script type="text/x-my-template" id="list-item"> <li><a href="%s">%s</a></li> </script> </head> <body> <ul id="mylist"> <!--<li><a href="%s">%s</a></li>--> <li><a href="/item/1">First item</a></li> <li><a href="/item/2">Second item</a></li> <li><a href="/item/3">Third item</a></li> </ul> <script> function sprintf(text) { var i = 1, args = arguments; return text.replace(/%s/g, function () { return (i < args.length) ? args[i++] : ""; }); } function addItem(url, text) { var mylist = document.getElementById("mylist"), script = document.getElementById("list-item"), templateText = script.text, result = sprintf(templateText, url, text), div = document.createElement("div"); div.innerHTML = result.replace(/^s*/, ""); mylist.innerHTML += result.replace(/^s*/, ""); } // usage addItem("/item/4", "Fourth item"); </script> </body> </html>
复杂的客户端模版
如knockout.js 地址: http://knockoutjs.com/
这种模版,也是项目中常用到的。这里就不赘述了,想了解的,可以通过上面的链接,去访问官方网站。