以一个简单的web程序为例
具体设计模式请配合代码及注释食用
<!DOCTYPE html>
<!--
1 预留退路:如果用户禁用了js,链接还能正常显示吗?(href)
2 分离js:行为层与结构层真的分开且互不干扰吗?(onclick)
3 向后兼容:js代码中检测了浏览器的函数支持吗?(if(!xxx)return)
-->
<html lang="en">
<head>
<meta charset="UTF-8">
<title>ImageGallery</title>
<!--<script type="text/javascript" src="scripts/showPic.js"></script>-->
<script type="text/javascript" src="scripts/preparegallery.js"></script>
<!--<script type="text/javascript" src="scripts/popUp.js"></script> 测试弹窗脚本-->
<link rel="stylesheet" href="css/layout.css" type="text/css" media="screen">
<!--<link rel="stylesheet" href="css/.warning.css" type="text/css" media="screen">-->
</head>
<body>
<h1>snapshots</h1>
<!-- 测试通过链接调用js函数-->
<!--<a href="javascript:popUp('http://www.baidu.com');">test 'javascript:'</a>-->
<!-- 测试通过onclick调用js函数-->
<!--<a href="#" οnclick="popUp('http://www.baidu.com');return false">test on click popUp</a>-->
<!-- 预留退路:将href地址与popup的url地址设为相同的-->
<!--<a href="http://www.baidu.com" οnclick="popUp('http://www.baidu.com');return false;">test popup</a>-->
<!-- 使用弹窗的标准写法2个-->
<!--<a href="http://www.baidu.com" οnclick="popUp(this.getAttribute('href'));return false;">test popup</a>-->
<!--<a href="http://www.baidu.com" οnclick="popUp(this.href);return false;">test popup</a>-->
<!-- test warning css-->
<!--<p class="warning">Be careful!</p>-->
<ul id="imagegallery"><!-- js分离的群体控制,挂钩子-->
<li>
<!--js分离前(onclick)<a href="images/fireworks.jpg"
οnclick="showPic(this);return false;" title="A firework display">Firework</a>-->
<!--测试js分离(popup)(单个控制)<a href="images/fireworks.jpg"
title= "A firework display" class="popup">Fireworks</a>-->
<a href="images/fireworks.jpg" title="A firework display">
Fireworks</a>
</li>
<li>
<a href="images/coffee.jpg" title="A cup of black coffee">
Coffee</a>
</li>
<li>
<a href="images/rose.jpg" title="A red, red rose">
Rose</a>
</li>
<li>
<a href="images/bigben.jpg" title="The famous clock">
BigBen</a>
</li>
</ul>
<img id="placeholder" src="images/placeholder.gif" alt="my image gallery" οnlοad="alert(3)"/> <!--img:alt 无法显示图片时用来替换的文本-->
<p id="description">Choose an image.</p>
</body>
</html>
window.onload = preparegallery;
//addLoadEvent(preparegallery());
//addLoadEvent(showPic());
function preparegallery(){
if (!document.getElementsByTagName) return false; // 向后兼容
if (!document.getElementById) return false;
if (!document.getElementById("imagegallery")) return false; // 预防性措施
var gallery = document.getElementById("imagegallery");
var links = gallery.getElementsByTagName("a");
for (var i=0; i<links.length; i++) {
links[i].onclick = function() {
// 此处根据showPic的返回值控制了:onclick之后是否还要再打开一次链接(预留退路)
//alert(showPic(this));
return showPic(this);
}
}
}
// 改良后的showPic函数 (集成里替换图片、替换文字的两个功能)
// 为什么检测的这么细致呢,面对我们不可控制的html时写的js代码,不能主观认为html里一定有什么,有点fuzzing的感觉
function showPic(whichpic) {
// 向后兼容,如果没有placeholder,那么onclick函数完全无用,
// 考虑到“预留退路”,应该不取消onclick后面的return!
// 此处用showPic的返回值进行控制是否取消onclick的"后摇"
// (见调用showPic()的onclick函数! )
if (!document.getElementById("placeholder")) return true; // 向后兼容(不取消onclick之后的默认动作)
var source = whichpic.getAttribute("href");
// 检查是否是图片 注意在nodeName中全是大写的
var placeholder = document.getElementById("placeholder");
if (placeholder.nodeName != "IMG") return true;
placeholder.setAttribute("src", source); // 替换图片
if (!document.getElementById("description")) return false; // 向后兼容(取消默认动作)
var description = document.getElementById("description");
if (whichpic.getAttribute("title")) { // 继续减少依赖性,用if判断
var text = whichpic.getAttribute("title");
} else {
var text = ''; // 这样处理即使出错也不会影响视觉效果
}
// 检查是否是文本
if (description.firstChild.nodeType == 3) {
description.firstChild.nodeValue = text; // 替换文本
}
return false; // 千万别忘了这一句
}
/*
// 加载js函数的通用方式
// 因为要将js分离,将onclick写到js里,所以需要在加载完html后、接受用户操作前加载js函数
// 为避免onload的冲突,采用以下两种通用方式
//1 为onload指定函数
window.onload = function(){
showPic();
preparegallery();
};
//2 程序化解决(在脚本库中添加addLoadEvent() 函数 并在添加时调用)
addLoadEvent(preparegallery());
*/
function addLoadEvent(func) {
var oldonload = window.onload;
if (typeof window.onload != 'function') {
window.onload = func;
}
else{
window.onload = function(){
oldonload();
func();
}
}
}
//使用:
//addLoadEvent(function_name)
/**
*
* Created by xy on 7/18/15.
*/
function popUp(winURL){
window.open(winURL, "popUp", "width=320, height=480");
}
/*
//分离js与html(将onclick方法放入js代码中)
//script文档在html的head标签里被引入并加载,所以下面代码将会在body加载之前就运行,是无效的
var links = document.getElementsByTagName("a");
for (var i=0; i<links.length; i++) {
links[i].onclick = function(){
popUp(this.getAttribute("href"));
return false;
}
}
*/
/*
//正确的处理方式(分离js)
window.onload = prepareLinks;
function prepareLinks(){
var links = document.getElementsByTagName("a");
for (var i=0; i<links.length; i++) {
if(links[i].getAttribute("class") == "popup") { //对具有class=popup属性的标签加载onclick方法
links[i].onclick = function() {
popUp(this.getAttribute("href")); //调用popUp函数
return false;
}
}
}
}
*/
//向后兼容(察看浏览器知否支持这个方法)
//为了减少大括号层数,使用if(!xxx)return false;特别注意这里的方法不是调用,方法后面不要有小括号!
//修改上例代码如下
//window.onload = prepareLinks;
function prepareLinks(){
if (!document.getElementsByTagName) return false; // see this !
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;
}
}
}
}