在渲染骨干视图时获得通知
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()?
我遇到过这个问题,有一些模式可以提供帮助。Backbone给你工具,但不会告诉你如何使用它们。在使用过程中建立良好的模式是非常重要的。我使用了两种不同的模式来帮助实现这一点。
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()
后不久(在当前执行的代码完成运行并将控制权返回给JS引擎以运行下一个排队的代码之前的任何时间)附加到DOM,则可以利用这一事实。当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: function(callback){
//use Backbone/jQuery to append to DOM here
if(typeof callback === 'function'){
callback(null,'viewX-rendered'); //invoke the error-first callback
}
}
考虑到从渲染返回"this"以链接主干调用是首选模式,则前两个选项可能是更好的选项。
最后,如果您当前的呈现方法确实是异步的,也就是说,将内容附加到DOM的jQuery代码是异步发生的,那么您可以使用jQuery将侦听器附加到DOM元素,就像一样
https://gist.github.com/azat-co/5898111
- 如何使用javascript从主svg对象动态创建svg视图框
- 正在使用$location.path(.)路由ng视图
- angular.js没有'无法在PhoneGap中处理视图标记
- 如何包含特定于每个视图angularjs的javascript文件
- 通过在Dojo mobile ViewController.openExternalView中动态更改打开同一外部视图的
- Kendo:我该如何在树视图中创建一个递归的hieiarchy
- 在渲染骨干视图时获得通知
- CakePHP3:如何使用视图单元格实现Facebook风格或堆栈式用户通知
- 反应+通量:通知视图/组件操作失败
- 模型完成通知视图模型
- Dojo DataGrid如何通知视图服务器上的数据已更改
- AngularJS通知视图对模型的更改
- 如何通知模型中的视图更改主干中的值
- Zk通知多视图
- AngularJS方式:通过通知功能扩展控制器/视图
- JavaScriptMVC:视图如何通知控制器
- 当视图模型属性改变复选框值时被通知
- 如何用JavaScript在加载视图中删除所有Chrome通知
- 如何通过主干视图渲染持久化状态消息/图标/通知
- 如何在knockoutjs中正确地通知我的observablearray来刷新它的视图?