javascript事件 from PPK yahoo演讲

作者:kun10 发布时间:March 30, 2010 分类:JavaScript


----------以上是ppk在yahoo演说js events的视频-------------

----以下是本人利用自己的双耳听到的,用自己的脑袋理解和翻译出来的,可以作为参考,以下的“我”表示PPK,如若误解,深表荣幸----

今天我会说一些关于JavaScript事件的事情,我很希望自己能启发大家一些什么,不过大伙都是高手,不管怎么,我还是要说说JavaScript事件。
大约一年前我打算对JavaScript的事件做一些深入的研究,并且我做了一张兼容性的表,大家可以通过下面这里来访问

http://quirksmode.org/dom/events


那么今天我会和大家谈论4件事情:
首先会是key事件(按键事件),因为在这里存在很多的困惑,很多是关于他们如何工作的困惑。
然后我会谈谈change事件,他是我很喜欢的一个事件,不幸的是,它的工作情况有些乱。
第三,我会谈谈委派focus事件,当然可能你已经知道了。委派的事件通常只会触发在鼠标或者是键盘事件上,但是我找到了一种办法使它也能够使用在focus上面。
最后我会说说手机上面的事件,相当诡异的东西。。。

那么首先就来看看键盘事件吧,键盘事件有三个:keydown,keypress和keyup。大多数的人都认为自己很清楚他们在会何时触发,而我在这里要告诉你,其实未必就如你所想的那样。
我们先来看看定义,、
keydown事件:当用户按下键盘上面的一个键时会触发,用户一直按着这个键他就会持续触发。
keypress事件:有一点点的不同,用户按着一个字符键(原文是character key)才触发,就是说用户按了一个能在屏幕上输出字符的按键keypress事件才会触发,比如我们往一个textarea里面输入字符。
keyup事件:很简单,当我们释放一个按键时候会触发。
举一个例子,这样你能更明白些
比方说我按下了一个字母“o”键或是字母“i”键,那么keydown和keypress就都会触发,而当我按下的是一个特殊的按键比如是shift键,那么kyedown会触发,而keypress不会。
keydown和keypress的这种区别最初是由微软提出的,所有的ie都支持这种区分方式,一年前(08年吧)推出的safari3.1也适用这样的方式,不过这只是说明了keydown和keypress存在方式的不同。相比较,firefox和opera会同时触发多个事件,因为此时事件既是一个keydown事件又是一个keypress事件,所以我们应该会同时触发多个事件。这样很好,但是这样却无法解释为什么要同时存在两种事件、而不是一种(keydown)。所以其实我还是很喜欢微软的这种区分的。
好吧,我们再来重温一次概念,keydown会在任何键按下时触发,keypress只是在字符键按下时触发,以上是在ie和safari下的情况,另外,我目前没有google chrome,不过他和safari很相近,所以这个应该也适用于chrome浏览器。

OK,让我们来看一些实际问题,通常我们都会写一段脚本来检测用户按过哪个按钮,然后利用这样的结果做一些有趣的交互应用。

键盘事件拥有两个属性,keyCode和CharCode,他们之间有一些不一样之处。keyCode表示用户按下键的实际的编码,而charCode是指用户按下字符的编码。
因此,当我按下“a键”,我会得到keyCode 65和字母a的charCode 97(注意是小写的字母哦),而当我按下shift键,我会得到keyCode 16,而我不会得到任何的charCode,因为按shift并没输入任何的字符。就这样,很简单吧~~~
我们现在得到两个属性了,两个属性各自包含了各种的信息,这真是好事~~~

但是接下来我们又遇到问题了,很复杂,无法解释但它就是这样的问题。keyCode属性。在keyDown事件里面,事件包含了keyCode – 用户按下的按键的物理编码。在Onkeypress里,keyCode包含了字符编码,即表示字符的ASCII码。这样的形式适用于所有的浏览器 – 除了火狐,它在onkeypress的时候keyCode返回数字0, 别问我为什么,它就这样。然后,火狐在Onkeydown中charCode返回数字0,在 onkeypress里,由charCode返回字符ASCII编码。而这个,只会在Firefox和Safari工作,因为他们是唯一支持charCode的浏览器。(这一段翻译感谢信息学院的AN同学的纠正)

