Javascript平稳退化
-
什么是平稳退化呢?我们要知道,有些网站、用户是会禁用掉Javascript的。我们要做的是,将JavaScript做到”即使用户禁用掉JavaScript也不会影响到基本操作“这一点。
一般来说,我们有这几个方面要注意、检查:
检查DOM方法是否可用
当我们使用document.getElementById、document.getElementsByTagName、document.getElementsByClassName等DOM方法时,通常要检查这些方法是否可用。如果不可用,我们在保证基本操作的前提下退出函数。
检查元素属性、元素本身是否存在
在编写网站过程中,有时我们可能会将某个元素删除掉或它的属性删除掉。这是如果不”留好后路“,网站将很容易因为脚本文件出现问题。下列是元素或其属性被删除的示例:
if(!document.getElementById("placeholder")) //改变图片是我们的主要操作;因此如果placeholder不存在,那么文字的改变将没有意义 return false;//如果图片切换失败,退出函数,返回false
元素不存在,直接退出函数;
var pictitle = whichpic.getAttribute("title") ? whichpic.getAttribute("title") : "";//如果title属性缺失,返回空字符串
元素属性不存在,返回空字符串。
检查某函数是否运行成功
我们在调用函数的过程中往往会涉及到别的函数。有时我们应当判断,我们在当前函数中调用的函数是否能成功运行呢?如果运行失败那么怎样平稳退化呢?
下面是一个例子:
for(var i = 0; i < links.length; i++) { links[i].onclick = function() { return !showPic(this); //如果图片切换成功,showPic返回true,那么该函数返回false,点击链接弹出新窗口的默认行为将被禁用 } //如果图片切换失败,showPic返回false,那么该函数返回true,点击链接将会保留原有的行为, //即禁用js或者placeholder不存在也不影响操作 }
我们看到,在当前函数中调用的函数有返回值true/false。当true时代表执行成功,我们做出相应的操作;false时代表执行失败,我们就留下后路,在这里即保留点击链接的默认行为。
其实有些检查是没有必要的。在实际工作中,我们针对自己的个人情况决定是否需要这些检查。这些检查针对的是当HTML文档不在我们的掌控范围之内的情况。理想情况下,我们的脚本不应该对HTML文档的内容和结构做出太多的假设。当我们清楚HTML的具体情况时,很多检查也就没有必要了。但是平稳退化的思想依旧重要。
这里是一个平稳退化非常到位的实例,仅供参考。
function showPic(whichpic) { if(!document.getElementById("placeholder")) //改变图片是我们的主要操作;因此如果placeholder不存在,那么文字的改变将没有意义 return false;//如果图片切换失败,退出函数,返回false var source = whichpic.getAttribute("href"); var placeholder = document.getElementById("placeholder"); placeholder.setAttribute("src", source); if(document.getElementById("description"))//改变文字是我们的次要操作;即使description不存在,我们上面改变图片的操作也可以运行 { var pictitle = whichpic.getAttribute("title") ? whichpic.getAttribute("title") : "";//如果title属性缺失,返回空字符串 var description = document.getElementById("description"); if(description.firstChild.nodeType == 3)//如果description的firstchilde是文本节点,则执行以下操作 description.firstChild.nodeValue = pictitle; } return true;//如果图片切换成功,返回true,方便下面判断图片是否切换成功 } function prepareGallery() { if(!document.getElementById || !document.getElementsByTagName)//检查这两种DOM方法是否可行 return false; if(!document.getElementById("imagegallery"))//预防性措施:即使以后从网页上删除了图片库,也不用担心JS代码会出错 return false; var gallery = document.getElementById("imagegallery"); var links = gallery.getElementsByTagName("a"); for(var i = 0; i < links.length; i++) { links[i].onclick = function() { return !showPic(this);//如果图片切换成功,showPic返回true,那么该函数返回false,点击链接弹出新窗口的默认行为将被禁用 } //如果图片切换失败,showPic返回false,那么该函数返回true,点击链接将会保留原有的行为, //即禁用js或者placeholder不存在也不影响操作 } } function addLoadEvent(func) { var oldonload = window.onload;//将现有的window.onload事件存入oldonload变量 if(typeof oldonload != 'function')//如果这个事件处理函数上还没有绑定任何函数 window.onload = func;//那么就给它添加这个函数 else//如果事件处理函数上已经有了其他的函数 { window.onload = function() { oldonload();//执行旧的函数 func();//并将新函数追加到现有指令的末尾 } } } addLoadEvent(prepareGallery);