jquery的bind与on和live的使用

  • 使用​​.bind()​​方法非常浪费性能因为它把同一个事件处理函数附加到了每一个匹配的元素上
  • 你应该停止使用​​.live()​​方法因为它被弃用了同时也会带来很多问题
  • 使用​​.delegate()​​方法会给你带来很多好处当你需要解决一些性能上的问题和对动态添加的元素作出处理
  • 新的​​.on()​​​方法其实就是模拟​​.bind()​​​ , ​​.live() ​​​和​​.delegate()​​实现的语法糖,具体取决于你如何调用它

bind绑定dom元素

使用 .bind()时,选择器匹配的元素会附加一个事件处理函数,而以后再添加的元素则不会有。为此需要再使用一次 .bind() 才行。

//bind 为每个匹配元素绑定事件处理函数,绑定多个用{}。
$("p").bind("click", function(){
alert( $(this).text() );
});
$(menuF).bind({
"mouseover":function () {
$(menuS).parent().removeClass("hide");
},"mouseout":function () {
$(menuS).parent().addClass("hide");
}
});
$("p").unbind( "click" ) //解绑一个事件

可以给这个元素绑定一个简单的click事件,点击了元素,就会弹出一个警告框 。然后又有另一个元素添加进来了。$('body').append(' Another target '); 尽管这个新的元素也能够匹配选择器"#my-selector" ,但是由于这个元素是在调用 .bind() 之后添加的,所以点击这个元素不会有任何效果。

$('#my-selector').bind('click', function() {
$(this).unbind('click');
alert('Clicked and unbound!');
});

bind()和unbind()提供了事件的绑定和取消机制,既可以绑定html默认支持的事件,也能够绑定自定义的事件。

$("#btnConfirm").bind('click',function(){
debugger;
var $dg = $("#dglist");
var rows = $dg.datagrid("getSelections");
var renderSelectObj = parent.renderSelector;
var _datas = [];
for(var i=0,len=rows.length; i<len; i++){
var dataItem = {};
dataItem.code = rows[i].id;
dataItem.name = rows[i].userName;
dataItem.address = rows[i].address;
dataItem.headPerson= rows[i].headPerson;
dataItem.headPersonPhone= rows[i].headPersonPhone;
dataItem.customerType= rows[i].customerType;
_datas.push(dataItem);
}
renderSelectObj.selectResultAfterCallback(_datas);
});

jquery的bind与on和live的使用_事件处理

$("input[name='" + _keys[0] +"']").parent().parent().find("button").unbind('click').bind('click', function(){
debugger;
var action = "_self." + $(this).attr("action");
eval(action);
});

jquery的bind与on和live的使用_选择器_02

使用bind一次绑定多个事件和处理函数。

如果多个事件需要注册相同的处理函数,那么可以使用如下代码进行简化(事件名称使用空格分隔):

$("#button1").bind("mousedown mouseup",function(){  
console.log(11);
});

如果每个事件的处理函数不同,那么可以使用如下的方式(json对象):

$("#button1").bind(  
{
"mousedown":function(){
console.log("mousedown");
},
"mouseup":function(){
console.log("mouseup");
}
}
);

unbind用来取消之前通过bind绑定的事件处理函数,总的来说有三种形式:取消所有事件、取消某种类型的事件、取消某种类型下的某个事件处理函数。

$("#button1").bind("click",func1);   
$("#button1").bind("click",func2);

// try to cancel function2
$("#button1").unbind("click",func2);

function func1()
{
console.log("click1");
}

function func2()
{
console.log("click2");
}

$("#button1").unbind():取消button1上所有已经绑定的事件处理函数。

$("#button1").unbind("click"):只取消button1上绑定的click类型的事件处理函数。

绑定匿名函数,点击时候执行函数体

