2012-03-09 35 views
17

Tôi có một kịch bản nơi dữ liệu được thao tác trên máy khách được trình bày và tương tác theo một cách khác với dữ liệu được trình bày trên máy chủ.Tính chất tính toán trong Backbone

Xem xét tài nguyên sau event được trả về từ máy chủ.

{ 
    "id": 123, 
    "start_at": 1331336004906, 
    "end_at": 1331337704906 
} 

Và mẫu sau để chỉnh sửa:

<form> 
    <!-- Notice how date and time are separated in the interface --> 
    <input type="text" name="start_date" value="{{start_date}}" /> 
    <input type="text" name="start_time" value="{{start_time}}" /> 

    <!-- Instead of asking for an end date/time, we ask for the duration --> 
    <input type="text" name="duration" value="{{duration}}" /> 

    <input type="submit" /> 
</form> 

Làm thế nào tôi sẽ đi về xử start_date, start_time, và duration như là thuộc tính trong mô hình Backbone của tôi mà không gửi chúng đến các máy chủ? Tôi có phải sửa đổi .toJSON() không?

+0

vấn đề với định dạng ressource sự kiện là gì, arent họ timestamps? – mpm

+0

Xem thêm: http://stackoverflow.com/questions/10648990/how-to-access-a-calculated-field-of-a-backbone-model-from-handlebars-template –

Trả lời

4

Mô hình của bạn phải tương ứng gần nhất với những gì bạn có phía máy chủ. Vì vậy, hãy gắn bó với start_atend_at. Điều đó sẽ đơn giản hóa rất nhiều hoạt động của bạn sync().

On chỉnh sửa hình thức của bạn Xem, bạn có thể:

  1. Tính start_date, start_time, duration thông qua chức năng đơn giản và gọi cho họ trong mẫu.
  2. Chuyển đổi thành start_atend_at khi gửi.
+1

Không được đặt trong Chế độ xem sẽ dẫn đến nhiều mã dự phòng? Tôi sẽ sử dụng cùng một thuộc tính ảo trên toàn bộ trang web, trong đó một sự kiện duy nhất có nhiều chế độ xem hiển thị nó. – bloudermilk

+0

Không cần dự phòng. Tạo chế độ xem cơ sở và mở rộng nó. – ggozad

+1

Cuộc gọi tốt! Tôi cũng nghĩ rằng kiểu trang trí có thể phù hợp với vấn đề này. – bloudermilk

6

Chúng tôi rất quen với việc gửi model.toJSON() tới cấp nguồn cấp mẫu. Và phương pháp này là rất khó để ghi đè bởi vì được sử dụng bởi các thành phần khác.

Nhưng chúng ta có thể nuôi sống bản mẫu với một phương pháp tùy chỉnh model.toJSONDecorated() có thể trông như thế này:

# in your Backbone.Model 
toJSONDecorated: function(){ 
    return 
    _.extend( 
     this.toJSON(), 
     { 
     start_date : Utils.dateFromDate(this.get("start_at")), 
     start_time : Utils.timeFromDate(this.get("start_at")), 
     duration : Utils.youGetTheIdea(:)) 
     } 
    ); 
} 

Tất nhiên điều này là vi phạm một vài mẫu, tôi có thể sống với nó, nếu bạn không bạn có thể chuyển logic này sang lớp Decorator khi mọi người đã đề xuất trong các câu trả lời khác.

5

Bạn có một số tùy chọn:

  • Override toJSON để trả lại tính duration

  • Tạo một phương pháp duration() trên Backbone Model. Chỉ có nhược điểm là bạn phải gọi nó theo cách khác (obj.duration() thay vì obj.get('duration')). Theo quan điểm của bạn mà tay obj.toJSON() cho mẫu của bạn, trộn theo duration thuộc tính

  • Sử dụng https://github.com/asciidisco/Backbone.Mutators (hoặc tương tự) để tạo ra một getter bắt nguồn cho thời gian

+0

Cảm ơn. Tôi thường áp dụng cách tiếp cận được mô tả, nhưng tôi không biết Mutators: nó trông rất hữu ích và được thực hiện tốt. –

22

Tôi đang sử dụng một sự kết hợp của initialize() cùng với trình nghe sự kiện thay đổi để cập nhật các thuộc tính có nguồn gốc. Ý tưởng đầu tiên là tính toán các thuộc tính về khởi tạo mô hình, và thứ hai để cho mô hình nghe những thay đổi của riêng nó và cập nhật các thuộc tính cho phù hợp.

Giải pháp của tôi trông gần như thế này:

MyModel: Backbone.Model.extend({ 
    initialize: function() { 
     this.updateDerivedAttributes(); 
     this.on('change:start_at', this.updateDerivedAttributes, this); 
    }, 
    updateDerivedAttributes: function() { 
     this.set({ 
      start_date: Utils.dateFromDate(this.get("start_at")), 
      start_time: Utils.timeFromDate(this.get("start_at")), 
      duration: Utils.youGetTheIdea() 
     }, {silent:true}); 
    } 
});