让我们更进一步看点更实际的东西,如果你想获取用户实际敲击的按钮,用keyDown事件来获取事件对象,并获取keyCode,这在所有浏览器都行的通。另一方面,如果你想获取用户输入的字符,那么就使用keypress来获取,然后获取charCode(火狐和safari)或是keyCode(其他浏览器)

然后,我想有时候你也会有阻止某个按钮默认行为的想法,很常见的是方向键
设想你有一个适合于键盘的拖拽菜单,你希望用户用方向键来实现一个拖拽的操作,因此你就要取消方向键的默认行为(使页面向上或是向下滚动),那么一般来说你就会在keyDown事件里面做这件事,因为如我所说的那样----keyDown会在一个按钮被按下时候触发,而keyPress只是在字符键按下时触发,但是很不幸,这样子在opera行不通(当然我得承认我没有测试最新版的opera,也许现在已经修复了这个问题?待测试)。因此,我今天不会讨论在opera下面阻止方向键的方法,很坦诚的说,我还没有一个答案。

这就是键盘事件的一些总结,不会很麻烦吧?我说了几种键盘事件,但是你得注意keydown和keypress的差别。

好了好了,来说说change事件吧。照理论说,change事件应该是很好的一个事件,因为他应该是在表单有变化的时候触发。比如,你想在表单提交时检测一些用户操作表单的事情,比如是检测和验证用户在各个域的输入。当然也有很多时候我们会动态创建一个表单或是表单域或是选框--这样的表单会和用户之间产生很复杂的交互,这时候我们就要知道用户什么时候对表单作了修改,从理论上说,change事件是最合适不过的了。

但是通常,我们总是会被迫去使用focus和blur事件或者是click事件去做检测表单变化的事,而不是用change事件。这是因为change事件不总是能很正常的运行着。我们分三种情况来讨论
1、文本框的变化事件(text field)
2、选择框的变化事件(select box)
3、复选框和单选框的变化事件

从文本框开始说吧,假设用户把焦点移动到了文本框上面(或用鼠标或用键盘的方式),之后又移去了焦点,比如说他进入了下一个文本框的输入。在这样的情况下,change事件不触发,因为没有什么东西改变了---注意,第一个文本框的值并没有改变。但是我们对上述事情稍稍做一些变化,如果我们说,用户点击了文本框,并输入了一些文本,然后再撤去焦点,这就触发了change事件,很好,他在所有浏览器中都如此工作。

然而,当我们使用selectbox的时候问题就来了,选择框事件是你可以想到的最古老的浏览器事件,我想大约在95、96年我们在浏览器中就有了selectbox了,他可能列出了漂亮的链接,并节省了页面的空间。我们已经使用选择框有很长一段时间了,你也可以用鼠标去做一个选择。首先你点击选择框,它便列出了选项,当你再次单击里面的一个选项时,就触发了change事件。因为浏览器知道:“ok,用户已经改变了选择框里面的值了”。这也是用于所有的浏览器。

但是,用户还可以用键盘来操作改变选择框(select)的值,这就为我们使用change事件带来了麻烦。首先用户会把焦点移动到selectBox上面,然后利用方向键来选择他需要的选项。这还不是什么问题,但是这种情况,在IE和opera下面,每当用户按一次方向键(切换选项),change事件就会触发一次。这明显是很大的一个问题,如果一个选项表有20个选项,那么用户从第一个选项移到最后一个就会触发19次change事件,这可以说是ie和opera很严重的一个bug。
而在firefox和safari里面,他们所做的工作就是,允许用户在选项之间用上下键来选择,然后会在用户blur这个选择框的时候触发change事件,通俗的说,你告诉浏览器,我已经选择好了,浏览器你可以用change事件看看我是不是做了改变----像firefox和safari这样的工作方式很好很正确。不过,在IE下面做一些类似于选框导航的工作,当用户用键盘来操作,使用change事件就很容易产生问题。这就是我们对于change事件的首个大问题。

