自定义onChange事件

时间:2019-03-21 01:25:56

标签: javascript events dom-events

是否存在建议的方法来基于值的更改触发自定义事件?我有一个变量,status,它来自外部API,并且将从queued-> in progress-> complete更改。

我想观察该变量的变化并适当触发事件。现在,它的工作方式是这样的:我每2秒轮询一次状态,服务器响应如下:

<status> @ <every X seconds of polling>
queued @ 0s
queued @ 2s
queued @ 4s
in progress @ 6s
in progress @ 8s
in progress @ 10s
in progress @ 12s
in progress @ 14s
in progress @ 16s
complete @ 18s
complete @ 20s
complete @ 22s
complete @ 24 s

我正在根据此状态更改某些DOM元素。我想将DOM操作的次数从12次减至3次。将幼稚的方法似乎可以通过维持先前的状态和当前的状态变量来实现,但是我想知道是否可以通过使用CustomEvent之类的方法来做到这一点。

2 个答案:

答案 0 :(得分:0)

过去,使用对象的.watch()方法可以实现类似的效果。 每当属性的值更改时,它就会触发一个事件。 不幸的是,现在不推荐使用。

尽管有点棘手,我们可以使用 MutationObserver 来伪造此行为。 技巧是,不要将状态更改存储在变量 status 中,而是将其存储在不可见的DIV中,并使用MutationObserver在DIV的innerHTML属性更改后立即触发事件。

var observer = new MutationObserver(handler),
  targetDiv = document.getElementById("dummy"),
  objConfig = {
    childList: true,
    subtree: true,
    attributes: false,
    characterData: false
  };

observer.observe(targetDiv, objConfig);

function handler() {
  console.log("something changed");
}

// the following part is just needed to simulate the change
setTimeout(changeIt, 1000);
function changeIt() {
  document.getElementById("dummy").innerHTML = "different";
}
<div id="dummy" style="display:none"></div>

答案 1 :(得分:0)

我可以使用Proxy来做到这一点,


var jenkins_state = {
  current_status: null
};

var jenkins_state_proxy = new Proxy(jenkins_state, {
  set: function(target, key, value) {
    if (key !== 'current_status') return false;

    var currentValue = target[key];
    if (value !== currentValue) {
      // Do very expensive DOM modifications
      redraw_the_div();
      repaint_everything();
      console.log('status changed');
    }
    target[key] = value;
    return true;
  }
});

jenkins_state_proxy.current_status = "waiting"; // first run: fired
jenkins_state_proxy.current_status = "waiting"; // won't fire
jenkins_state_proxy.current_status = "waiting"; // won't fire
jenkins_state_proxy.current_status = "in queue"; // fired
jenkins_state_proxy.current_status = "in queue"; // won't fire
jenkins_state_proxy.current_status = "in queue"; // won't fire
jenkins_state_proxy.current_status = "in queue"; // won't fire
jenkins_state_proxy.current_status = "in progress"; // fired
jenkins_state_proxy.current_status = "in progress"; // won't fired
jenkins_state_proxy.current_status = "completed"; // fired

说明:

基本上,我只是在这里更改跟踪一件事,那就是current_status。因此,我将其包装在一个对象中,并使用Proxy为其创建了包装对象。我所有的修改都是通过该代理进行的,它们被set函数拦截。我不允许使用第一个if来更改对象(添加新键)。在第二个if中,确保正确处理current_status的新值。