將 JavaScript 從 CSS 中抽離
不要使用 IE 8 及更早版本支持的一個特性:CSS 表達式。
/* 不好的寫法 */ .box { expression(document.body.offsetWidth + "px"); }
將 CSS 從 JavaScript 抽離
// 不好的寫法 element.style.color = "red";
將 CSS 從 JavaScript 中抽離,需要把所有的樣式信息都放在 CSS 裏。這樣 JavaScript 只需要操作 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");
將 JavaScript 從 HTML 中抽離
<!-- 不好的寫法 --> <button id="action-btn">Click Me</button>
絕大多數(並非所有的) JavaScript 代碼都應當包含在外部文件中,並在頁面中通過 <script> 標籤來引用。在 HTML 中,也不應當直接給 on 屬性掛載事件處理程序。對於支持 2 級 DOM 模型的瀏覽器來說,可以這樣寫:
function doSomething() { // 代碼 } var btn = document.getElementById("action-btn"); btn.addEventListener("click", doSomething, false);
爲了兼容不支持 addEventListener() 函數的IE8 及其更早版本,需要一個函數封裝差異:
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; } } function doSomething() { // 代碼 } var btn = document.getElementById("action-btn"); addListener(btn, "click", doSomething);
使用 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);
最好將所有的 JavaScript 代碼都放到外部文件中,這樣做的原因是出於緊急調試的考慮。當 JavaScript 報錯,你的下意識的行爲應當是去 JavaScript 文件中查找原因。如果在 HTML 中包含 JavaScript 代碼,則會阻斷你的工作流。
將 HTML 從 JavaScript 中抽離
// 不好的寫法 var div = document.getElementById("my-div"); div.innerHTML = "Error
Invalid e-mail address.
";方法 1:從服務器加載
function loadDialog(name, oncomplete) { varxhr = new XMLHttpRequest(); xhr.open("get", "/js/dialog/" + name, true); xhr.onreadystatechange = function() { if (xhr.readystate == 4 && xhr.status == 200) { var div = document.getElementById("dlg-holder"); div.innerHTML = xhr.responseText; oncomplete); } else { // 處理錯誤 } }; xhr.send(null); }
使用 JavaScript 類庫:
// YUI function loadDialog(name, oncomplete) { Y.one("#dlg-holder").load("/js/dialog/" + name, oncomplete); } // jQuery function loadDialog(name, oncomplete) { $("#dlg-holder").load("/js/dialog/" + name, oncomplete); }
出於性能的原因,可以考慮採用客戶端模板。
方法 2:簡單客戶端模板
一段數據項模板:
<li><a href="%s">%s</li>
和一個格式化函數:
function sprintf(text) { var i=1, args=arguments; return text.replace(/%s/g, function() { return (i < args.length) ? args[i++] : ""; }); } // 用法 var result = sprintf(templateText, "/item/4", "Fourth item");
模板通過兩種方法存放在 HTML 頁面裏。
1) 在 HTML 註釋中包含模板文件
<ul id="mylist"><!--<li id="item%s"><a href="%s">%s</li>--> <li><a href="/item/1">First item</li> <li><a href="/item/2">Second item</li> <li><a href="/item/3">Third item</li> </ul>
function addItem(url, text) { var mylist = document.getElementById("mylist"), templateText = mylist.firstChild.nodeValue, result = sprintf(templateText, url, text); div.innerHTML = result; mylist.insertAdjacentHTML("beforeend", result); } // 用法 addItem("/item/4", "Fourth item");
2) 在 <script> 中包含模板文件
<script type="text/x-my-template" id="list-item"> <li><a href="%s">%s</li> </script>
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.appendChild(div.firstChild); } // 用法 addItem("/item/4", "Fourth item");
方法 3:複雜客戶端模板
考慮使用諸如 Handlebars(http://handlebarsjs.com)所提供的解決方案。
<script type="text/x-handlebars-template" id="list-item"> <li><a href="`url`">`text`</li> </script>
function addItem(url, text) { var mylist = document.getElementById("mylist"), script = document.getElementById("list-item"); templateText = script.text, template = Handlebars.compile(templateText), div = document.createElement("div"), result; result = template({ text: text, url: url }); div.innerHTML = result; mylist.appendChild(div.firstChild); } // 用法 addItem("/item/4", "Fourth item");