DOM变异时如何重新运行JavaScript?

时间:2015-02-14 06:24:55

标签: javascript meteor

我正在使用Template.rendered来设置下拉列表替换:

Template.productEdit.rendered = function() {
    if( ! this.rendered) {
        $('.ui.dropdown').dropdown();
        this.rendered = true;
    }
};

但是当DOM变异时我该如何重新运行呢?助手为选择选项返回新值,但我不知道在哪里重新执行我的.dropdown()

3 个答案:

答案 0 :(得分:2)

我认为你不希望在整个DOM渲染之前运行它,否则事件处理程序将在插入的每个元素上运行:

var rendered = false;
Template.productEdit.rendered = function() {rendered: true};

为了避免在已经下拉的元素上重新运行,你可以给新的一个类,当你将它们放入下拉列表时删除它

<div class="ui dropdown not-dropdownified"></div>

您可以为DOMSubtreeModified添加一个事件监听器,它只会在页面呈现后执行某些操作:

Template.productEdit.events({
    "DOMSubtreeModified": function() {
        if (rendered) {
            var newDropdowns = $('.ui.dropdown.not-dropdownified');
            newDropdowns.removeClass("not-dropdownified");
            newDropdowns.dropdown();
        }
    }
});

这应该减少触发事件时所做的操作次数,并且可以阻止callstack耗尽

答案 1 :(得分:1)

这是我的初步答案,它有效,但我仍然希望Meteor有某种模板变异回调,而不是这种更繁琐的方法:

Template.productEdit.rendered = function() {
    if( ! this.rendered) {
        $('.ui.dropdown').dropdown();

        var mutationOptions = {
            childList: true,
            subtree: true
        }

        var mutationObserver = new MutationObserver(function(mutations, observer){
            observer.disconnect(); // otherwise subsequent DOM changes will recursively trigger this callback

            var selectChanged = false;

            mutations.map(function(mu) {
                var mutationTargetName = Object.prototype.toString.call(mu.target).match(/^\[object\s(.*)\]$/)[1];
                if(mutationTargetName === 'HTMLSelectElement') {
                    console.log('Select Changed');
                    selectChanged = true;
                }
            });

            if(selectChanged) {
                console.log('Re-init Select');
                $('.ui.dropdown').dropdown('restore defaults');
                $('.ui.dropdown').dropdown('refresh');
                $('.ui.dropdown').dropdown('setup select');
            }

            mutationObserver.observe(document, mutationOptions); // Start observing again
        });

        mutationObserver.observe(document, mutationOptions);

        this.rendered = true;
    }
};

这种方法使用MutationObserver和我发现here

的语法帮助

答案 2 :(得分:-1)

采用广告式猜测,并假设您使用的是Semantic UI Dropdown插件,您可以定义四种回调:

onChange(value,text,$ choice):在选择下拉项后调用。接收选择的名称和值以及活动菜单元素

onNoResults(searchValue):搜索下拉列表时调用没有匹配的值

onShow :在显示下拉列表后调用。

onHide :隐藏下拉列表后调用。

要使用它们,请给dropdown()函数一个参数:

$(".ui.dropdown").dropdown({
    onChange: function(value, text, $choice) {alert("You chose " + text + " with the value " + value);},
    onNoResults: function(searchValue) {alert("Your search for " + searchValue + " returned no results");}
    onShow: function() {alert("Dropdown shown");},
    onHide: function() {alert("Dropdown hidden");}
});

我建议你阅读你使用的所有插件的documentation