在 Backbone 中捕获滚动事件
Capture scroll event in Backbone
我有一个 Backbone.Marionette 项目视图。它呈现项目列表。每次有人滚动列表时,我都想听 scoll 事件。我认为这会起作用:
events: {
'scroll ul': 'filterInteraction'
},
filterInteraction: function(){
console.log('in filterInteraction ');
}
但是它没有捕获滚动事件。但是,当我这样做时:
onRender: function() {
this.$el.find('ul').on( 'scroll', function(){
console.log('scroll event captured'):
});
}
这将捕获滚动事件。有什么不同?两者似乎都在做同样的事情...
使用 onRender,您在每次渲染时设置事件,这是我看到的唯一区别。所以在我看来第一个解决方案会有更好的性能。
正如 anonymousday 所说,第一个选项是实施事件委托,这意味着 事件委托允许我们将单个事件侦听器附加到父元素,它将为匹配选择器的所有后代触发, 这些后代是现在存在还是将来添加。
http://learn.jquery.com/events/event-delegation/
我们有 4 个事件处理程序:
- 滚动
- 对于根 div : el
- 对于 ul
- 点击
- 对于根 div : el
- 对于 ul
'click' 事件冒泡所以在事件延迟中 div #root 接收它并可以处理它,但是滚动事件不冒泡所以我们不能从 #root 处理它div
在下一个示例中,我们对每个事件使用相同的代码。
如果我们点击 'ul' 我们有一个日志 click for ul
和一个日志 click for #root
因为点击事件'bubble'/爬上DOM树直到#root.
如果我们在#root 上滚动,我们有一个日志 scroll for root
因为我们直接从它捕获事件。
但是我们不能使用事件委托来处理来自 ul 的滚动,因为滚动事件不会 'bubble' / 爬上 DOM 树。
var dbg = $('#dbg')
var log = function(val){
dbg.append('<div>' + val + '</div>')
.scrollTop(99999);
};
$('button').click(function(){dbg.empty() });
var i=0;
var MyView = Backbone.View.extend({
events : {
'click' : 'elClick' ,
'scroll' :'elScroll' ,
'click ul' : 'ulClick' ,
'scroll ul' :'ulScroll' ,
} ,
elScroll : function(){ log('scroll for #root : ' + (i++)); } ,
ulScroll : function(){ log('scroll for ul : ' + (i++)); } ,
elClick : function(){ log('clicked on #root : ' + (i++)); } ,
ulClick : function(){ log('clicked on ul : ' + (i++)); } ,
});
myView = new MyView({el : $('#root') });
#dbg{
position: aboslute;
border : solid 1px #EEE;
top : 0;
left : 0;
right :0;
height : 150px;
min-height : 150px;
overflow : auto;
bottom : auto;
}
#dbg:hover{
bottom : 0;
height : auto;
}
#root{
position: aboslute;
border : solid 1px #EEE;
top : 30px;
left : 0;
right :0;
height : 150px;
overflow : auto
}
ul,li {
border:solid 1px #CCC;
list-style : none;
padding : 0px;
margin : 1px;
cursor : pointer;
}
ul{
height : 200px;
overflow : auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://underscorejs.org/underscore-min.js"></script>
<script src="http://backbonejs.org/backbone-min.js"></script>
<div id='dbg'>debug : </div>
<div id='root'>
<ul>
<li>A</li>
<li>A</li>
<li>A</li>
<li>A</li>
<li>A</li>
<li>A</li>
<li>A</li>
<li>A</li>
<li>A</li>
<li>A</li>
<li>A</li>
<li>A</li>
<li>A</li>
<li>A</li>
<li>A</li>
<li>A</li>
<li>A</li>
<li>A</li>
<li>A</li>
<li>A</li>
<li>A</li>
<li>A</li>
<li>A</li>
<li>A</li>
<li>A</li>
<li>A</li>
<li>A</li>
<li>A</li>
<li>A</li>
<li>A</li>
<li>A</li>
<li>A</li>
</ul>
</div><button>clear debug</button>
我有一个 Backbone.Marionette 项目视图。它呈现项目列表。每次有人滚动列表时,我都想听 scoll 事件。我认为这会起作用:
events: {
'scroll ul': 'filterInteraction'
},
filterInteraction: function(){
console.log('in filterInteraction ');
}
但是它没有捕获滚动事件。但是,当我这样做时:
onRender: function() {
this.$el.find('ul').on( 'scroll', function(){
console.log('scroll event captured'):
});
}
这将捕获滚动事件。有什么不同?两者似乎都在做同样的事情...
使用 onRender,您在每次渲染时设置事件,这是我看到的唯一区别。所以在我看来第一个解决方案会有更好的性能。
正如 anonymousday 所说,第一个选项是实施事件委托,这意味着 事件委托允许我们将单个事件侦听器附加到父元素,它将为匹配选择器的所有后代触发, 这些后代是现在存在还是将来添加。 http://learn.jquery.com/events/event-delegation/
我们有 4 个事件处理程序:
- 滚动
- 对于根 div : el
- 对于 ul
- 点击
- 对于根 div : el
- 对于 ul
'click' 事件冒泡所以在事件延迟中 div #root 接收它并可以处理它,但是滚动事件不冒泡所以我们不能从 #root 处理它div
在下一个示例中,我们对每个事件使用相同的代码。
如果我们点击 'ul' 我们有一个日志 click for ul
和一个日志 click for #root
因为点击事件'bubble'/爬上DOM树直到#root.
如果我们在#root 上滚动,我们有一个日志 scroll for root
因为我们直接从它捕获事件。
但是我们不能使用事件委托来处理来自 ul 的滚动,因为滚动事件不会 'bubble' / 爬上 DOM 树。
var dbg = $('#dbg')
var log = function(val){
dbg.append('<div>' + val + '</div>')
.scrollTop(99999);
};
$('button').click(function(){dbg.empty() });
var i=0;
var MyView = Backbone.View.extend({
events : {
'click' : 'elClick' ,
'scroll' :'elScroll' ,
'click ul' : 'ulClick' ,
'scroll ul' :'ulScroll' ,
} ,
elScroll : function(){ log('scroll for #root : ' + (i++)); } ,
ulScroll : function(){ log('scroll for ul : ' + (i++)); } ,
elClick : function(){ log('clicked on #root : ' + (i++)); } ,
ulClick : function(){ log('clicked on ul : ' + (i++)); } ,
});
myView = new MyView({el : $('#root') });
#dbg{
position: aboslute;
border : solid 1px #EEE;
top : 0;
left : 0;
right :0;
height : 150px;
min-height : 150px;
overflow : auto;
bottom : auto;
}
#dbg:hover{
bottom : 0;
height : auto;
}
#root{
position: aboslute;
border : solid 1px #EEE;
top : 30px;
left : 0;
right :0;
height : 150px;
overflow : auto
}
ul,li {
border:solid 1px #CCC;
list-style : none;
padding : 0px;
margin : 1px;
cursor : pointer;
}
ul{
height : 200px;
overflow : auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://underscorejs.org/underscore-min.js"></script>
<script src="http://backbonejs.org/backbone-min.js"></script>
<div id='dbg'>debug : </div>
<div id='root'>
<ul>
<li>A</li>
<li>A</li>
<li>A</li>
<li>A</li>
<li>A</li>
<li>A</li>
<li>A</li>
<li>A</li>
<li>A</li>
<li>A</li>
<li>A</li>
<li>A</li>
<li>A</li>
<li>A</li>
<li>A</li>
<li>A</li>
<li>A</li>
<li>A</li>
<li>A</li>
<li>A</li>
<li>A</li>
<li>A</li>
<li>A</li>
<li>A</li>
<li>A</li>
<li>A</li>
<li>A</li>
<li>A</li>
<li>A</li>
<li>A</li>
<li>A</li>
<li>A</li>
</ul>
</div><button>clear debug</button>