2012-02-13 25 views
9

tôi có một cái nhìn xương sống mà các cuộc gọi đến một tiểu-view:Thuộc tính truy cập của Backbone Chánh Xem

lr.MapView = Backbone.View.extend({ 
    el: $('#map'), 
    foo: "bar", 
    initialize: function() { 
     var that = this; 
     _.bindAll(this, "render", "addAllEvents", "addOneEvent"); 
     this.collection = new lr.Events(); 
     this.collection.fetch({ 
     success: function(resp) { 
      that.render(); 
      that.addAllEvents(); 
     } 
     }); 
    }, 

    addAllEvents: function() { 
     this.collection.each(this.addOneEvent); 
    }, 

    addOneEvent: function(e) { 
     var ev = new lr.EventView({ 
     model: e 
     }); 
    }, 

    render: function() { 
    } 
    }); 

Đây là sub-view:

lr.EventView = Backbone.View.extend({ 
    initialize: function() { 
     _.bindAll(this, "render"); 
     console.log(lr.MapView.foo); // will console.log 'undefined' 
    }, 
    render: function() { 
    } 
    }); 

Tôi muốn để có thể để truy cập các thuộc tính chế độ xem cha mẹ trong chế độ xem phụ nhưng không hoạt động với mã ở trên. Ví dụ, làm thế nào tôi có thể truy cập biến 'foo' trong chế độ xem phụ?

Trả lời

10

lr.MapView là một "lớp học", tất cả những gì Backbone.View.extend xây dựng sẽ ở số lr.MapView.prototype, không phải trong lr.MapView. Chạy với giao diện điều khiển mở và bạn sẽ thấy whats going on:

var MapView = Backbone.View.extend({ foo: 'bar' }); 
console.log(MapView); 
console.log(MapView.prototype); 
console.log(MapView.prototype.foo); 

Demo: http://jsfiddle.net/ambiguous/DnvR5/

Nếu bạn chỉ sẽ có một MapView duy nhất sau đó bạn có thể tham khảo lr.MapView.prototype.foo ở khắp mọi nơi:

initialize: function() { 
    _.bindAll(this, "render"); 
    console.log(lr.MapView.prototype.foo); 
} 

Lưu ý rằng ở khắp mọi nơi bao gồm trong lr.MapView trường để foo của bạn sẽ đóng vai trò như một "biến lớp" từ phi nguyên mẫu dựa trên ngôn ngữ OO.

Cách đúng để làm điều này là sử dụng một biến Ví dụ cho foo và truyền thể hiện quan điểm cha mẹ đến trường tiểu xem khi họ đang tạo ra:

// In MapView 
addOneEvent: function(e) { 
    var ev = new lr.EventView({ 
    model: e, 
    parent: this 
    }); 
} 

// In EventView 
initialize: function(options) { 
    _.bindAll(this, "render"); 
    this.parent = options.parent; // Or use this.options.parent everywhere. 
    console.log(this.parent.foo); 
} 

Hoặc tốt hơn, thêm một phương pháp accessor để MapView:

_foo: 'bar', 
foo: function() { return this._foo } 

và sử dụng phương pháp trong EventView:

initialize: function(options) { 
    // ... 
    console.log(this.parent.foo()); 
} 

Đóng gói và giao diện thích hợp là một ý tưởng hay ngay cả trong JavaScript.

+0

Câu trả lời tuyệt vời, cảm ơn bạn. Tại sao phương pháp tiếp cận phương pháp tiếp cận thích hợp với phương án thay thế khác mà bạn đề cập? – AdamVickers

+2

@AdamVickers: Sự hiện diện của một tín hiệu truy nhập tới thế giới bên ngoài mà 'foo()' là một phần của giao diện công khai của MapView và việc thiếu một mutator chỉ ra rằng người ngoài không phải thay đổi nó. –

0

Chỉ cần một đoán, nhưng bạn có thể thử một cái gì đó như thế này trong MapView:

addOneEvent: function(e) { 
    var that = this, 
     ev = new lr.EventView({ 
      model: e, 
      parentView = that 
     }); 
} 

Và sau đó truy cập vào nó như thế này:

lr.EventView = Backbone.View.extend({ 
    initialize: function() { 
     _.bindAll(this, "render"); 
     console.log(this.parentView.foo); 
    }, 
    render: function() { 
    } 
    }); 
Các vấn đề liên quan