2012-02-09 35 views
6

Tôi đang cố gắng tạo một ứng dụng backbone.js nhỏ, nhưng phải vật lộn với thứ tự của sự vật.view backbone.js hiển thị trước khi tìm nạp mẫu

Trong file html của tôi, tôi có hai khối kịch bản trong tiêu đề:

<script type="text/template" id="model-template"> 
    <a href="#"><%= title %></a> 
</script> 

<script type="text/javascript"> 
    jQuery(function(){ 
    window.model.fetch(); 
    }); 
</script> 

Trong app.js của tôi, tôi đã xác định một mô hình đơn giản, xem và một router.

(function($) { 

window.MyModel = Backbone.Model.extend({ 
    url: '/mymodel' 
}); 

window.mymodel = new MyModel(); 

$(document).ready(function() { 

    window.MyModelView = Backbone.View.extend({ 
     template: _.template($('#mymodel-template').html()), 

     initialize: function() { 
      _.bindAll(this, 'render'); 
     }, 

     render: function() { 
      var renderedContent = this.template(this.model.toJSON()); 
      $(this.el).html(renderedContent); 
      return this; 
     } 
    }); 
}); 

window.MyApp = Backbone.Router.extend({ 
    routes: { 
     '': 'home' 
    }, 

    initialize: function() { 
     this.myModelView = new MyModelView({ 
      model: window.mymodel 
     }); 
    }, 

    home: function() { 
     var $body = $('body'); 
     $body.empty(); 
     $body.append(this.myModelView.render().el); 
    } 
}); 

$(function() { 
    window.App = new MyApp(); 
    Backbone.history.start({pushState: true}); 
}); 

})(jQuery); 

Ứng dụng được phục vụ bằng ứng dụng sinatra đơn giản. Url /mymodel phục vụ tệp json tĩnh:

{ 
    "title": "My Model", 
} 

Khi tải các ứng dụng, tôi nhận được một lỗi trong giao diện điều khiển javascript:

Uncaught ReferenceError: title is not defined 

Vấn đề có vẻ là, rằng quan điểm làm cho bản thân trước mô hình được lấy từ máy chủ. Tại sao vậy?

Hôm qua, tôi đã theo dõi hai lần phát sóng màn hình backbone.js đầu tiên từ PeepCode. Tôi đã cố gắng so sánh ứng dụng của mình với ứng dụng đã xuất hiện trên màn hình, nhưng không thể thấy lý do tại sao ứng dụng của tôi muốn hoạt động.

Mọi đề xuất?

+0

Tôi mất nhiều giờ ... GIỜ để tìm ra rằng đây là lý do tại sao ứng dụng của tôi không hoạt động, đã làm việc một số lần không phải những người khác hoặc làm việc trên một số trình duyệt chứ không phải các trình duyệt khác. Loại một sai lầm tân binh khi bạn nghĩ về cách lấy nên làm việc tôi giả sử. Bài học kinh nghiệm. Tôi nghĩ rằng quá nhiều ví dụ Backbone ra có sử dụng dữ liệu mã hóa cứng và các khái niệm rất quan trọng như mùa thu này bởi các bên. – IcedDante

Trả lời

16

Trong trường hợp này, bạn nên khởi động dữ liệu mô hình để có sẵn khi tải trang.

Thay vì

window.model.fetch(); 

đặt một cái gì đó như thế này trong (nếu sử dụng một .erb)

<script> 
    window.model = new MyModel(<%= @model.to_json %>); 
</script> 

Nếu không, bạn cần phải làm cho quan điểm sau khi mô hình được lấy ví dụ

ràng buộc quan điểm để render khi model thay đổi

initialize: function() { 
    _.bindAll(this, 'render'); 

    this.model.on("change", this.render); 
}, 

hoặc xử lý sự thành công của mô hình.tìm nạp và hiển thị chế độ xem

window.model.fetch({ 
    success: function (model, response) { 
     window.MyApp.myModelView.render(); 
    } 
}); 
+0

Câu trả lời này giúp tôi gần gũi nhất với giải pháp. Tôi đã xóa cuộc gọi để hiển thị trong bộ định tuyến của mình, nhưng giữ mã đã thêm thuộc tính của chế độ xem vào tài liệu. Vì vậy, khi tìm nạp hoàn thành, nó thay đổi mô hình của tôi, mà ném sự kiện thay đổi, mà gọi phương thức render. – Vegar