$("#listAdd").bind("click", function() {
var gfyId=$("#gfyId").val();
if(gfyId==null||gfyId==''){
$Core.UI.message.error("请先选择用户");
return false;
}

if(flag){
$("#listAdd").gridselect({
title:'设备信息',
dialogWidth: '600', //窗口宽度 默认值600
dialogHeight: "400",//窗口高度 默认值 70%
searchFields: [ //搜索条件
{
name: "deviceName", //separator 指定后会换行显示
text: "设备名称",
type: "textbox", //控件类型 只支持 简单的表单控件 textbox my97 combobox 等简单控件 如果条件过多 可以增加 separator 换行显示
//url: "system/dic/getDicByCode/material_type", //字典获取路径
width: '', //宽度
querytype: "like",
//hidden: true, //是否隐藏域 默认否
value: '' //默认值
},
{
name: "gfy", //separator 指定后会换行显示
text: "",
type: "textbox", //控件类型 只支持 简单的表单控件 textbox my97 combobox 等简单控件 如果条件过多 可以增加 separator 换行显示
//url: "system/dic/getDicByCode/material_type", //字典获取路径
width: '', //宽度
querytype: "eq",
hidden: true, //是否隐藏域 默认否
value: $("#gfyId").val() //默认值
},
{
name: "deviceState", //separator 指定后会换行显示
text: "状态",
type: "textbox", //控件类型 只支持 简单的表单控件 textbox my97 combobox 等简单控件 如果条件过多 可以增加 separator 换行显示
//url: "system/dic/getDicByCode/material_type", //字典获取路径
width: '', //宽度
querytype: "like",
hidden: true, //是否隐藏域 默认否
value: 1 //默认值
}

],
dgOpts: { //datagrid 参数
url: 'security/deviceuser/query',
/* queryParams: {
qqq : '[{"name":"gfy","value":"'+$("#gfyId").val()+'","type":"like"}]',
d:'fff'
},*/
/*onBeforeLoad:function(paras){
paras.querystra +="&id="+$("#gfyId").val();
},*/
columns: [[
{ title: '设备名称', field: 'deviceName', align: 'center', sortable: false,formatter:function (value,row,index) {
return $Core.DicCache.get("installdevName")[value];
} },
{ title: '设备编号', field: 'deviceNumber', align: 'center', sortable: false },
{ title: '单位', field: 'company', align: 'center', sortable: false},
{ title: '数量', field: 'number', align: 'center', sortable: false },
]]
},
//选择一行时 被调用 return false 不会关掉窗口
onSelect: function (index, row) {
var materialId = row.materialId;
var isAppend = true;
$.each($("#dglist2").datagrid("getRows"), function (j,k) {
if (k.userDeviceId==userDeviceId) {
isAppend = false;
}
});
if (isAppend) {
$("#dglist2").datagrid("appendRow", row);
}
return false;},
onClear: function () { //点击清空按钮时被调用

}
});
flag = false;
}
$("#listAdd").gridselect("show");

});

 

live()事件

live方法是固定把事件都绑定在了document上,而delegate 把事件绑定了提供的父元素上

然后再点击新增的元素,他依然能够触发事件处理函数。 

$('.clickme').live('click', function() {
alert("Live handler called.");
});

然后再添加一个新元素:

