Home  >  Q&A  >  body text

javascript - 关于backbone的问题

最近简单用了下backbone,由于backbone不是很熟悉,所以用起来感觉比较别扭。所以把代码发上来想请各位高手看一下,项目后台使用的是dwr。比如我做了一个简单的例子,点击不同的tab后显示不同的列表,我把他们抽象为两套model和view。Model1和View1代表tab的model和view,Model2和View2代表list的model和view。代码如下:

Model.js

var M1=Bckbone.Model.extend({
     initialize:function(){
         this.getData({实例化时传入的参数});
     },
    data:null,
    promise:$.Deferred(),
    getData:function(a,b){
        var tThis=this;
        BaseController.getTabs(a,b,function(data){
            if(data && data.length){
                tThis.data=data;
            }else{
                tThis.data=[];
            }
            tThis.promise.resolve(tThis);            //向view传model
        });
    }
});
var M2=Bckbone.Model.extend({
     initialize:function(){
         this.getData({实例化时传入的参数});
     },
    data:null,
    promise:$.Deferred(),
    getData:function(a,b){
        var tThis=this;
        BaseController.getListsFromTabId(a,b,function(data){
            if(data && data.length){
                tThis.data=data;
            }else{
                tThis.data=[];
            }
            tThis.promise.resolve(tThis);            //向view传model
        });
    }
});

View.js

var View1= Backbone.View.extend({
    el:'#id1',
     initialize:function(model){
         this.model=model;
         this.render(model);
     },
     model:null,
     render:function(data){
         var ele=$(this.$el);
         var html='';
         ele.find("ul").empty();
         /*
         *拼接html并显示 
         */
     },
     events:{
        "click": //点击事件,点击后调用model2的getData方法,更新model2,并重渲染view2
     }
});
var View2= Backbone.View.extend({
    el:'#id2',
     initialize:function(model){
         this.model=model;
         this.render(model);
     },
     model:null,
     render:function(data){
         var ele=$(this.$el);
         var html='';
         ele.find("ul").empty();
         /*
         *拼接html并显示 
         */
     },
     events:{
        click:
     }
});

main.js

var M1= new Model1({..});
M1.promise.then(function(){
    var V1=new View1(M1);
})
.then(function(){
    var M2=new Model2({...})
    return M2.promise()
})
.then(function(){
    var v2=new View2()
})

问题:
1.类似这样的写法该如何实现view与下一个model间的通信?比如最常见的点击tab后切换列表显示,
如果我现在要在view1里面加入一个点击事件,点击后更新model2的data,并再重新渲染view2,这个该怎么做到呢?如果是重新new 一个Model2()会不会造成内存泄露?

天蓬老师天蓬老师2772 days ago479

reply all(1)I'll reply

  • 高洛峰

    高洛峰2017-04-10 16:42:16

    不是内存泄露的问题,楼主源码对 Model 的定义就有些许问题了,在 Model.js 中定义了 M1M2 两个模型,在 main.js 又将 M1M2 覆盖掉了。

    不过,假设楼主源码没有问题,M1 能够被正常初始化,但会有一个严重的问题,所有的 M1 Model 都会指向同一个 promise,所以最好是在 initialize 的时候才去指定 promise 属性。

    比如 M1 这坨源码:

    var M1 = Backbone.Model.extend({
        initialize: function() {
            this.promise = $.Deferred();
            
            this.fetch(/* 此处应有参数 */);
        },
        
        //  fetch 函数是 Backbone 推荐的 RESTFUL 风格的 GET
        fetch: function(a, b) {
            var self = this;
            BaseController.getTabs(a, b, function(data) {
                self.data = data && data.length ? data : [];
                self.promise.resolve(self);
            });
        }
    });

    然后 View.js 中,可以使用 listenTo() 方法去监听 Model 的改动,然后去触发一个指定的方法,View1 修改如下:

    var View1 = Backbone.View.extend({
        el: '#id1',
        
        events: {
            'click': 'fetchModelData'
        },
        
        //  没有必要传入 model, 因为在初始化 View 的时候传入 
        //  { model: model } Backbone 会自动将 model 填入
        initialize: function() {
            this.listenTo(this.model, 'change', this.render);
        },
        
        render: function() {
            //  this.$el 本身就是一个 jQuery 对象,不需要再传入 $() 包装
            $('ul', this.$el).empty();
            
            //  插♂入 HTML
        },
        
        fetchModelData: function() {
            this.model.fetch(/* 此处应有参数 */);
        }
    });

    综上,其实 Model 也没有必要插入一个 promise 去执行 View 的初始化操作,将视图建立出来后才交互数据,数据被写入模型之中时会触发 change 事件,因为视图有监听 change 事件,所以也触发了 render() 方法渲染视图。故模型,视图还有初始化视图可以修改如下:

    var M1 = Backbone.Model.extend({
        
        //  fetch 函数是 Backbone 推荐的 RESTFUL 风格的 GET
        fetch: function(a, b) {
            var self = this;
            BaseController.getTabs(a, b, function(data) {
                self.data = data && data.length ? data : [];
                self.promise.resolve(self);
            });
        }
    });
    
    var View1 = Backbone.View.extend({
        el: '#id1',
        
        events: {
            'click': 'fetchModelData'
        },
        
        //  没有必要传入 model, 因为在初始化 View 的时候传入 
        //  { model: model } Backbone 会自动将 model 填入
        initialize: function() {
            this.listenTo(this.model, 'change', this.render);
            this.fetchModelData();
        },
        
        render: function() {
            //  this.$el 本身就是一个 jQuery 对象,不需要再传入 $() 包装
            $('ul', this.$el).empty();
            
            //  插♂入 HTML
        },
        
        fetchModelData: function() {
            this.model.fetch(/* 此处应有参数 */);
        }
    });
    
    var v1 = new View1({ model: new M1() });

    reply
    0
  • Cancelreply