不幸的事继续发生,当我们在复选和单选框上面使用change事件,情况会更糟,我以一个复选框为例,基本上他和单选的工作方式一样。当用户点击了复选框(我不仅仅指用鼠标点选),一个点选操作可以通过鼠标或是键盘来达到。总之,这样的一个点击使得复选框的值发生了变化---true or false。按常理这时候change就发生了,因为用户确确实实的改变了东西,这样的一件事也的的确确会在firefox,safari,opera里面发生,但是IE不会
IE到底怎么了?你点击了复选框而什么也没有发生。接下来呢,你用鼠标或是键盘把焦点移出这个复选框移到别的复选框上面,原来的这个复选框的blur事件就触发了,同时change事件随之触发。这样的情况对于一些整理表格的操作实现来说是很糟糕的,比如通过复选框来开启表单的隐藏选项,在IE下面你只能在blur一个复选框的时候开启隐藏选项,这样对于用户来说是很困惑的(因为会给用户带来一种滞后的感觉)。这也是IE下面一个很严重的bug。

你可以看到我在ppt上面给W3C也划了一个叉号,因为据我所知w3c的事件标准只是规定了blur,根据标准,一个change事件应该在一个表单域改变并被移去焦点时发生。现在我们可以总结一下,change在文本域里面工作的很不错,当我们用键盘操作select框是它很有意义,而对于单选框和复选框或者是你用鼠标操作select框change事件使用的意义就不太大。(我作为翻译认为这里ppk出现了口误,把鼠标和键盘操作selectbox的情况说反了,大家要看了欢迎纠正,另外ppk貌似也没有提到用鼠标scroll方式操作select框的值的方式)

这就是我们目前遇到的一个问题,而我目前还没有找到一个很好的解决方式。幸运的是,我们可以用click事件或是focus事件或是blur事件做一些弥补,虽然这不会花费太多的精力,但是我还是期望change事件能变得真正的实用。这样我们可以比较统一的用一个事件去侦测一个表单里面的变化并做一些有意思的事。目前这还是我们能期待的。

进入我们今天的第三个话题吧,事件委派(event delegation),我非常确信你(指yahoo的同学们)应该已经知道什么是事件委派,不过其他的人却不知道,我简单的介绍一下。基本来说,事件委派是减少定义事件处理的一种方式,我们用下拉菜单为例。用传统的方式,我们可能要对这个下拉菜单添加很多的事件处理函数,当你的鼠标停留在父级菜单上面,1级子菜单弹出,我们在移动鼠标到1级菜单上面,二级菜单又会出来。而当我们使用事件委派时情况就有所不同,事件委派利用了事件的冒泡,当用户移动鼠标到一个链接(link)上面,触发了链接的mouseover事件,同时通过冒泡mouseover事件冒泡到了链接的上一级元素,直至冒泡到整个文档上面,这个过程会触发链接(link)上级任何一个含有mouseover事件的元素的mouseover事件,比如会冒泡到li和ul的mouseover事件,那我们为什么不把处理事件的函数放在链接的上层呢?这样可以节省众多链接的事件处理函数的绑定。

曾经我的一个客户抱怨他的站点有点慢,尤其是在IE下面,于是我看了源代码,我发现他的下拉菜单有六七十甚至更多的链接,每一个链接绑定了自己的mouseover、mousedown、mouseout事件,这就使得页面变得缓慢了。
因为每一个浏览器都会为单独的事件处理开辟一个单独的内存,更何况是IE(拥有内存泄露的美名)。于是我告诉我的客户事件委派,然后。。。。(网页快起来了)

那么首先让我们来建立一个下拉菜单

<ul>
<li><a href=”#”>Multimedialize</a>
<ul>
<li><a href=”#”>Sound</a></li>
<li><a href=”#”>Java applets</a></li>
</ul></li>
<li><a href=”#”>Ajaxify</a>
<ul>
<li><a href=”#”>Web 2.0</a></li>
<li><a href=”#”>Web 3.0</a></li>
<li><a href=”#”>Web 4.0b</a></li>
</ul></li>
</ul>

