[英]Get notified when a Backbone View has been rendered
我正在研究Backbone.View
,它應該將集合呈現為可滾動列表。
在初始渲染的一部分中,我需要訪問一些布局屬性(例如clientWidth
),這些屬性僅在渲染視圖之后才可用。
我的問題是, 如何知道何時將視圖添加到DOM?
使用Backbone.View
通常有兩種將視圖附加到DOM的方法:
創建視圖>渲染>附加它:
view = new MyList().render() $('#dummy').append(view.$el)
創建視圖並就地渲染:
new MyList({el: '#dummy'}).render()
注意:我知道(1)和(2)並不完全等效,這不是重點。
讓我們考慮一下我的列表定義如下:
class MyList extends Backbone.View
render: ->
@$el->html( ... )
@
layout: ->
max = $el.scrollWidth - $el.clientWidth
# ... disable / enable scrolling arrows based on max ...
MyList附加到DOM后,如何確定layout()被調用?
我已經遇到了這個問題,有些模式可以提供幫助。 骨干網為您提供工具,但不會告訴您如何使用它們。 建立良好的模式在您使用它時非常重要。 我使用了兩種不同的模式來幫助實現這一目標。
1)根據您的應用程序的工作方式,確保始終在呈現視圖並將其附加到DOM之后始終調用attached()
方法或在視圖上觸發attached
事件可能很容易,也可能很難。 就我而言,這很容易,因為我創建了一種架構,可以在一個中央位置處理該架構。
2)如果您總是在渲染之后立即將元素附加到DOM-特別是在渲染之后的任何時間,而不是通過在異步回調中這樣做來延遲附加,那么在render()函數中,您可以將對layout()
的調用或其他需要在連接后運行。 像這樣:
var MyList = Backbone.View.extend({
render: function() {
/* rendering logic goes here */
// Notice that the timeout is 0 - you can actually not even pass this argument
// but I wanted to emphasize that there is no delay given.
setTimeout(this.layout, 0);
return this;
},
layout: function() {
// This code won't be run until after this.el is attached to the DOM
}
});
var view = new MyList().render();
$('#dummy').append(view.$el);
Javascript始終是單線程的。 I / O可以異步完成,但是實際上需要JS引擎花費時間的任何事情都不能與其他JS代碼並行運行。 當您調用不帶最后一個參數或值為0
setTimeout()
時,實際上它將使它排隊,以便在當前執行的代碼完成后盡快運行。
如果在調用render()
之后立即遵循始終附加到DOM的模式,則可以利用這一事實-在當前執行的代碼完成運行並將控制權返回給JS引擎以運行接下來排隊的任何東西之前的任何時間。 在運行由setTimeout(func, 0)
排隊的函數時,您便可以知道您的視圖已附加到DOM。 請注意,這與_.defer()
作用相同,但是我想為您解釋一下。
再一次,建立模式非常重要。 如果您從未保持一致並且沒有在應用程序內建立模式,那么您將沒有任何保證,您將失去依靠這種機制的能力-否則您可能會建立其他機制。 希望這可以幫助!
這是一個看似困難的問題。 有DOM突變事件 ,但是AFAIK並未跨瀏覽器實現,因此無論如何都已棄用。 突變觀察者似乎是做到這一點的新方法,但是同樣,我不確定兼容性。
確保安全的方法,但昂貴/混亂的方法是輪詢以查看屍體是否位於祖先鏈中。
whenInserted = function ($el, callback) {
check = function () {
if ($el.closest('body').length) { // assuming a jQuery object here
callback();
} else {
setTimeout(check, 100);
}
};
check();
};
我對其中一些答案的糟糕程度感到驚訝。 jQuery方法是同步的。
因此,在Backbone.View渲染功能中,您有幾個不錯的選擇:
//只調用一個函數
render:function(){
//first, use Backbone/jQuery to append to DOM here
//second
this.callSomeFunctionToSignifyRenderIsDone();
return this;
}
//觸發一個事件
render:function(){
//use Backbone/jQuery to append to DOM here
Backbone.Events.trigger('viewX-rendered'.); //trigger an event when render is complete
return this;
}
或者,如果您的render方法具有異步代碼,這種情況不太可能發生,您可以將可選的回調傳遞給render函數:
render: function(callback){
//use Backbone/jQuery to append to DOM here
if(typeof callback === 'function'){
callback(null,'viewX-rendered'); //invoke the error-first callback
}
}
考慮到從渲染返回“ this”以便鏈接Backbone調用是首選模式,那么前兩個選擇可能是更好的選擇。
最后,如果您當前的渲染方法確實是異步的,也就是說,將內容附加到DOM的jQuery代碼正在異步發生,那么您可以使用jQuery這樣將偵聽器附加到DOM元素上
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.