Knockout extender, заставляющий observable возвращать значение по умолчанию при первом проходе независимо от ввода - PullRequest
0 голосов
/ 01 ноября 2019

Я определил модель представления под названием model.customDifficultySettings, часть которой показана ниже. Он использует расширитель с прецизионной точностью, который является просто переименованной версией примера расширителя для округления до десятичных дробей X, показанных в документации Knockout.js.

ko.extenders.precision = function(target, precision) {
  //create a writable computed observable to intercept writes to our observable
  var result = ko
    .pureComputed({
      read: target, //always return the original observables value
      write: function(newValue) {
        var current = target(),
          roundingMultiplier = Math.pow(10, precision),
          newValueAsNum = isNaN(newValue) ? 0 : +newValue,
          valueToWrite =
            Math.round(newValueAsNum * roundingMultiplier) / roundingMultiplier;

        //only write if it changed
        if (valueToWrite !== current) {
          target(valueToWrite);
        } else {
          //if the rounded value is the same, but a different value was written, force a notification for the current field
          if (newValue !== current) {
            target.notifySubscribers(valueToWrite);
          }
        }
      }
    })
    .extend({ notify: "always" });

  //initialize with current value to make sure it is rounded appropriately
  result(target());

  //return the new computed observable
  return result;
};

model.customDifficultySettings = {
  econBase: ko
    .observable(0)
    .extend({ rateLimit: { timeout: 750 }, precision: 3 }),
};

В более поздней функции makeGame() мы гарантируем, что наша model.customDifficultySettings.econBase() наблюдаемый соответствует значению выбранного значения сложности

        model.customDifficultySettings.econBase(
          difficultyInfo[model.newGameDifficultyIndex() || 0].econBase
        );
        console.log(model.customDifficultySettings.econBase());
        console.log(difficultyInfo[model.newGameDifficultyIndex() || 0].econBase);

Значение difficultyInfo[model.newGameDifficultyIndex()].econBase при первом запуске составляет 0,55. Я ожидаю, что консоль будет либо показывать оба значения как 0,55, либо, если что-то пошло не так, оба значения равны 0. Но возвращаемое значение равно 0 для наблюдаемого, но 0,55 для значения, вводимого в него.

Если язапросите наблюдаемое из консоли после запуска кода, он возвращает ожидаемое значение 0,55.

Если уровень сложности изменяется, что приводит к повторному запуску makeGame(), все значения устанавливаются правильно. Эта проблема возникает только при первом запуске.

Я отследил проблему до точного расширителя. Удалите расширитель и все работает как положено. Но так как я только что скопировал код примера, мне не совсем понятно, что он делает и, следовательно, почему эта проблема возникает.

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

1 Ответ

0 голосов
/ 04 ноября 2019

Проблемы возникают, потому что я сначала объявил rateLimit. Если я переверну это и сначала объявлю precision, то все будет работать как положено. Итак, моя модель теперь выглядит так:

model.customDifficultySettings = {
  econBase: ko
    .observable(0)
    .extend({ precision: 3, rateLimit: { timeout: 750 } }),
};
...