jquery原理与ajax基础系列(四)之事件相关

10 篇文章 0 订阅
9 篇文章 0 订阅

       主要是区别于原生js的异同点。

one.

你可以一直用原生的js来处理事件,但是你一定要记住jquery处理事件的最重要的一些特殊点:

1.同一个dom节点添加不同的事件,不会被覆盖。这是jquery重构事件的出发点。

2.由于上述第一点,一个dom节点对应多个事件,需要被管理。因此,与“on”对应的存在“off”。原生的js中没有同一个节点管理不同事件的需求,不存在"off"之类的,也没这个需求,比如不存在oDiv.offclick=function(){}..

3.组合拳(自定义新的事件)。他有两个不同的方向,一个方向是定义一个压根在现实世界里不存在的事件,常常与trigger联合起来使用自动触发,再给事件进行命名的时候随意性较大;另外一个方向是多个人协同工作的时候,不同的人给同一个DOM添加各自不同的事件,管理混乱的情况下尤其是在测试谁的代码问题的时候,使用称之为“事件命名空间”的技术(由于上述第一点的存在故而产生这种需求),它的在给事件进行命名的时候,都是在已有的现实中存在(如点击click,移入mouseover,移出mouseout)的,他的事件命名的格式形如:dom.on("click.lx",fn) &&dom.on("click.zly",fn) [分别代表代号为“lx”“zly”两个不同的人的命名空间]。无论是哪种的方向,都只能采用dom.on(eventName,fn)的形式而不能采用dom.click(fn)的形式,都常常与trigger联合起来使用。

 // 起作用的是“bb()”“"原生js的onmouseover"”.aa被bb覆盖。
                  // 原生的js中同一类型的事件会被覆盖,不同类型的事件会保留:
                  oDiv=document.getElementsByTagName("div")[0]
                  oDiv.onclick=aa;
                  oDiv.onclick=bb;
                  oDiv.onmouseover=function(){
                  alert("原生js的onmouseover")
                  }

                  // 居然不认可$("div")[0]
                  $("div")[0].click(aa) //失效?!最好不要用这种半原生的半jq的!
                  $("div").click(function() {
                        alert("第一种方式:dom.click(fn)")
                  })
                  $("div:eq(0)").on("click", function() {
                        alert("第二种方式dom.on(eventName,fn)")
                  })
                  $("div").eq(0).click(aa);
                  $("div").click(bb);
                  $("div").mouseover(function() {
                        alert("jquery的mouseover")
                  })

                  // 连些模式,移入点击都会触发aa()
                  $("div").on("click mouseover", aa)

                  // 需要被管理,因此出现off("eventName",fn)
                  $("div").off("mouseover", aa) //禁止$("div").mouseover(aa)的效果
                  $("div").off("mouseover") // 所有的“mouseover”事件都被禁止
                  $("div").off("mouseover click", aa) //禁止$("div").click(aa)和$("div").mouseover(aa)

 

two

事件冒泡  vs 阻止默认事件

jquery把两者都简化成“return false”了(write less ,do more)。

"return false"解决所有问题,尤其代码的记忆问题ev.stopPropagation/ev.preventDefault单词很难记啊!)

// 靠近20行的代码,阻止默认事件/阻止冒泡事件。
oDiv_f=document.getElementsByTagName("div")[0];
oDiv_son=document.getElementsByTagName("div")[1];
oDiv_f.onclick=father;
//冒泡
oDiv_son.onclick=son;
// 阻止冒泡,将son包含在另外一个新的函数中,ev为所有的事件函数都默认带有。
oDiv_son.onclick=function(ev){
son();
ev.stopPropagation(true);
};
oA=document.getElementsByTagName("a")[0];
oA.onclick=function(ev){
alert("本来跳转到“爱美句”的结果不跳转了")
ev.preventDefault(true);
}

oForm=document.getElementsByTagName("form")[0];
oForm.onclick=function(ev){
alert("本来跳转到“爱xuexi”的结果不跳转了")
ev.preventDefault(true);
}