1

Đặt lại trạng thái của mô hình từ máy chủ. Hữu ích nếu mô hình có không bao giờ được điền dữ liệu hoặc nếu bạn muốn đảm bảo rằng bạn có trạng thái máy chủ mới nhất. Sự kiện "thay đổi" sẽ được kích hoạt nếu trạng thái của máy chủ khác với các thuộc tính hiện tại. Chấp nhận gọi lại thành công và lỗi trong băm tùy chọn, được chuyển qua (mô hình, phản hồi) làm đối số.

Trong trường hợp này, bạn sẽ muốn hiển thị chế độ xem trong gọi lại thành công.

model.fetch({ 
    error: function() { 
    }, 
    success: function (model, response) { // model is ready now 
     // do view stuff here 
    } 
}); 
1

Rõ ràng từ các câu trả lời trước đó, bạn biết rằng bạn cần hiển thị thêm một chút. Cụ thể, tuyến đường gia đình của bạn được sử dụng để xây dựng myModelView ngay lập tức thay vì khi dữ liệu của nó tải. Điều này xảy ra bởi vì bạn đang gọi render() để nối thêm vào phần thân. Thay vào đó, hãy thử và khởi tạo chế độ xem với phần tử hiện có. Bằng cách này, bạn có thể trì hoãn cuộc gọi để hiển thị cho đến khi tìm nạp hoàn tất:

window.MyApp = Backbone.Router.extend({ 
    routes: { 
     '': 'home' 
    }, 

    initialize: function() { 

    }, 

    home: function() { 
     var $body = $(document.body).empty(); 
     var myModelEl = $("<div></div>").appendTo($body); 

     this.myModelView = new MyModelView({ 
      model: window.mymodel, 
      el: myModelEl 
     }); 
    } 
}); 

Bây giờ, bạn chưa gọi render() nhưng chế độ xem của bạn được đính kèm thành công vào DOM như bạn dự định.

+0

Vì vậy, ở đây, bạn đang tạo một thể hiện của MyModelView cả trong khởi tạo và chức năng nhà? Hoặc tôi nên loại bỏ nó hình thành khởi tạo? – Vegar

+0

Bạn chính xác, hãy xóa nó khỏi khởi tạo. Xin lỗi vì sự nhầm lẫn. Nó không phải luôn luôn có ý nghĩa để đặt nó trong anyways khởi tạo như thường bạn sẽ làm cho các quan điểm khác nhau tùy thuộc vào phương pháp tuyến đường được gọi là. –

5

Bạn cũng có thể tận dụng lợi thế của đối tượng thu nhập hoãn lại http://api.jquery.com/category/deferred-object/ rằng Backbone.Model.fetch() trở về, như thế này:

window.MyModel = Backbone.Model.extend({ 
    url: '/mymodel' 
}); 

//when the model is fetched, store a reference to the jQuery deferred object 
window.MyModelFetch = window.MyModel.fetch(); 

window.MyModelView = Backbone.View.extend({ 
    template: _.template($('#mymodel-template').html()), 

    initialize: function() { 
     _.bindAll(this, 'render'); 
    }, 

    render: function() { 
     //reference the deferred object and use 'done' method 
     //to register a callback after complete 
     window.MyModelFetch.done(function(){ 
      var renderedContent = this.template(this.model.toJSON()); 
      $(this.el).html(renderedContent); 
      return this; 
     } 
    } 
}); 

Bạn có thể muốn tạo một phần mở rộng của mô hình xương sống mà các cửa hàng một đối tượng thu nhập hoãn lại trên mô hình của bạn mà bạn có thể tài liệu tham khảo, như thế này:

Backbone.DeferrableModel = Backbone.Model.extend({ 
     fetch: function(){ 
      this.fetching = Backbone.Model.prototype.fetch.apply(this, arguments); 
      return this.fetching; 
     } 
}); 

Sau đó, theo quan điểm của bạn phương pháp render, bạn chỉ có thể nói điều này:

render: function() { 
     //the deferred reference is now directly referenced from your model 
     this.model.fetching.done(function(){ 
      var renderedContent = this.template(this.model.toJSON()); 
      $(this.el).html(renderedContent); 
      return this; 
     } 
    }  

Nó có thể rất tiện dụng để sử dụng một mô hình mở rộng và làm theo mô hình này trong suốt ứng dụng xương sống của bạn.

Các vấn đề liên quan