2011-08-18 34 views
14

Tôi có một phương pháp render trong Backbone mà đi cơ bản như thế này:Gọi một plugin jQuery trong một Backbone Phương thức render

render: function() { 
    $.tmpl(this.template, attrs).appendTo(this.el); 
    return this; 
}, 

được gọi từ một hành động router:

action: function() { 
    $('#container').empty(); 
    $('#container').append(myView.render().el); 
}, 

Bây giờ, tôi muốn áp dụng plugin trên các phần tử label bên trong chế độ xem này. Suy nghĩ đầu tiên của tôi là để gọi các plugin bên render:

render: function() { 
    $.tmpl(this.template, attrs).appendTo(this.el); 
    this.$('label').inFieldLabels(); 
    return this; 
}, 

nhưng điều này không làm việc (Tôi giả định này là bởi vì nguyên tố này chưa được bổ sung vào DOM chưa). Nó không việc nếu tôi gọi là plugin trong hành động bộ định tuyến mặc dù:

action: function() { 
    $('#container').empty(); 
    $('#container').append(myView.render().el); 
    myView.$('label').inFieldLabels(); 
}, 

Tôi không muốn làm điều này, bởi vì các plugin là một phần của quan điểm, không phải là router, vì vậy nó không làm cảm giác được gọi nó bên trong hành động. Có cách nào tốt hơn để làm điều này?

Trả lời

0

Tôi đã giải quyết được sự cố này bằng cách thêm phương thức loadPlugins vào chế độ xem của mình, vì vậy tôi có thể thực hiện myView.loadPlugins() sau khi hiển thị trong tác vụ. Nó không lý tưởng, nhưng nó hoạt động.


Edit: Vâng, tôi đã heard from the horse's mouth và có vẻ như tôi không thể áp dụng các plugin trước khi nguyên tố này là được thêm vào DOM, do đó, hoặc tôi có thể làm như trên (với loadPlugins) hay tôi có thể sửa đổi mã để phần tử được thêm vào DOM theo phương thức render. Hy vọng điều này sẽ giúp ai đó ở một vị trí tương tự.

Dưới đây là cách tôi đang làm bây giờ:

//in router 
action: function() { 
    var myView = new MyView({ 
    el: '#container' 
    }); 
} 

//in view 
render: function() { 
    $.tmpl(this.template, attrs).appendTo(this.el); //this now appends to the DOM 
    this.loadPlugins(); 
    return this; 
}, 

loadPlugins: function() { 
    this.$('label').inFieldLabels(); 
    //and other plugins 
}, 
5

Beter làm điều đó theo cách này:

action: function() { 
    var container = $('#container'); 

    container.empty(); 
    myView.render(container); 
}, 

render: function (container) { 
    $(this.el) 
     .append($.tmpl(this.template, attrs)) 
     .appendTo(container); 
    $('label', this.el).inFieldLabels(); 
    return this; 
}, 
+1

Cảm ơn - đó là về cơ bản những gì tôi có nghĩa là bằng cách "thay đổi mã nên phần tử được thêm vào DOM trong phương thức 'render'". Ngẫu nhiên, bạn có thể thực hiện 'this. $ ('Label')', viết tắt của '$ ('label', this.el)'. – Skilldrick

+0

cảm ơn! không biết điều đó;) –

0

tôi đã phải đối mặt với một vấn đề tương tự nhưng trong trường hợp của tôi ngay cả những giải pháp trên sẽ không hoạt động vì các chế độ xem gốc chưa được thêm vào DOM.

Gắn bó với quy ước có chế độ xem cha mẹ thêm trẻ em vào DOM, việc loadPlugins() trong phương thức hiển thị không hoạt động.

Đây là những gì tôi đã làm. Nó cảm thấy loại hacky nhưng có thể giúp đỡ, tùy thuộc vào cách bạn đang quản lý quan điểm của bạn toàn bộ phân cấp:

render: function() { 
    var self = this; 

    setTimeout(function() { 
    $(self.el).setupPlugin(); 
    }, 0); 

    return this; 
} 

