Backbone: 两次实例化视图时重复事件

创建于 2012-02-05  ·  9评论  ·  资料来源: jashkenas/backbone

当我定义一个视图(通过 Backbone.View.extend)并实例化它两次(通过 new)时,当一个事件在每个 ivies 对象上发生一次时,它会被触发两次。

简短示例:

<html>
<head>
    <script type="text/javascript" src="js/jquery-1.7.1.js"></script>
    <script type="text/javascript" src="js/underscore-1.3.1.js"></script>
    <script type="text/javascript" src="js/backbone-0.9.1.js"></script>
</head>
<body>
    <div id="test"></div>
    <script type="text/javascript">
        testview = Backbone.View.extend ({
            el: '#test',
             events: {'click .test': 'doTest'},
             doTest: function() {alert('test')},
             render: function() {$('#test').append($('<a>').attr('href', '#').addClass('test').append('test'));}});
        view_one = new testview;
        view_two = new testview;
        view_one.render();
    </script>
    </body>
</html>

所有9条评论

出于好奇,你为什么要实例化它两次? 您是在移动视图中还是在视口中的第一个实例被另一个视图替换的地方,当用户返回到第一个视图时,您得到了双重绑定?

类似的东西。 我有一个主页视图,如果用户登录与否,它将调用不同的端点。 事件绑定用于登录/注销按钮。 两个视图都被实例化,但当时只有一个被渲染。 当他们登录或注销时,我会切换到相同的视图,但使用不同的模式。 希望这足够清楚。

我仍然不完全清楚,为什么您同时实例化了两个视图。 将两者绑定到 dom 中相同的预先存在的元素意味着会有双重事件。 这不是真正的错误,而只是事件和特别是事件委托的工作方式。

如果在预先存在的元素上实例化视图,则需要专门解除绑定这些事件,否则它们将持续存在,直到元素节点本身从 dom 中删除。

嗯,在初始化期间实例化两个视图似乎是个好主意,将它们绑定到 DOM 中的同一个根元素,然后根据登录模式渲染一个或另一个,并在渲染时替换另一个的元素。 我想有一个更好的方法来做到这一点,从你的评论。

当你需要它们时,我会实例化它们。 如果一个视图没有被使用,就没有必要让它占用内存并可能引入你所看到的副作用。

我倾向于不使用这种模式:

var View = Backbone.View.extend ({
    el: '#test',
    events: 
    {
        'click .test': 'onClick'
    },
    onClick: function(event) 
    { 
        ... 
    }
});

view = new View;
view.render();

但相反,我倾向于使用这种模式,正是为了避免导致事件重复的僵尸视图

var View = Backbone.View.extend ({
    events: 
    {
        'click .test': 'onClick'
    },
    onClick: function(event) 
    { 
        ... 
    }
});

view = new View;
$('#target').append(view.render().el);

我将使用您的第一个模式的唯一位置是在实例化 GUI 的应用程序的 Chrome 视图中:

var Application = Backbone.View.extend({
    el: '#wrapper',
    initialize: function (options)
    {
        this.render();
    }
)};

$(document).ready(function () {
    window.application = new Application();
});

同上@vincentbriglia所说的关于不定义el并让视图生成它自己的元素的内容。 我也有 95% 的时间这样做。 但是,如果您确实想定义el并在删除时清理事件,您可以定义自己的Backbone.View.destroy()方法,并为每个相应的on()定义一个.off() on()以及events: {}每个事件

例如:

var MyView = Backbone.View.extend({

  initialize: function() {
    this.model.on('change', this.render, this);
  },

  render: function() {
    return this;
  },

  destroy: function() {
    this.remove();
    this.model.off('change', this.render, this);
  }
})

谢谢@malandrew@vincentbriglia ,这真的

只是为了为后代更新这个......我在 View 类中添加了一个 destroy 方法,如下所示

           destroy: function() {
                this.undelegateEvents();
            }

然后,每当我实例化()时,我都会销毁当前视图(State.view)。

此页面是否有帮助?
0 / 5 - 0 等级