我们首先把我们的mouseover和mouseout事件处理函数绑定到ul上面,这在所有浏览器中都行的通。

var dropdown = {
    init: function (dropdown) {
       dropdown.onmouseover = this.mouseOver;
       dropdown.onmouseout = this.mouseOut;
    }
}

不过如果一个用户不用鼠标,而是想用键盘操作打开这个下拉菜单,我们又该怎么做呢?这个问题有个我们带来了一个重要的主题,设备的独立性(让网页支持多种设备的操作)。这也是我想向大家解说的,我们做的东西要兼容各种设备。
基本的规则是,所有带有“mouse”在名字里面的事件,只是在你真正使用鼠标的时候工作。听起来很简单吧,不过这总会被很多人忽视。因此,我们需要用户使用键盘的时候能告诉我们用户何时是鼠标移入何时又是鼠标移出的事件,那么目前看最合适不过的就是focus和blur事件。因此,如果事件通过鼠标mouseover或是键盘focus冒泡到上面的元素,冒泡到达ul时我们就执行目标函数展开菜单。当鼠标mouseout或者是键盘blur冒泡上去时,我们就执行关闭菜单的函数。但是问题在于,这不可行,因为focus和blur事件不会冒泡。

这就带给我们另一个问题,什么事件支持冒泡?什么事件又不支持冒泡?我们先把事件分为两类:一类是设备事件(鼠标或是键盘按键事件),另一类是界面事件。

鼠标和键盘事件是在使用输入设备的时候触发的,我还在做一个更好的定义,不过基本是这个意思,基本上用户所作的就是点击鼠标按键、点击键盘按键、移动鼠标或其他的一些事,总之是和一个具体的外接设备相关的,这些事件的例子如,mouseout,mouseover,click,keydown,keypress,顺便说一声click是唯一既迟滞鼠标触发又支持键盘触发的事件:你用鼠标点击会触发click,用键盘tab移动焦点到目标然后回车也会触发click。click是很少的能够工作于多种设备下的事件。因此,一个click事件是很安全的。其他的一些设备事件总是只支持某一个设备,最后要说的,就是以上提及的这些事件支持冒泡,直到document级。

界面事件,在一个常规事件触发时执行,而不关注它是如何被触发的(翻译的有点生涩,欢迎提意见)
界面事件的一个比较好的例子是,表单的submit事件,当一个表单被提交他就会触发,而表单submit事件并不关心用户是用什么方式来提交表单的,可以使用户用鼠标点击了提交按钮提交表单,可以是用户输入文本按了回车提交表单,只要是提交了表单,submit事件就会触发。这类事件还有很多,又如onload,onupload,change,focus,blur,对了这里有我们苦苦追寻的focus和blur事件。因为我们希望我们的下拉菜单能够兼容多种设备。

大体来说,界面事件不支持冒泡,对我们来说这真是一个不好的消息,因为如果我们想让键盘用户也能用我们的下拉菜单,我们就要用到focus和blur。但是focus和blur并不能冒泡上ul元素,我们就只能老老实实的把事件处理绑定在每一个li上面了。当然还有一个不算好消息的好消息,我们可以在事件捕获中得到focus和blur,事件捕获的工作是和事件冒泡相反的,但是它在IE下不被支持。。。不过我们一会儿会讨论IE。

我们说事件冒泡,我们点击了a元素,a的click执行,然后事件冒泡到了li,之后是ul,之后是document。事件捕获则是,在我们点击了a之后,事件从document一级级的下来,经过ul、li、然后才到达a并终止捕获。你会觉得冒泡和捕获这两个东西用哪个都差不多,不过当我向dean Edwards问了这个问题后,他说:“不不不,你应该在大多数情况下去使用事件捕获”。

