计划,每天学习两小时,坚持带来大改变。

Marionette:胜在内存管理(五)

前端开发 阿尤 2580浏览 0评论

除了缩减了view定义的代码,Marionette所有view中还有些先进的内存管理功能,使得view实例的清除工作和事件处理更容易了。

看下面的view实现:

var ZombieView = Backbone.View.extend({ template: '#my-view-template', initialize: function(){ // bind the model change to re-render this view this.model.on('change', this.render, this); }, render: function(){ // This alert is going to demonstrate a problem alert('We`re rendering the view'); } });

如果我们用相同的变量名称创建这个view的两个实例,然后修改model中的一个值,能看到几次警告框?

创建两个view实例

var myModel = new MyModel({ firstName: 'Jeremy', lastName: 'Ashkenas', email: '[email protected]' }); // create the first view instance var zombieView = new ZombieView({ model: myModel }) // create a second view instance, re-using // the same variable name to store it zombieView = new ZombieView({ model: myModel }) myModel.set('email', '[email protected]');

按常理,因为两个实例都用zombieView 变量名,所以view的第二个实例创建后,第一个实例立马就会落到作用域之外。Javascript可以通过垃圾收集把它清除掉,也就是说第一个view实例不再有用,也不会对模型的“change”事件作出响应。

但运行这段代码时,警告框还是出现了两次!

出现这种问题,是因为model事件绑定是在view的initialize 方法中。无论什么时候把this.render当做回调方法传给model的 on 事件绑定,model也会得到一个对view实例的直接引用。就是因为model中有对view实例的引用,所以即使换掉 zombieView变量引用的view实例,不再被 zombieView引用的view实例也不会落到作用域之外。前面说过了,model中还有对它的直接引用。

既然最初那个view还在作用域内,第二个view实例也在,两个实例自然都会对model中的数据修改做出响应。

解决这个问题很简单。只要在用完view后调用model上的off 方法,让这个事件绑定处于准关闭的状态就行。为此,要在view里加个close 方法。

增加close方法的View定义

var ZombieView = Backbone.View.extend({ template: '#my-view-template', initialize: function(){ // bind the model change to re-render this view this.model.on('change', this.render, this); }, close: function(){ this.model.off('change', this.render, this); }, render: function(){ // This alert is going to demonstrate a problem alert('We`re rendering the view'); } });

不再需要第一个实例后,只需在其上调用close方法就行,活着的view实例就只剩一个了。

close方法演示

var myModel = new MyModel({ firstName: 'Jeremy', lastName: 'Ashkenas', email: '[email protected]' }); // create the first view instance var zombieView = new ZombieView({ model: myModel }) zombieView.close(); // double-tap the zombie // create a second view instance, re-using // the same variable name to store it zombieView = new ZombieView({ model: myModel }) myModel.set('email', '[email protected]');

再运行代码,就只剩一个警告框了。

有了Marionette,我们就不用自己写代码关闭事件处理器了。

Marionette的内存管理

var ZombieView = Marionette.ItemView.extend({ template: '#my-view-template', initialize: function(){ // bind the model change to re-render this view this.bindTo(this.model, 'change', this.render, this); }, render: function(){ // This alert is going to demonstrate a problem alert('We`re rendering the view'); } });

注意上面的代码,我们用bindTo方法取代了on方法。这个方法在Marionette的EventBinder对象中定义,在所有view类型中都能用。 bindTo 的方法签名跟on方法差不多,只是把触发事件的对象不再是调用者,而是变成了方法的第一个参数。

Marionette的view中还有一个 close方法,用来'off'掉事件的绑定。用bindTo设置的事件绑定会被自动关闭。也就是说我们不用亲自定义,和调用 close 方法,只要用bindTo 方法设置事件绑定,我们就可以放宽心,事件绑定会被自动'off'掉,我们的views也不会变成僵尸。

但view上 close 方法的自动调用是怎么实现的呢?什么时候,以及在哪调用它呢?请看Marionette.Region - 这是负责管理每个view生命周期的对象。


转自:http://www.ituring.com.cn/article/31721

转载请注明:阿尤博客 » Marionette:胜在内存管理(五)

游客
发表我的评论 换个身份
取消评论

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
  • 验证码 (必填)点击刷新验证码