首页»前端»浏览器事件的思考

浏览器事件的思考

来源:一淘 UX 发布时间:2012-11-15 阅读次数:

  先看下面的代码:

  var $ = KISSY.all;

  $(‘a’).on(‘click’,function(e){

  doSomeThing();//这个方法貌似很有名

  e.halt();

  });

  上面的代码看起来像是很好的完成了我们交给它的工作,浏览器不会再将我们重定向到href中的链接,但这么做到底有什么不对呢?

  在解释有什么不对前,我们来看看浏览器中事件中的几个概念

  浏览器默认行为

  当我们点击某一个链接的时候,浏览器会直接跳转,在表单中按回车,表单会自动提交,这些都是浏览器的默认行为。

  Javascript事件传播的机制

  什么是事件冒泡?

  比如点击了一个按钮,这个元素上的事件被触发,同时该事件将会传播到它的所有父级元素中被触发。(a->div->body->document->window)这一过程被称为事件冒泡。事件冒泡是从子级元素到父级元素。

  注意:不是所有的事件都能冒泡,blur、focus、load和unload不能像其它事件一样冒泡

  什么是事件捕获?

  和事件冒泡恰恰相反,事件捕获是从父级元素到子级元素。

  什么是事件目标?

  简单的说也就是事件开始的那个元素,也就是上面说的a

  不同浏览器下的事件模型

  ● 支持W3C标准的浏览器:先捕获在冒泡。在添加事件时用addEventListener(event,fn,useCapture)方法,基中第3个参数useCapture是一个Boolean值,为true,则采用事件捕获,为false,则采用事件冒泡。

  ● 不兼容W3C的浏览器(IE):IE只支持事件冒泡,它也不支持addEventListener函数,不过提供了attachEvent()方法来处理事件。

  看完上文,是否有感觉什么地方不对?没有?那再看看下文。

  ”halt“到底做了什么?

  当你每次调用”halt“的时候,它实际上做了2件事情:

  ● e.preventDefault();//阻止浏览器执行默认行为

  ● e.stopPropagation();//取消事件冒泡

  preventDefault和stopPropagation翻译成原生js后

function preventDefault(e) {
//如果提供了事件对象,则这是一个非IE浏览器
if(e && e.preventDefault) {
  //阻止默认浏览器动作(W3C)
  e.preventDefault();
} else {
  //IE中阻止函数器默认动作的方式
  window.event.returnValue = false;
}
return false;
}
 
function stopPropagation(e) {
//如果提供了事件对象,则这是一个非IE浏览器
if(e && e.stopPropagation) {
  //因此它支持W3C的stopPropagation()方法
  e.stopPropagation();
} else {
  //否则,我们需要使用IE的方式来取消事件冒泡
  window.event.cancelBubble = true;
}
return false;
}

  不是吧,我写最开始的代码只是想阻止浏览器的默认行为,不需要取消事件冒泡。

  但是,这样写也没有什么问题?。。ㄗ煊?,啪啪……)。

  确实,大多数情况下,这样的代码没有任何问题,那如果我们把这段代码放大到一个大环境中,会出现什么状况

<div>
<h2><a href="http://etao.com/page1">Page1</a></h2>
<div>
    Teaser text...
</div>
</div>
<div>
<h2><a href="http://etao.com/page2">Page2</a></h2>
<div>
    Teaser text...
 </div>
</div>

  现在假设我们想要在用户点击文章标题时,将文章动态载入到div.content中(也就是doSomeThing做的事情),

  哈哈:上文的js代码也还是会执行啊(年轻人太急)。

  我们顺着这个思路继续,如果我想要在用户点击了一个div.post元素(或者任何一个它的子元素)时,给它加上一个active类,我就需要给div.post绑定click

var posts = $('div.post');
posts.on('click',function () {
posts.removeClass("active");
$(this).addClass("active");
});

  这个代码就会有时候执行有时候不执行,因为你在点击a的时候取消了事件冒泡。

  我们把这个代码的执行范围再次放大,产品提了一个需求,要求监听页面上所有的点击情况,一个同学接到需求,开心的在document上用了事件代理,向服务端发送了数据,回头数据一统计,似乎少了什么?;赝芬豢?,有人在a标签的点击事件中用了halt。

  其实这就是本文想传递的信息,大多数情况下,当你使用halt时,你其实真正需要的是e.preventDefault(),在你写通用的组件时候这个问题尤其突出。

相关文档:浏览器大战

QQ群:WEB开发者官方群(515171538),验证消息:10000
微信群:加小编微信 849023636 邀请您加入,验证消息:10000
提示:更多精彩内容关注微信公众号:全栈开发者中心(fsder-com)
网友评论(共0条评论) 正在载入评论......
理智评论文明上网,拒绝恶意谩骂 发表评论 / 共0条评论
登录会员中心
大发国际网址 鄂托克前旗| 化德县| 定南县| 红桥区| 建昌县| 河源市| 泽州县| 普宁市| 长乐市| 鹤壁市| 兴海县| 西乌珠穆沁旗| 海丰县| 平湖市| 成都市| 张掖市| 集贤县| 邓州市| 内黄县| 宁远县| 耿马| 汝阳县| 衡水市| 大理市| 天门市| 凤翔县| 搜索| 油尖旺区| 滁州市| 新野县| 阿拉善左旗| 孝义市| 麻栗坡县| 安陆市| 库伦旗| 昌都县| 元氏县| 桦川县| 公安县| 普定县| 成都市| 衡南县| 石狮市| 灵丘县| 裕民县| 建瓯市| 苍南县| 云梦县| 甘洛县| 呼和浩特市| 永兴县| 周至县| 旅游| 象州县| 筠连县| 岢岚县| 竹溪县| 米泉市| 刚察县| 栖霞市| 星座| 怀仁县| 龙江县| 灵璧县| 淮北市| 邯郸市| 萨嘎县| 永兴县| 浦北县| 嵩明县| 洮南市| 依兰县| 江达县| 若羌县| 淮滨县| 噶尔县| 蒲江县| 丹凤县| 临安市| 长岭县| 奇台县| 资源县| 昌平区| 富宁县| 连云港市| 吴堡县| 龙胜| 广汉市| 蒙阴县| 遵化市| 元江| 甘泉县| 盐津县| 华容县| 天镇县| 五家渠市| 富蕴县| 牡丹江市| 翼城县| 谷城县| 大埔县| 志丹县| 潜江市| 克什克腾旗| 西林县| 西乌珠穆沁旗| 山西省| 商河县| 迭部县| 盐津县| 虹口区| 泰和县| 容城县| 河北省| 东至县| 金秀| 北川| 巍山| 合山市| 调兵山市| 景泰县| 普兰县| 马尔康县| 迭部县| 梁河县| 台湾省| 东台市| 若羌县| 芜湖市| 景德镇市| 泌阳县| 丰台区| 衡南县| 柘荣县| 涡阳县| 垣曲县| 阜新|