$('body').append('
Another target
');

处理机制是先通过检测事件对象的target 来确定是不是需要继续。这个测试是通过检测 $(event.target).closest('.clickme')能否找到匹配的元素来实现的。

当一个事件处理函数用 .live()绑定后,要停止执行其他的事件处理函数,那么这个函数必须返回 false。 仅仅调用 .stopPropagation()无法实现这个目的。

$("a").live("click", function() { return false; });//阻止默认事件行为和事件冒泡,返回false

$("a").live("click", function(event){
event.preventDefault();
}); //仅仅阻止默认事件行为

 

delegate()

与bind 不同的是当时间发生时才去临时绑定。delegate()则是更精确的小范围使用事件代理,性能优于.live()

$("p").delegate("click",function(){
do something...
});

$("p").undelegate();    //p元素删除由 delegate() 方法添加的所有事件
$("p").undelegate("click") //从p元素删除由 delegate() 方法添加的所有click事件

delegate减少了冒泡次数,效率会更高些

live方法将与事件处理函数关联的选择器和事件信息一起附加到文档的根级元素(即document)。通过将事件信息注册到document上,这个事件处理函数将允许所有冒泡到document的事件调用它(例如委托型、传播型事件)。一旦有一个事件冒泡到document元素上,Jquery会根据选择器或者事件的元数据来决定哪一个事件处理函数应该被调用,如果这个事件处理函数存在的话。

  • 这个方法在Jquery 1.7以后的版本被弃用了,你应该在你的代码里逐步放弃使用它
  • 使用 ​​event.stopPropogation() ​​方法将会没用,因为事件总是已经被委托到了document元素上
  • 因为所有的选择器或者事件信息都被附加到document元素上了,所以一旦有一个事件要调用某个事件处理函数,Jquery会在一大堆储存的元数据中使用matchesSelector方法来决定哪一个事件处理函数将会被调用,如果这个函数有的话。
$( "#members li a" ).live( "click", function( e ) {} );

$( "#members" ).delegate( "li a", "click", function( e ) {} );

​.delegate()​​​方法十分强大。在上面这个例子中,与事件处理函数关联的选择器和事件信息将会被附加到( #members" )这个元素上。这样做比使用​​live()​​​高效多了,因为​​live()​​方法总是将与事件处理函数关联的选择器和事件信息附加到document元素上。

  • 你可以选择将选择器或者事件信息附加到指定的元素。
  • 匹配操作实际上在前面并没有执行,而是用来注册到指定的元素。
  • 链式操作可以得到正确的支持
  • Jquery仍然需要迭代这些选择器或者事件信息来匹配元素,不过因为你可以选择哪一个元素作为根元素,所以筛选的量会大幅减少
  • 因为这项技术使用了事件委托机制,它可以匹配到被动态地添加到DOM的元素
  • 你可以在文档加载完之前连接事件处理函数

在Jquery 1.7版本中​​.bind() ​​​, ​​.live() ​​​和​​.delegate()​​​方法只需要使用​​.on()​​​方法一种方式来调用它们。当然​​.unbind()​​​ ,​​ .die() ​​​和.​​undelegate()​​方法也一样。一下代码片段是从Jquery 1.7版本的源码中截

源码

bind: function( types, data, fn ) {
return this.on( types, null, data, fn );
},
unbind: function( types, fn ) {
return this.off( types, null, fn );
},

live: function( types, data, fn ) {
jQuery( this.context ).on( types, this.selector, data, fn );
return this;
},
die: function( types, fn ) {
jQuery( this.context ).off( types, this.selector || "**", fn );
return this;
},

delegate: function( selector, types, data, fn ) {
return this.on( types, selector, data, fn );
},
undelegate: function( selector, types, fn ) {
return arguments.length == 1 ?
this.off( selector, "**" ) :
this.off( types, selector, fn );
}

one事件只加载一次方法

$(xx).one("click",function(){...});只触发一次。

 

on与off替代bind 和unbind以及delegate

bind绑定click事件,数据是动态加载的数据多了有时候再次调用click事件却没法调用了。

var bindEvent = function() {
$(".demo").unbind("click").bind("click", function() {
//TODO
});
};

整合了之前的三种方式的新事件绑定机制。后面就用on与off代替bind与live事件

$("#btn").on("myClick", function (event, message1, message2) { //获取数据
$("#test").append("p" + message1 + message2 + "</p>");
});
$("#btn").trigger("myClick",["我的自定义","事件"]); //传递两个数据

等价于

$("#btn").bind("myClick", function (event, message1, message2) { //获取数据
$("#test").append("p" + message1 + message2 + "</p>");
});
$("#btn").trigger("myClick",["我的自定义","事件"]); //传递两个数据

同时给多个元素绑定一样的事件

$("ul li,div").on("click",function(){  
alert("不响应事件!");
})

同时给元素绑定多个事件 

$(".demonstrate").on({  
mouseover:function(){
$(this).addClass("over");
},
mouseout:function(){
$(this).removeClass("over");
}
},"ul li")

实现事件委托

父元素ul li 给目标元素.demostrate添加事件,事件委托的好处是,目标元素可以是之前页面不存在到,后来加上去的也可以。 只需要考虑一个父元素就可以,给父元素添加委托事件,不用考虑子元素的数量什么的。

$("ul li").on({
click:function(){
console.log('click','1111');
},
mouseover: function () {
console.log('mouseover','1111');
$(this).addClass("over");
},
mouseout: function () {
$(this).removeClass("over");
}
},".demostrate");

同时给元素解绑多个事件 

$("ul li,div").off("click") 

---------------------

$(".demonstrate").off("mouseover mouseout","ul li")

---------------------

$("ul li").off("click mouseover mouseout",".demostrate");

---------------------

如何使用​​.on()​​​方法决定了它如何调用其他方法。你可以认为​​.on()​​方法被具有不同签名的方法”重载“了,而这些方法实现了不同的事件绑定的连接方式。

/* Jquery的 .bind() , .live() 和 .delegate() 方法只需要使用`.on()`方法一种方式来调用它们 */

// Bind
$( "#members li a" ).on( "click", function( e ) {} );
$( "#members li a" ).bind( "click", function( e ) {} );

// Live
$( document ).on( "click", "#members li a", function( e ) {} );
$( "#members li a" ).live( "click", function( e ) {} );

// Delegate
$( "#members" ).on( "click", "li a", function( e ) {} );
$( "#members" ).delegate( "li a", "click", function( e ) {} );

有三个A标签,点击其中一个后添加on样式

<a href="javascript:void(0);" onclick="open('a');return false;" class="off">a</a>
<a href="javascript:void(0);" onclick="open('b');return false;" class="off">b</a>
<a href="javascript:void(0);" onclick="open('c');return false;" class="off">c</a>

$("a").parent().on("click", "a", function() {
$(this).addClass("on").siblings("a").removeClass("on");
});

如果有很多的临时变量,on可以给当前的临时对象保存一个事件

drawPoint.type["onClick"] = function(point, e){
Leak.showInfoWindow(point)
}

marker = new AMap.Marker(pointOpitons);
mPoint.marker = marker;
if(mPoint.type.onClick && $.isFunction(mPoint.type.onClick)) {

marker.on('click',function(e){

mPoint.type.onClick(e.target.getExtData(),null);
}); //点事件的获取
}

jquery的bind与on和live的使用_选择器_03

jquery的bind与on和live的使用_事件处理_04

jquery的bind与on和live的使用_事件处理_05

jquery的bind与on和live的使用_控件_06

jquery的bind与on和live的使用_控件_07

只能上传一张图片

$("#subjectSmallImage").mouseover(function(){
var tbodyLength = $(this).siblings().find("tbody[id='subjectSmallImage_list_table']").find("tr")
var flag = true;
if($(tbodyLength).length==0){
flag = false;
}

if(flag){
$(".layui-input-block button[id='subjectSmallImage']").off('click').on('click',a) }
if(!flag){
$(".layui-input-block button[id='subjectSmallImage']").off('click',a).on('click',upload);
$("#subjectSmallImage").trigger('click');
}

})

$("#subjectImage").mouseover(function(){
var tbodyLength = $(this).siblings().find("tbody[id='subjectImage_list_table']").find("tr")
var flag = true;
if($(tbodyLength).length==0){
flag = false;
}

if(flag){
$(".layui-input-block button[id='subjectImage']").off('click').on('click',a) }
if(!flag){
$(".layui-input-block button[id='subjectImage']").off('click',a).on('click',upload);
$("#subjectImage").trigger('click');
}

})

function a(){
layer.msg("附件仅能上传一个");
};
function upload(){

}