Sử dụng setTimeout từ 0 cho phép các cuộc gọi stack hiện tại để kết thúc, vì vậy theo thời gian các chức năng thời gian chờ được được gọi là khung nhìn và tất cả cha mẹ của nó đã được thêm vào DOM. (Nếu bạn tuân theo quy ước nêu trên).

+0

Sẽ tốt hơn nếu có cách đính kèm trình xử lý sự kiện kích hoạt khi một phần tử nhất định thực sự được thêm vào DOM. Có ai biết cách làm điều này không? – evilcelery

+0

Vâng, tôi cũng đã nghĩ đến việc làm một setTimeout - nó chắc chắn sẽ hoạt động nhưng nó cũng cảm thấy rất khủng khiếp. – Skilldrick

+0

Dường như có * sự kiện * khi [đã thêm một phần tử] (http://en.wikipedia.org/wiki/DOM_events), ví dụ: 'DOMNodeInserted', nhưng chúng không được IE hỗ trợ. Như mọi khi. Một số thông tin khác: http://stackoverflow.com/questions/2143929/domnodeinserted-equivalent-in-ie – Skilldrick

5

Tôi đã gặp sự cố tương tự khi thiết lập plugin Công cụ jQuery Tooltip. Nhưng tôi đã có một cách tiếp cận khác hoàn toàn hoạt động tốt: kích hoạt sự kiện tùy chỉnh trên chế độ xem. Theo như tôi biết, không có sự kiện 'được chèn vào dom' nào được xây dựng vào Backbone, vì vậy tôi đã tự làm điều đó.Tôi không sử dụng Bộ định tuyến nhưng mã được sửa đổi ở trên trông giống như sau:

// In the router: 
action: function() { 
    var container = $('#container'); 

    container.append(myView.render().el)); 
    myView.trigger('rendered'); 
}, 

// In the view: 
initialize: function() { 
    this.bind('rendered', this.afterRender, this); 
}, 
render: function (container) { 
    $(this.el).append($.tmpl(this.template, attrs)) 
    return this; 
}, 
afterRender: function() { 
    $('label', this.el).inFieldLabels(); 
} 

Tôi cho rằng lợi thế là chế độ xem vẫn không biết gì về vùng chứa của nó. Điểm bất lợi là nó giống như một dòng phụ hoặc hai mã. Nhưng nếu bạn cần thiết lập nhiều plugin hoặc làm nhiều thứ hơn đòi hỏi phần tử phải nằm trong DOM, nó sẽ hoạt động tốt (và nó giữ logic tách biệt).

Tôi thực sự thích phương pháp của @ Skilldrick để chuyển vùng chứa này sang chế độ xem, nhưng tôi vẫn cảm thấy như thể có ý nghĩa khi có chế độ xem gốc chịu trách nhiệm chèn trẻ em. Tôi mới vào Backbone vì vậy xin vui lòng bình luận.

+0

Đó là một ý tưởng thú vị, nhưng tôi không thích ý tưởng của router phải nói với quan điểm rằng nó đã được hiển thị. Điều đó về cơ bản có vẻ giống như một cái gì đó quan điểm nên biết về! – Skilldrick

+0

Đó là một thỏa hiệp tốt nếu bạn muốn giữ phần tử vùng chứa ngoài chế độ xem. – Skilldrick

+0

Phải, đó là một sự cân bằng. Tôi không thực sự cảm thấy một sự kéo theo hướng này hay cách khác. Tôi sẽ bình luận lại nếu có điều gì đó xảy ra khi tôi chạy ứng dụng của mình. –

2

tôi đã có thể có được điều này để làm việc cho jQuery plugin của tôi chỉ bởi xác định bối cảnh cho jQuery trong hàm render:

render: function() { 
    $(this.el).html(this.template(this.model.toJSON())); 
    $('#email1dropdown', this.el).dropdownify(); 

    return this; 
}, 
+2

Sử dụng ký hiệu 'this. $ ("# Email1dropdown") '. – Matthew

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