Template.onRendered() 调用得太早
Template.onRendered() called too early
我遇到了一个奇怪的问题。我正在使用 hammer.js 配置长按事件,并在 Template.onRendered() 回调中附加事件观察器。这在我的本地开发机器上完美运行。但是,当我部署到服务器时,似乎在模板在浏览器中完成呈现之前触发了 onRendered()。 jQuery 选择器为空。我不得不求助于设置计时器以确保在配置事件处理程序之前呈现模板。或者,我尝试在 Tracker.afterFlush() 中配置事件处理程序来代替 setTimeout(),但是在触发时仍未呈现模板。
看来我不应该在这里使用setTimeout()。我是不是做错了什么或出了问题?
Template.CATEGORIES.onRendered(function () {
Meteor.setTimeout(function () {
console.log('setting up hammer object', this.$('.collapsible'));
var h = this.$('.collapsible').hammer({domEvents:true});
h.on('tap press swipe pan', '.collapsible-header', function (ev) {
// get the ID of the shopping list item object
var target = ev.target;
var $target = $(target);
var type = ev.type;
var $header = $target;
if (Collapse.isChildrenOfPanelHeader($target)) {
$header = Collapse.getPanelHeader($target);
}
console.log('Firing ', type, ' on ', $header);
Kadira.trackError('debug', 'Firing ' + type + ' on ' + $header);
// handler for checkbox
if (type === 'tap' && $target.is('label')) {
var data = Blaze.getData(target);
var TS = data.checkedTS;
ev.preventDefault();
data.checked = !data.checked;
console.log('Checkbox handler', data);
if (data.checked && !TS) {
TS = new Date()
} else if (!data.checked) {
TS = null
}
// Set the checked property to the opposite of its current value
ShoppingList.update(data._id, {
$set: {checked: data.checked, checkedTS: TS}
});
} else if (type === 'tap' && $target.has('.badge')) {
// if the user taps anywhere else on an item that has a child with .badge class
// this item has deals. Toggle the expand.
console.log('badge handler');
$header.toggleClass('active');
Collapse.toggleOpen($header);
} else if (type === 'press' || type === 'swipe' || type === 'pan') {
// remove any selected deals
var itemID, item;
var $label = $header.find('label');
console.log('long press handler');
if ($label) {
itemID = $label.attr('for');
item = ShoppingList.findOne(itemID);
if (item && item.deal) {
Deals.update(item.deal._id, {$set: {'showOnItem': false}});
ShoppingList.update(itemID, {$set: {'deal': null}});
}
}
}
})
}, 2000);
});
前几天有人回答了这个问题,但一定是撤回了他们的回答。他们建议模板实际上已呈现,但数据订阅尚未完成复制。他们是对的。
我能够验证我需要等到数据订阅完成才能设置我的 java 脚本事件。
我遇到了一个奇怪的问题。我正在使用 hammer.js 配置长按事件,并在 Template.onRendered() 回调中附加事件观察器。这在我的本地开发机器上完美运行。但是,当我部署到服务器时,似乎在模板在浏览器中完成呈现之前触发了 onRendered()。 jQuery 选择器为空。我不得不求助于设置计时器以确保在配置事件处理程序之前呈现模板。或者,我尝试在 Tracker.afterFlush() 中配置事件处理程序来代替 setTimeout(),但是在触发时仍未呈现模板。
看来我不应该在这里使用setTimeout()。我是不是做错了什么或出了问题?
Template.CATEGORIES.onRendered(function () {
Meteor.setTimeout(function () {
console.log('setting up hammer object', this.$('.collapsible'));
var h = this.$('.collapsible').hammer({domEvents:true});
h.on('tap press swipe pan', '.collapsible-header', function (ev) {
// get the ID of the shopping list item object
var target = ev.target;
var $target = $(target);
var type = ev.type;
var $header = $target;
if (Collapse.isChildrenOfPanelHeader($target)) {
$header = Collapse.getPanelHeader($target);
}
console.log('Firing ', type, ' on ', $header);
Kadira.trackError('debug', 'Firing ' + type + ' on ' + $header);
// handler for checkbox
if (type === 'tap' && $target.is('label')) {
var data = Blaze.getData(target);
var TS = data.checkedTS;
ev.preventDefault();
data.checked = !data.checked;
console.log('Checkbox handler', data);
if (data.checked && !TS) {
TS = new Date()
} else if (!data.checked) {
TS = null
}
// Set the checked property to the opposite of its current value
ShoppingList.update(data._id, {
$set: {checked: data.checked, checkedTS: TS}
});
} else if (type === 'tap' && $target.has('.badge')) {
// if the user taps anywhere else on an item that has a child with .badge class
// this item has deals. Toggle the expand.
console.log('badge handler');
$header.toggleClass('active');
Collapse.toggleOpen($header);
} else if (type === 'press' || type === 'swipe' || type === 'pan') {
// remove any selected deals
var itemID, item;
var $label = $header.find('label');
console.log('long press handler');
if ($label) {
itemID = $label.attr('for');
item = ShoppingList.findOne(itemID);
if (item && item.deal) {
Deals.update(item.deal._id, {$set: {'showOnItem': false}});
ShoppingList.update(itemID, {$set: {'deal': null}});
}
}
}
})
}, 2000);
});
前几天有人回答了这个问题,但一定是撤回了他们的回答。他们建议模板实际上已呈现,但数据订阅尚未完成复制。他们是对的。
我能够验证我需要等到数据订阅完成才能设置我的 java 脚本事件。