Пользовательское событие onChange - PullRequest
0 голосов
/ 21 марта 2019

Есть ли рекомендуемый подход для запуска пользовательских событий на основе изменения значения?У меня есть переменная, назовем ее 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 голосов
/ 22 марта 2019

Я смог сделать это, используя 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 обработано соответствующим образом.

0 голосов
/ 21 марта 2019

В прошлом нечто подобное было возможно с помощью метода объекта .watch (). Всякий раз, когда значение свойства изменялось, оно вызывало событие. К сожалению, это устарело.

Хотя это немного сложно, мы можем подделать это поведение, используя MutationObserver . Хитрость заключается в том, что вместо сохранения изменений вашего состояния в переменной status , сохраните его в невидимом DIV и, используя MutationObserver, мы можем запустить событие, как только изменится свойство innerHTML в DIV.

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>
...