当你要捕获一个focus事件,被绑定在目标元素的祖先元素上的事件就会被执行,这个可以在所有浏览器下使用,当然除了IE,因为它不支持事件捕获。因此基本来说,如果我们把焦点移上a元素上并同时使用事件冒泡,只有a链接的unfocus事件会被触发。但是我们反过来使用事件捕获,那么这个unfocus事件就会顺着document->ul->li的顺序执行下去。

为什么事件捕获和事件冒泡会有差别?我也说不出。这只是我测试出来的,我开始在opera里面测试,开始我以为他只是opera特有的,但是我在firefox下面也测试,哦?火狐也有这个特性,然后又测试了safari,呵呵,safari也有同样的表现,最后,我发现它几乎是一个跨浏览器的特性。这样让我觉得事件冒泡和事件捕获具有同样的作用,因为在我之前的感觉中,事件是否能被捕获并不最重要,但是能否冒泡就不一样了(能否被冒泡意义重大)。不管怎么说,目前的这种状况(应该是说冒泡和捕获的混乱的支持情况)意义不是很大,但他确实能解决很实际的问题,因为现在我们可以对focus和blur进行事件委派了。

我们要做的很简单,我们给根元素添加上addEventListener,并给这个函数的最后一个参数设为true,使其工作在捕获阶段。

var dropdown = {
    init: function (dropdown) {
        dropdown.onmouseover = this.mouseOver;
        dropdown.onmouseout = this.mouseOut;
        dropdown.addEventListener('focus',this.mouseOver,true);
        dropdown.addEventListener('blur',this.mouseOut,true);
    }
}

这样,一旦下拉菜单有focus事件发生,那么ul上面的事件捕获就会触发,绑定在上面的this.mouseOver函数就会被执行。别问why,他就是这样工作的。

当然,因为IE不支持事件捕获,我们还要添加一点点东西,做一些修改,IE虽不支持事件捕获但是他有自己的解决方案,这是IE所特有的。