// "return false"解决所有问题,尤其代码的记忆问题
// (ev.stopPropagation/ev.preventDefault单词很难记啊!)
// 不到10行的代码,“write less  do more!”
$(".father").click(father);
$(".son").click(function(){
alert(" “retrun false”阻止冒泡事件");
return false;
});
$("a").click(function(ev){
// 阻止a的默认跳转
return false;
})
$("form").click(function(ev){
// 阻止表单action的默认跳转
return false;
})

three.

在jquery中,都是通过on/off/trigger来控制dom的事件的开/关/自动运行的,因此,他们的代码的格式也及其的相似,可以统一的表达为:

DOM.on/off/trigger("eventName",fn)。fn在off/trigger可以省略。

trigger  vs  triggerHanddler:

trigger 不阻止冒泡不阻止默认事件。triggerHandller阻止冒泡阻止默认事件(可以想见源代码类似于上述two中的"return false"有无的区别)。但是对于特殊的标签"a",$("a").trigger("click")在jquery的源代码中做过了处理,无论是trigger还是triggerHandller都是不会跳转页面的【目的是为了防止篡改页面?安全考虑?】。如果确实有这个需要则需要手动修改html页面,将a标签中的内容包裹在span中,比如<a><span>a标签中的HTM内容</span></a>(也就是说,你要是想不通过点击自动跳转页面,光有修改js的权限还是不够的,你还得有修改html的权限,防止恶意篡改)。

four.

1.自定义现实中不存在的操作事件。

      function  father(){alert("father()")}
      function  son(){alert("son()")}
// myclickisnotreal  mymouseisnone都是在现实中不存在的操作
      $(".father").on("myclickisnotreal",father);
      $(".son").on("mymouseisnone",son);
// 不起作用,父节点不能使用子节点的自定义事件,不相干的节点不能调用该节点的自定义事件
      // $(".father").trigger("mymouseisnone")
      // $("span").trigger("mymouseisnone")
// 都起作用,即对于子节点而言,父节点/子节点自身带有的自定义事件都可以被.trigger()
$(".son").trigger("myclickisnotreal")
$(".son").trigger("mymouseisnone")

2.自定义现实中存在的操作事件,在存在的操作事件后加".人物名缩写/人物名"以示区别。比如dom.on("click.lx",fn) &&dom.on("click.zly",fn) [分别代表代号为“lx”“zly”两个不同的人的命名空间]。

$(".father").on("click",function(){
alert("我是你们爸爸!")
})
$(".son").on("click.lx",function(){
alert("没门牙的响哥")
return false
})
// 冒泡现象在这里(事件命名空间)神奇的不起作用了!
$(".son").on("click.zly",function(){
alert("伪娘燎原")
})
// 常常用于检测谁的代码出错了啊?!便于管理.
$(".son").trigger("click.zly")

总结如下:

1.无论是自定义事件还是自定义的“事件命名空间”,冒泡现象起作用与否主要看事件的名称是否完全一致

2.无论是自定义事件还是自定义的“事件命名空间”,两者都是与trigger有着广泛的联系!

five.

事件委托”是“事件捕获”的具体的应用。顶级的父类的事件通过“事件捕获”一级一级的传递给子类DOM节点,当子类节点暂时不存在或者不方便点击或者不方便获取 的时候,通过“事件委托”把当前节点所应该处理的“事件委托”给父类或者便于获取/点击的节点。尤其要注意原生js在jquery在这个领域上的比较!

一段原生的js的代码:

      <script>
// 点击子节点div1,div2以及之后新增的div3全部转化成点击父节点。
               window.onload = function(){
              let div = document.getElementById('div');
              div.addEventListener('click',function(e){
// 原生的js中是用 e.target 来标注鼠标点到的某一个具体的DOM节点元素上的。
// 而jquery中非常复杂的委托(delegate)事件需要用在这里不露痕迹的
// 似乎不费劲的显示了出来:
//(jq)需要被委托的节点.delegate(寻求委托的DOM节点,"eventName(click,mouseouver...)",fn)
//(原生js) 需要被委托的节点.addEventListener(eventName,fn(e){e.target})
                  console.log(e.target)
              })
              let div3 = document.createElement('div');
              div3.setAttribute('class','div3')
              div3.innerHTML = 'div3';
              div.appendChild(div3)
          }
      </script>
      <body>
          <div id="div">
              <div class="div1">div1</div>
              <div class="div2">div2</div>
          </div>
      </body>

