我正在开发一个小项目,试图学习backbone.js,并且我正在使用AMD(教程中推荐)。我有一个“运动员控制”的 subview ,基本上是我计划在其他页面/ View 上重用的 View 。 subview (AthleteView) 上的点击事件不会触发。
AthleteView 呈现在 TimerView 内的 div 中,而 TimerView 则呈现在索引页上 id 为“page”的 div 中。我已将所有内容包含在下面,因为我怀疑我的设置方式可能是问题所在。
主视图:
define([
'jquery',
'underscore',
'backbone',
'views/SettingsView',
'views/AthleteControlView',
'text!templates/timerTemplate.html',
'timer'
], function($, _, Backbone, SettingsView, AthleteView, timerTemplate){
var TimerView = Backbone.View.extend({
el: $("#page"),
render: function(){
this.$el.html(timerTemplate);
var settingsView = new SettingsView();
settingsView.render();
var athleteView = new AthleteView();
athleteView.render();
console.log('rendered Timer');
}
});
return TimerView;
});
subview :
define([
'jquery',
'underscore',
'backbone',
'text!templates/AthleteControlTemplate.html',
'jqueryui'
], function($, _, Backbone, keypadTemplate){
var AthleteView = Backbone.View.extend({
el: $("#AthleteControl"),
events: {
'click': 'clickHandler'
},
render: function(){
$("#AthleteControl").html(keypadTemplate);
console.log('rendered AthleteControl');
},
clickHandler: function()
{
alert('click');
console.log('click');
}
});
return AthleteView;
});
路由器.JS
define([
'jquery',
'underscore',
'backbone',
'views/TimerView'
], function($, _, Backbone, TimerView) {
var AppRouter = Backbone.Router.extend({
routes: {
'*actions': 'defaultAction'
}
});
var initialize = function(){
var app_router = new AppRouter;
app_router.on('route:defaultAction', function (actions) {
var timerView = new TimerView();
timerView.render();
});
Backbone.history.start();
};
return {
initialize: initialize
};
});
索引.html
<html>
<head>
<script data-main="js/main" src="js/libs/require/require.js"></script>
</head>
<body>
<div id="page">
Loading....
</div>
<div id="footer"></div>
</div>
</body>
</html>
计时器模板:
<div class = "Controls">
<button id="Start">Start</button>
<button id="Stop">Stop</button>
<button id="Reset">Reset</button>
</div>
<div id="AthleteControl"></div>
最佳答案
所以id="AthleteControl"
元素来自内部timerTemplate.html
。这意味着$('#AthleteControl")
执行此代码时不会找到任何内容:
var AthleteView = Backbone.View.extend({
el: $("#AthleteControl"),
这意味着AthleteView
最终的行为就像你说的:
var AthleteView = Backbone.View.extend({
el: undefined,
如果不指定 View 的el
明确地,该 View 将创建一个空的 <div>
作为el
。诸如此类:
el: $("some-selector")
由于时间问题,几乎总是出现错误。相反,只需使用选择器字符串并让 Backbone 在需要时将其转换为 DOM 节点即可:
el: "some-selector"
快速修复应该是取消 jQuery el
s:
el: '#page'
el: '#AthleteControl'
<小时/>
就“让 View 创建自己的 el
”而言,您可以让 View 创建自己的 DOM 节点来用作它们的 el
。而不是尝试将 View 绑定(bind)到 el
已在页面上的 s。这种方法:
- 让您的观点更加独立。
- 随着应用程序变得越来越大并涉及更多 View ,有助于减少事件绑定(bind)冲突。
- 有助于减少内存泄漏,因为应用程序运行时每个 View 都有一个 DOM 节点(反之亦然)。
- 删除 View 很简单
view.remove()
调用而不是手动清理事件绑定(bind)和 HTML。如果您有 subview ,那么您将覆盖remove
您认为调用remove
在链接到默认remove
之前在 subview 上实现。
这种方法(为了清楚起见,没有 AMD/require.js 的东西)看起来更像下面这样。
HTML:
<script id="timerTemplate" type="text/x-underscore">
<div class="Controls">
<button id="Start">Start</button>
<button id="Stop">Stop</button>
<button id="Reset">Reset</button>
</div>
</script>
<div id="page">
</div>
JavaScript:
var AthleteView = Backbone.View.extend({
id: 'AthleteControl',
render: function() {
this.$el.html('Athlete control stuff goes here.');
return this; // This is standard practice, you'll see why below.
}
});
var TimerView = Backbone.View.extend({
render: function () {
var tmpl = _.template($('#timerTemplate').html());
this.$el.html(tmpl());
var athleteView = new AthleteView();
this.$el.append(athleteView.render().el);
return this;
}
});
var timer_view = new TimerView;
$('#page').html(timer_view.render().el);
注意 return this
在 render
方法并注意如何this.$el.html
和this.$el.append
用于构建和组合 View 。
关于javascript - subview 中的事件未触发 - Backbone.js,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24529238/