如何附加在以编程方式更改值时触发的 JavaScript 事件处理程序

How to attach a JavaScript event handler that gets triggered when the value is changed programmatically

我有 'Title' 下拉菜单,选择 "Dr" 会触发 'Gender' 下拉菜单出现。在页面准备就绪时,我将事件处理程序附加到更改事件,但是页面上有某种机制(我无法控制)以编程方式更改下拉列表中的值但不会触发 change() 事件。

Manually invoking .change() 设置值后不是一个选项。

如何附加一个 JavaScript 事件处理程序,它在值以编程方式更改时触发,而不是仅在通过 select 的 UI 更改时触发?

如果您无法控制的代码更改了 select 框中的 selected 值,您将无法收到事件通知。您只剩下通过 setInterval 或一系列 setTimeout.

进行轮询的令人不快的选择

我检查了一下,即使是 MutationObserver 也没有帮助——这并不奇怪,因为更改 selected 项目不会改变 DOM,但我无论如何希望。

每 50 毫秒左右轮询一次应该不会对性能产生任何重大影响。

这里以轮询为例,适当修改间隔:

(function() {
  var s = $("#s"),
      lastValue = s.val();
  setInterval(function() {
    var value = s.val();
    if (value !== lastValue) {
      lastValue = value;
      snippet.log("The value changed to: " + value);
    }
  }, 50);
})();
snippet.log("Changing the value in a second...");
setTimeout(function() {
  snippet.log("Changing value now");
  $("#s").val("2");
  snippet.log("Done changing value");
}, 1000);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<select id="s">
  <option value="1">One</option>
  <option value="2">Two</option>
  <option value="3">Three</option>
</select>
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>


将您的评论转给 Amit:

knockout.js does it with observables somehow

不,它不是,它依赖于您仅通过 select 框(触发事件)或通过 KO:

修改 select 的值

var vm = {
  sval: ko.observable('one')
};
vm.sval.subscribe(function(newValue) {
  snippet.log("New value: " + newValue);
});
ko.applyBindings(vm, document.body);
snippet.log("sval is " + vm.sval() + ", changing value in select in one second");
setTimeout(function() {
  document.getElementById("s").selectedIndex = 1;
  snippet.log("Changed select, but sval is still " + vm.sval());
}, 1000);
<select id="s" data-bind="value: sval, options: ['one', 'two', 'three']"></select>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

这是@T.JCrowder 对答案的修改,适用于那些需要在第一次下拉选项更改时触发 .change() 然后自行关闭的版本的人。

(function () {
    var selector = "[id='Title']";
    var lastValue = $(selector).val();
    var timer = setInterval(function () {
        var value = $(selector).val();
        if (value !== lastValue) {
            lastValue = value;
            $(selector).change();
            clearInterval(timer);
        }
    }, 500);
})();