Как заставить функцию устранения дребезга действовать независимо от разных экземпляров одного и того же компонента на Vue.js?

У меня есть два компонента Vue, у которых есть вызов «сохранить на диск» при каждом изменении данных, он загружается в эти компоненты через миксин, и каждый компонент сохраняется в другой файл, поэтому они должны функционировать независимо (только запускать сброс дребезга при собственное изменение данных). Чтобы предотвратить слишком много записи на диск. Вот моя функция отката:

function debounce(fn, delay) {
  var timeoutID = null;
  return function () {
    console.log("clearing " + timeoutID)
    clearTimeout(timeoutID);
    var args = arguments;
    var that = this;
    timeoutID = setTimeout(() => fn.apply(that, args), delay);
  };
}

Вот методы моего миксина, которые наследуют компоненты:

  methods: {
    saveData: debounce(function(){
        console.log('saving widget: ' + this.$parent.widget.id);
        this.saver.store = this.persisted;
    }, 5000),
  },

Это хорошо работает, когда я меняю данные в одном или другом компоненте, но когда я меняю данные в одном и до окончания устранения дребезга я изменяю другой, он отменяет мою функцию устранения дребезга из первого и сохраняет только данные второго компонента. .

Что мне здесь не хватает?


person sigmawf    schedule 02.06.2020    source источник
comment
Вероятно, потому что вы очищаете тайм-аут в начале вашего метода. timeoutID всегда выглядит нулевым.   -  person Gabriel Willemann    schedule 02.06.2020


Ответы (2)


Это связано с тем, что каждый экземпляр компонента использует одну и ту же отмененную функцию, меняется только контекст (this, that).

Простым обходным путем было бы изменить вашу реализацию debounce на


function debounce(fn, delay) {
  var thatUidToTimeoutID = {};
  return function () {
    var args = arguments;
    var that = this;
    clearTimeout(thatUidToTimeoutID[that._uid]);
    thatUidToTimeoutID[that._uid] = setTimeout(() => fn.apply(that, args), delay);
  };
}

_uid содержит уникальный идентификатор каждого компонента, это скорее внутреннее свойство (отсюда и странный ключ), но этого должно быть достаточно.

person Kamil Bęben    schedule 02.06.2020
comment
имеет смысл ... поскольку debounce является глобальной функцией в моем случае для нескольких сценариев, что произойдет, если я использую эту функцию вне компонента vue? - person sigmawf; 02.06.2020
comment
Что касается версии, зависящей от поля _uid, то она зависит от контекста. Если контекст равен нулю, вы получите сообщение об ошибке Can't read property _uid of undefined, в противном случае он будет вести себя так же, как исходная функция debounce (при условии, что _uid не определено или является неизменяемой строкой/числом/логическим свойством, потому что все они являются допустимыми ключами в js объект). - person Kamil Bęben; 02.06.2020

Сегодня я столкнулся с той же проблемой. Я пробовал что-то другое, что, на мой взгляд, немного чище. Вместо того, чтобы определять функцию debounce в блоке методов, как вы это делали, попробуйте определить ее как часть данных следующим образом:

  data() {
   return {
    saveData: debounce(function(){
        console.log('saving widget: ' + this.$parent.widget.id);
        this.saver.store = this.persisted;
    }, 5000)
  }
 }

Вы можете вызвать метод так же, как обычно. Из документов: параметр данных компонента должен быть функцией, чтобы каждый экземпляр мог поддерживать независимую копию возвращаемого объекта данных. Таким образом, каждый экземпляр, использующий функцию debounce, будет иметь свой собственный уникальный экземпляр.

Подробнее о том, как это работает, можно узнать здесь: https://vuejs.org/v2/guide/components.html#data-Must-Be-a-Function

person Nicolas D    schedule 21.04.2021