如何更新 multi-select 并让它实际显示 Chrome 中的新选项

How to update a multi-select and have it actually show the new options in Chrome

我不敢相信,但我发现一些 JS 代码在 IE 11 中完美运行,但在 Chrome(81 版)中不起作用。

我正在从一个多 select 更新另一个,保持选项排序。所以我有一个功能:

    /**
     * Move the options defined by <sel> from select tag <from> to select tag <to>
     * @param from   The source SELECT tag jQuery object
     * @param to     The destination SELECT tag jQuery object
     * @param sel    Either: "option" for all, or "option:selected"
     */
    function moveOpt(from, to, sel) {
        var opts = from.children(sel).removeAttr('selected').remove().get();
        opts = opts.concat(to.children('option').remove().get());
        opts.sort(function (a, b) {
            return a.value.localeCompare(b.value);
        });
        to.append(opts);
        /*
        // Chrome doesn't re-render the opts until they are selected and then focus is lost ???
        window.setTimeout(function() {
            to.children('option').attr('selected', 'selected').trigger('click');
            from.trigger('focus');
            to.children('option').removeAttr('selected');
        }, 1);
         */
    }

这在 IE 11 中完美运行,但在 chrome 中,选项已移动,但您无法在浏览器中看到它们。它们在那里是因为如果你 "inspect" SELECT 元素,所有的选项标签都在那里,而且 $(to).children().length 显示正确的数字。

如果我取消注释丑陋的 HACK(window.setTimeout() 调用),那么 Chrome 最终会正确显示选项。但必须这样做是疯了。我一定做错了什么。有人知道那是什么东西吗?

Here is a JS fiddle showing the issue - 运行 它在 IE(只读模式)中显示它工作,Chrome 没有。

更新

我尝试将 jQuery 从 1.10.2 升级到 3.5.0,但仍然没有成功。

@ZacharyYaro 也指出它适用于 Chrome 80,但不适用于 81。

改变这个:

to.append(opts);

为此:

var toElm = to.get()[0];
$.each(opts, function(i,v) { toElm.appendChild(v); });

解决了问题。

(重新提交我的评论作为答案,因为它对你有用) 看起来你的 Fiddle 也在 Chrome 80 中工作,然后在 Chrome 81 中中断。看起来 using the built-in selectElement.add function instead of jQuery (JSFiddle) 在 Chrome 81 中工作,所以看起来 Chrome 81 刚刚破坏了 jQuery 的 $element.append(arrayOfElements) 函数使用的东西。