var dropdown = {
    init: function (dropdown) {
        dropdown.onmouseover = this.mouseOver;
        dropdown.onmouseout = this.mouseOut;
        if (dropdown.addEventListener) {
            dropdown.addEventListener('focus',this.mouseOver,true);
            dropdown.addEventListener('blur',this.mouseOut,true);
        }
        dropdown.onfocusin = this.mouseOver;
        dropdown.onfocusout = this.mouseOut;
    }

IE带有两个类似于focus和blur的事件,但唯一的区别就在于他们支持冒泡,他们是focusin和focusout,我们给原来的代码添加上两行,dropdown.onfocusin, and dropdown.onfocusout。这样我们的事件委派就工作在了所有的浏览器中。

顺便说一声,YUI团队已经把这种特性纳入了他们的之中,不过当你使用其他的一些库的时候,这样的技巧你也可以记一下以便必要时候用得到,这样的技巧很好,但是IE并不是总能提供类似于focusin和focusout这样的东西,所以那种时候你可能会抓狂。
----------------------------------------------------------
休息线
----------------------------------------------------------
......先翻译这三段吧,第四部分PPK讲的是手机端的js事件,看完之后感觉手机端的事件是相当的混乱,目前本人对此研究也不深入,待更明白一点的时候再做翻译吧。。。,上面翻译的也不是很到位,各位千万要提出意见,这里可以给出ppk的原文,欢迎对照指点。

另附:PPK的一些关于事件的文章

《PPK谈JavaScript》读书笔记 --可用性

作者:kun10 发布时间:February 3, 2010 分类:JavaScript

很早就买了ppk的这本书,在还不知道taobaoUED的时候就买了,当时也没有看得很明白,只是看到一些关于用户可用性的东西,觉得很不错,很快就用上了。下面就总结一下用户可访问性的规则:

1、条理分明的HTML

在脚本环境下面要保证可访问性的最显而易见的方法就是确保纯HTML页面包含了成功浏览所需要的“筋骨”,
内容、导航和重要的内容的表单都应该被硬编码(hard-code)到HTML中,这样,无论发生了什么,任何的用户都可以访问并使用它们。
这样,当浏览器不支持JavaScript的时候,会降低一些页面的易用性,但是其基本的功能不会被破坏。

1.1、硬编码的连接必须有href

你的html中任何的一个硬编码的连接都应该拥有一个href属性,他指向一个有用的页面或是其他的文件,因此这样是错误的

 <a href="#" onclick="showPopUp('niceimage.png')">Nice Image</a>

当一个无脚本的用户点击了这个连接,什么也不会发生,
坏例子
对此,我还要严重的批评一下山东毕业生就业信息网,它对于学生给出的就业意向,信息网给出了一些相关的推荐的岗位,但是居然利用了弹出窗口的方式,并且居然没有html硬编码,最可恨的就是他的javacript出错了,导致的问题就是这些学生非常需要的信息学生根本就不能访问,点击后只是提示javascript错误,也没有弹出窗口,也没有打开连接(所以说,真不知道是哪个没头没脑的家伙做的。如果是硬编码的话,至少有点技术的用户还可以分离出里面的html连接来访问这些信息)
相反,一个清醒的javascript的开发者会这么做

<a href="niceimage.png" id="nice">Nice Image<a/>
document.getElementById('nice').onclick = function(){
     showPopup(thie.href);
}

现在,无脚本用户沿用被硬编码的href属性,而脚步用户会打开一个弹出窗口(popup),网站保持了可访问性,而且把行为从结构里面分离了出来。

2、产生对脚本用户有意义的内容

在某些情况下,javaScript中产生的内容使网页更具有可访问性,

2.1、触发高级脚本的链接

假设你有一个链接,点击它将启动一段漂亮的Ajax脚本。这段脚本会获得内容并执行其他有用的任务。但是你没有一个合适的HTML页面可以让这个链接指向它。我们刚才已经看到了,这样是不对的

<a href="#" onclick="startUpAjaxStuff()">我拿代码耍耍酷</a>

我们不能仅仅应用上一条规则(1.1),如果没有明显的于Ajax脚本等效的无脚本替代品,我们改把href指向哪里呢?
如果给链接加上一条href不可行,那么就用JavaScript来生成连接

var link = document.createElement('a');
link.href = "#";
link.onclick = startUpAjaxStuff();
var linkText = document.createTextNode('这回可以耍酷了');
link.appendChild(lintText);
document.body.appendChild(link);

如此一来,无脚本的用户就完全看不到这条连接了,这样很好,因为否则他点了这个连接却发现什么反应也没有,他会很困惑的。
注意,上面的例子把链接的href的属性设置成了'#',虽然我们知道使用#作为href通常不是一个好主意,但是我们需要它,因为绝大多数的浏览器定义一个超连接即使一个拥有href的a元素
幸运的是,在这种情况下,上一条规则并不适用,因为我们只是让支持JavaScript的用户看到了这个链接。能看到这条连接的用户,其浏览器一定支持onclick事件,所以href为#并无大碍。

2.2、用Javscript隐藏内容

隐藏内容是危险的。一般来说,隐藏的内容是你认为如果不立即显示可以提高页面可用性的内容。直到用户点击了页面里面的什么的时候,内容才显示出来。
如果没有JavaScript,内容就永远不会显示,而且这个页面就不具备可访问性,如果你创建了一个隐藏内容直到用户激活一段脚本的时候才显示,那么你应该始终用JavaScript来作这件事情,而不是在CSS中
有时候直接定义这样的css是不好的

 .importantContent
    {
       display:none;
    }

如果一个无脚本的用户访问你的页面,他将不会看到这些所谓的重要的信息,因此这个页面的可访问性就降低了,我想,一些页面所呈现的重要的信息,比如一些公告,应该设置css的时候就设定为display:block,然后用javascript去控制其隐藏和显示。,不过你在此处有什么反驳咱们可以探讨一下~~~
值得一想的例子
----例子----
Google的英文首页,在页面中定义了一个mousemove事件。这个事件只在用户的浏览器支持JavaScript的情况下面会工作(是上一个要点的范例),但我想说的不只是这个,这个鼠标移动事件会使得页面中除了主搜索框以外的一些部分显示出来,如果你不移动鼠标,而直接输入内容,使用的只是搜索框和搜索按钮,不过大多数的用户都是好动的,当他们移动了自己的鼠标的时候,页面上角如google邮箱,阅读器之类的服务连接都显示出来了,个人觉得这是很好的一种体验,不管怎么说至少晚一些运行了javascript。

----例子结束----

3、重定向用户

有时候,解决可访问性的问题就是为你的网站创建一个有脚本的版本和一个无脚本的版本。我不喜欢这个解决方案,显得很不帅。。。但是,就算不怎么帅,他还是很有实用价值的。
如果你使用的是这种方法,就应该遵循两点:
首先,你网站的入口应该是一个无脚本的页面(ppk这么说,其实我觉得到不一定就要做到纯无脚本,而是说做到无脚本可访问就可以,硬编码的什么的必须做到,这样其实第二条我们都可以不管了,很多时候我们应该在一个无脚本可访问的页面的基础上面去创建更好的可用性),这样,所有的浏览器都可以正常的访问;
第二,当浏览器到达这个无脚本页面,启动一段脚本来使得页面跳转到有脚本页面。我们在这里用replace来进行跳转。

<head>
<title>NoScript Page</title>
<script type="text/javascript">
var isSupport = [检测是否支持javascript的代码];
if(isSupport){//如果支持
    location.replace("scriptpage.html");//最好是不要用location.href来做,原因见下面
}
</script>
</head>

如果在这里,你用了location.href,那么,它会在浏览器的历史记录里面建立一条浏览记录,如果用户到达无脚本页面,他就被跳转到了有脚本的页面,然而,一旦他点击了浏览器的后退按钮,就会被送回到无脚本的页面,而上述的跳转代码又被启动,他又被送回有脚本页面(这不是折腾用户是什么?)
location.replace则会覆盖掉原来的页面,用户点击后退,会回到无脚本页面前面的那个页面,这也正好让后退按钮的功能给发挥出来了。所以,不管ppk说的这一部分靠不考谱(我是指把页面分为有脚本和无脚本两个版本的做法),我们都应该知道尽管有些功能效果很相近,但是,不乱用功能,是很重要的一件事,从选好replace和href方法做起。

4、键盘用户

我们已经看到了键盘用户不会发生鼠标事件(除非他们同时使用屏幕阅读器),因此,应该说你应该总是定义鼠标事件的替代方案。有时候这很简单,比如,把mouveover事件和focus事件配对。有时候则会困难些,比如一个托放事件,你就必须编写其他的函数来迎合键盘用户。

4.1、可点击元素

即使你创建了完美的键盘解决方案,如果用户不能把焦点移动到那些元素上面,那也是没有用的,(貌似有点废话阿,咱创建键盘事件不就是等待用户焦点移动来触发的么?但是我们要想的一个问题是用户是否能够将焦点移到元素上。)
我们设想一个下拉菜单,他使用mouseover事件来触发显示下一级的菜单,根据上面的原则,我们添加了focus事件,然后,为了触发focus事件,键盘用户必须把焦点落到下拉菜单上面,如果这一点做不到,那么脚本很明显是不可访问的。
在所有的浏览器中,可以可靠的获得焦点的元素只有链接(带有href的a)、表单域以及按钮(经过测试opera下面的表现很垃圾,都不想说啥,我的版本是9.64,居然不支持tab切换链接。。。)。因此,任何键盘友好事件都应该被设置在这几种元素上面。

5、<noscript>标签

浏览器厂商意识到开发者也许想提供特殊的内容给那些没有javascript解释程序的用户,他们发明了noscript标签。
noscript标签的工作如下所述
1、不支持任何javascript的浏览器不能识别这个标签,因为未知的标签会被HTML解释器忽略。这些浏览器会显示这个标签的内容。或许这里这和浏览器的渲染模式还有一定的关系。
2、支持javascript的浏览器会检查javascript是否背启用了。如果是,他们就从视图中隐藏这个标签的内容,否则就显示标签中的内容
我觉得这样的工作没有什么太大的用处,我基本不用这个标签~~~

  1. 1