我正在尝试收听两个javascript事件。两者都需要发生,但我不知道它们将以何种顺序发生。在这两种情况发生之前,我不想运行我的代码。我可以将延迟事件与jQuery的事件处理程序附加函数一起使用吗?
具体来说,我想等到带有远程加载内容的bootstrap模式完成显示和加载。
单击此超链接显示模式,使用jquery的load
方法在超链接中加载页面,并将加载的页面内容插入到模式中。
<a href="http://www.example.com" data-toggle="modal" data-target="#mymodal">Click Here</a>
目标模式:
<div class="modal fade" id="mymodal>
<div class="modal-dialog">
<div class="modal-content"></div>
</div>
</div>
我尝试附加事件侦听器失败,并使用promises知道两个事件何时被触发。我认为这里的问题是承诺告诉我听众是附属的,而不是事件已经解雇。
var loaded = $(".modal").on('loaded.bs.modal', function(evt) {
console.log("content loaded");
}).promise();
var shown = $(".modal").on('shown.bs.modal', function(evt) {
console.log("modal visible");
}).promise();
$.when(loaded, shown).done(function(load, show) {
console.log("content loaded and modal visible");
});
bootply上的
答案 0 :(得分:1)
.promise()
返回fx
队列的延迟承诺。由于您实际上并没有等待fx
队列,因此没有理由在此处使用该特定方法。
show.bs.modal - 调用
show
实例方法时会立即触发此事件。如果由单击引起,则单击的元素可用作事件的relatedTarget
属性。shown.bs.modal - 当模式对用户可见时将触发此事件(将等待CSS过渡完成)。如果由单击引起,则单击的元素可用作事件的
relatedTarget
属性。loaded.bs.modal - 当模式使用远程选项加载内容时会触发此事件。
承诺是一次性使用。一旦他们解决了,你需要产生新的承诺。
如果您知道事件将按特定顺序发生,那么依赖该订单通常就足够了。例如,如果订单始终为:
然后将事件处理程序附加到shown
事件就足够了,因为它总是在loaded
事件之后发生。
我对文档的解释是,shown
事件将始终在loaded
事件之后触发(为什么显示某些内容还没有?),这意味着您可以只听取shown
事件,并完全忽略loaded
。
由于我不能100%确定实际的行为,因此我会假设为了这篇文章,订单也可以是:
我已在列表中加入show
,因为它是一个始终如一的起点。在 shown
事件被解雇之后,您将无法获得loaded
或show
个事件。这很有用,因为您可以使用它来生成新的延迟。
$('.modal').on('show.bs.modal', function () {
var $this,
data;
$this = $(this);
data = $this.data();
if (data.shownDeferred) {
//if this modal had been opened before, but never finished
//showing it should be cancelled
data.shownDeferred.reject();
}
data.shownDeferred = $.Deferred();
if (data.loadedDeferred) {
//if this modal had been opened before, but never loaded
//it should be cancelled
data.loadedDeferred.reject();
}
data.loadedDeferred = $.Deferred();
$.when(data.shownDeferred, data.loadedDeferred).then(function () {
$this.trigger('yourcustomeventname');
});
}).on('loaded.bs.modal', function () {
var dfd;
dfd = $(this).data('loadedDeferred');
if (dfd) {
dfd.resolve();
}
}).on('shown.bs.modal', function () {
var dfd;
dfd = $(this).data('shownDeferred');
if (dfd) {
dfd.resolve();
}
});
通过上述设置,您可以设置模式,以便在loaded
和shown
事件都已完成触发时触发您自己的自定义事件。
警告我还没有对这些代码进行过任何测试,因此可能有错误
答案 1 :(得分:0)
对于这个问题,Deferreds / Promises是一个破解坚果的大锤。即使事件的顺序未知,整个事情也可以用布尔来解决,而不是承诺。
但是,的事件顺序已知。运行 test ,您可以看到初始&#34;显示&#34;表现与后续的#34;表演不同。这些事件按顺序排列如下:
换句话说,loaded
是一次性事件,shown
可靠地持续。
因此,您只需听取shown
。
$('.modal').on('shown.bs.modal', function () {
//Do awesome stuff here
});
如果你想进一步抑制&#34;节目&#34;在模态显示之前,它稍微涉及但不是太糟糕 - 这样的事情可能是:
$('.modal').on('show.bs.modal', function () {
var $this = $(this),
data = $this.data('modal');
if (!data) {
data = $this.data('modal') = {};
}
if(!data.pending) {
data.pending = true;
$this.one('shown.bs.modal', function() {
data.pending = false;
//Do awesome stuff here
});
}
});
稍微考虑一下,这可能会简化。