2011-10-19 32 views
11

Tôi nghĩ rằng tôi hoàn toàn không hiểu ý tưởng đằng sau việc sử dụng các bộ định tuyến Backbone một cách thích hợp. Dưới đây là những gì tôi có:Bộ định tuyến đường trục: chờ dữ liệu được tìm nạp trước tiên

Tôi có một số dữ liệu mà tôi tìm nạp từ máy chủ khi trang tải và sau đó đóng gói nó vào các mô hình và bộ sưu tập. Số lượng các mô hình và bộ sưu tập đó là vô thời hạn. Tôi muốn sử dụng bộ định tuyến để có thể hiển thị trực quan chế độ xem của bộ sưu tập nhất định ngay từ đầu.

Vấn đề là: Bộ định tuyến đường trục khởi động sớm, và vì tôi yêu cầu nó truy cập vào một giao diện nhất định và kích hoạt hành động render của nó, nó không thể làm điều đó, vì những chế độ xem đó chưa được tạo. Điều đó có nghĩa là tôi thực sự phải làm cho các tuyến đường của tôi khởi động sau khi tìm nạp xong.

Tôi không biết nếu điều này là một cách thích hợp để làm điều đó, nhưng ý tưởng duy nhất mà tôi đã đưa ra là:

  1. Bó đường nét và các bit Backbone.history.start(); thành một top-level riêng chức năng có khả năng (tức là chuẩn bị để gọi nó bằng tay sau này).
  2. Run có chức năng như success gọi lại cho fetch()
  3. Số bộ sưu tập của tôi trong những bộ sưu tập là không rõ, tôi cũng không có cách nào để tìm hiểu khi tất cả trong số họ đã lấy, và tôi không muốn bắt đầu các tuyến đường nhiều lần. Vì vậy, tôi sử dụng số _.defer()_.once().

này hoạt động, nhưng nó chắc chắn trông rất lạ:

Router:

window.startRoutes = _.once(function() { 

     var AccountPage = Backbone.Router.extend({ 

      routes: { 
      'set/:id': 'renderSet', 
      }, 

      renderSet: function(setId) { 

       /** … **/ 

       // Call the rendering method on the respective CardView 
       CardsViews[setId].render(); 

      } 

     }); 

     var AccountPageRouter = new AccountPage; 

     Backbone.history.start(); 

    }); 

Bộ sưu tập:

window.CardsCollection = Backbone.Collection.extend({ 

    model: Card, 

    initialize: function(params) { 

     /** … **/ 

     // Get the initial data 
     this.fetch({success: function() { 
      _.defer(startRoutes); 
     }}); 

    }, 

}); 

Vì vậy, câu hỏi của tôi là ... tôi làm việc đó phải không? Hoặc là có một cách tốt hơn để làm điều này (phải)?

+0

Tại sao thực hiện cuộc gọi ajax ngay lập tức? Tại sao không chỉ đơn giản là render trang với json cần thiết cho databload ban đầu và truyền dữ liệu vào startbone? – redsquare

Trả lời

14

Bạn có thể xác định bộ định tuyến của mình trước thời hạn; nó sẽ không làm bất cứ điều gì cho đến khi bạn gọi Backbone.History.start().

Bạn có thể ràng buộc "thiết lập lại" sự kiện trên bộ sưu tập của bạn để bắt đầu lịch sử như thế này:

my_collection.bind("reset", _.once(Backbone.History.start, Backbone.History)) 

Sau đó router sẽ bắt đầu làm công cụ khi bộ sưu tập của bạn được nạp đầy đủ. Tôi không chắc chắn nếu điều này là chính xác những gì bạn đang tìm kiếm (kể từ khi bạn đề cập có một số lượng bộ sưu tập biến).

Tôi có tình huống tương tự, ngoại trừ việc tôi biết trước bộ sưu tập nào tôi muốn tải trước khi bắt đầu định tuyến.Tôi đã thêm một phương pháp startAfter để Router của tôi, như vậy:

window.Workspace = new (Backbone.Router.extend({ 
    . . . 
    startAfter: function(collections) { 
     // Start history when required collections are loaded 
     var start = _.after(collections.length, _.once(function(){ 
     Backbone.history.start() 
     })) 
     _.each(collections, function(collection) { 
     collection.bind('reset', start, Backbone.history) 
     }); 
    } 
    })); 

và sau đó sau khi tôi đã thiết lập các bộ sưu tập của tôi

Workspace.startAfter([collection_a, collection_b, ...]) 

Điều này có thể được điều chỉnh để làm việc với các mô hình độc quá, mặc dù tôi nghĩ rằng bạn cần phải liên kết với một thứ khác ngoài sự kiện 'đặt lại'.

Tôi rất vui vì đã đọc mã mẫu của bạn, việc sử dụng _.once và _.defer chỉ cho tôi đúng hướng.

+0

Không phải là nó 'my_collection.bind (" reset ", _.once (Backbone.history.start))'? – iblue

+2

Bạn đã sử dụng các đối số sai cho '_.once()'. Tôi sẽ chỉnh sửa câu trả lời của bạn để sửa lỗi này. kthxbye :) – iblue

+0

Ví dụ '_.once()' không hoạt động đối với tôi. Tôi đã phải sử dụng: 'app.users.on (" đặt lại ", _.once (function() { Backbone.history.start(); }));' –

1

Tôi chỉ đang kiểm tra phương thức .render() của mình mà tất cả các trường bắt buộc đều được điền trước khi sử dụng. Nếu chưa điền - tôi đang hiển thị tiện ích 'Đang tải ...'.

Và tất cả các chế độ xem của tôi được đăng ký thay đổi mô hình, trước this.model.bind('change', this.render, this);, vì vậy ngay sau khi mô hình sẽ được tải, render() sẽ được gọi lại.

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