将 JavaScript 从 CSS 中抽离
不要使用 IE 8 及更早版本支持的一个特性:CSS 表达式。
/* 不好的写法 */.box { width: expression(document.body.offsetWidth + "px");}
将 CSS 从 JavaScript 抽离
// 不好的写法element.style.color = "red";
将 CSS 从 JavaScript 中抽离,需要把所有的样式信息都放在 CSS 里。这样 JavaScript 只需要操作 CSS 的 className。
// 好的写法- 原生代码element.className += " reveal";// 好的写法- HTML5element.classList.add("reveal");// 好的写法 - YUIY.one(element).addClass("reveal");// 好的写法 - jQuery$(element).addClass("reveal");// 好的写法 - dojodojo.addClass(element, "reveal");
将 JavaScript 从 HTML 中抽离
绝大多数(并非所有的) 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 类库:
// YUIY.one("#action-btn").on("click", doSomething);// jQuery$("#action-btn").on("click", doSomething);// dojovar 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 类库:
// YUIfunction loadDialog(name, oncomplete) { Y.one("#dlg-holder").load("/js/dialog/" + name, oncomplete);}// jQueryfunction loadDialog(name, oncomplete) { $("#dlg-holder").load("/js/dialog/" + name, oncomplete);}
出于性能的原因,可以考虑采用客户端模板。
方法 2:简单客户端模板
一段数据项模板:
和一个格式化函数:
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 注释中包含模板文件
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 > 中包含模板文件
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()所提供的解决方案。
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");