jquery:

$("ul").delegate("li","click",function(ev){
console.log(ev.target);
// 区别于原生的js,这里的this代表的是“li”,而非“谁的函数this就是谁”的"ul".
// 注:jquey在"this"重新定向的问题上显然是经过加工和再处理了。
console.log(this.innerHTML)
// 这里的this只是一个dom对象还不是一个jquery对象,还需要将其包装成jquery对象,$(this)
console.log($(this).html())
})

一半原生js一半jquery处理的委托:

$("ul").click(function(ev){
console.log(ev.target);
console.log(ev.target.innerHTML);
console.log($(ev.target).html());
})

总结:

1.原生的js在处理“事件委托”的时候,是直接把子节点的点击换成父节点的点击,并没有刻意的使用类似于jquery“.delegate()”之类的函数。
(jquery格式:)需要被委托的节点.delegate(寻求委托的子节点,"eventName",fn)

  (原生js:) 需要被委托的节点.addEventListener(eventName,fn(e){e.target})

2.$(function(){})或者window.οnlοad=fn来说,加载的只是已经写好的固定的H5页面,对于新增的节点,是无法操作的。新增的节点只有2个操作:添加,移除。对应于父节点.append(子节点) / 子节点.remove()。因此在需要操作这类特殊的新增加的节点的时候,需要考虑用“事件委托”/“事件捕获”:

//注册页面的时候弹出窗口。$mask(“蒙版”) 和 $(".login")【登陆时候弹出的窗口】都是新增加的节点。

//这类特殊的节点只有append()和remove()可以使用
$mask.remove();

//语法上没有错误,所以下面的代码不会有任何的效果,但是也不会报错。$(".login")未通过$(fn)加载进
//来,要牢记这一点,避免这种情况,因为不报错很难查找。目前技术暂时只能放弃这种使用,以后有更好的
//技术能直接使用也说不准。
 $(".login").attr("display","none")

six(复习)

 div.addEventListener('click',fn,false/true),关于addEventListener的使用范围:

1.dom.addEventListener("eventName",fn,ture/false) 增加的同一个类型的事件不会被覆盖,是原生js自带的事件的加强版。

2.dom.addEventListener("eventName",fn,ture/false),第三个参数“true/false”可以不写,不写的时候默认为“false”.当写“true”的时候表示阻止冒泡事件但是对于a标签form标签的默认事件无能为力。

3.当dom节点是window的时候,window.addEventListener("load",fn)----回到开篇介绍jquery性能的时候讲到过这一点。用这种方式不会被覆盖,她的价值等于$(function(){})

seven

        在jquery源代码中,mouseenter/mouseleave作为进阶版本的mouseover/mouseout 事件,通过在父节点的所有的子节点中遍历增加“return false”,而避免了子节点捕获/获取父节点的事件。因此,这种格式更合适实际的生产需要。要补充说明的是,上述情况只适用于子类的“面积”完全在父类的掌控中的时候。当子类的设置的面积大于父类的时候,在父类的掌控中的面积避免了“事件冒泡”;但是多余的突出面积依然存在事件捕获/事件冒泡,点击突出面积依然会有父类事件的弹出!

另外要注意的是hover是mouseenter/mouseleave的改写,也是通过增加“return false”避免事件冒泡。

$(".father").mouseenter(function(){
console.log("father  mouseenter")
})
$(".father").mouseleave(function(){
      console.log("father mouseleave")
})

$(".son").mouseenter(function(){
console.log("son  mouseenter")
})
$(".son").mouseleave(function(){
      console.log("son mouseleave")
})

$(".father").hover(function(){
// 这里是移入后的函数
console.log("hover 移入")
},function(){
// 这里是移出后的函数
console.log("hover 移出")
})
$(".son").hover(function(){
console.log("hover的两个函数相同的时候可以省略成一个!呵呵!")
})

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值