子视图中的事件未触发 - Backbone.js

时间:2014-07-02 10:49:59

标签: javascript events backbone.js view amd

我正在开发一个小项目,试图学习backbone.js和我使用AMD(在教程中推荐)。我有一个"运动员控制"的孩子视图,基本上是我打算在其他页面/视图上重复使用的视图。子视图(AthleteView)上的click事件不会触发。

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;

});

子视图:

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;

});

ROUTER.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
  };
});

的index.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>

2 个答案:

答案 0 :(得分:2)

因此id="AthleteControl"元素来自timerTemplate.html内部。这意味着$('#AthleteControl")在执行此代码时无法找到任何内容:

var AthleteView = Backbone.View.extend({
  el: $("#AthleteControl"),

这意味着AthleteView最终表现得好像你说的那样:

var AthleteView = Backbone.View.extend({
  el: undefined,

如果您未明确指定视图el,则视图会创建一个空<div>作为el。比如:

el: $("some-selector")
由于时间问题,

几乎总是一个错误。相反,只需使用选择器字符串,让Backbone在需要时将其转换为DOM节点:

el: "some-selector"

快速修复应该是取消jQuery el s:

el: '#page'

el: '#AthleteControl'

至于&#34;让视图创建自己的el s&#34;关注的是,您让视图创建自己的DOM节点以用作el,而不是尝试将视图绑定到页面上已有的el。这种方法:

  1. 让您的观点更加独立。
  2. 帮助减少事件绑定冲突,因为您的应用程序变得更大并且涉及更多视图。
  3. 帮助减少内存泄漏,因为每个视图在应用程序运行时都有一个DOM节点(反之亦然)。
  4. 删除视图是一种简单的view.remove()调用,而不是手动清理事件绑定和HTML。如果您有子视图,那么您在视图中覆盖remove,以便在链接到默认remove实施之前调用子视图上的remove
  5. 这种方法(为了清晰起见没有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.htmlthis.$el.append如何用于构建和组合视图。

    演示:http://jsfiddle.net/ambiguous/r4tsA/1/

答案 1 :(得分:-1)

要将事件绑定到操作,您需要指定哪个元素正在侦听哪个事件,例如

.., var AthleteView = Backbone.View.extend({
..
events: {
  'click button.btn': 'doSomething'
},
..
doSomething: function(e) {
  // code goes here
},
..