valueAccessor() возвращает сигнатуру функции вместо значения во время создания пользовательской привязки

Я новичок в Knockout.js и следил за учебником. Однако мой код не работает должным образом, потому что в моей пользовательской привязке createDecimal, valueAccessor() вместо фактического значения возвращается сигнатура функции.

Я использую последнюю версию Knockout.js на сегодняшний день, v3.4.2.

<p>First Name <strong data-bind="text: firstName"></strong></p>
<p>Last Name <strong data-bind="text: lastName"></strong></p>
<p>Change First Name <input data-bind="value: firstName, valueUpdate: 'afterkeydown'" type="text" name="firstName"></p>
<p>Change Last Name <input data-bind="value: lastName, valueUpdate: 'afterkeydown'" , type="text" name="lastName"></p>
<p>Full Name: <strong data-bind="text: fullName"></strong></p>
<p>Add new hobby: <input data-bind="value: hobby, valueUpdate: 'afterkeydown'" type="text" name="hobby"><button data-bind="click: addHobby">Add</button></p>
<p>Hobby to possibly be added: <strong data-bind="text: hobby"></strong></p>
<ul data-bind="foreach: hobbies">
  <div>
    <li data-bind="text: $data"></li>
    <button data-bind="click: $parent.removeHobby">Remove Hobby</button>
  </div>
</ul>
<p>Total Number of Properties: <strong data-bind="makeDecimal: numberOfHobbies"></strong></p>

<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<script type="text/javascript">
  ko.bindingHandlers.makeDecimal = {
    update: function(element, valueAccessor) {
      var numberOfHobbies = valueAccessor();
      console.log("Number of Hobbies", numberOfHobbies);
      var formattedText = "$" + numberOfHobbies.toFixed();
      element.innerText = formattedText;
    }
  };

  function IndexViewModel() {
    var self = this;
    self.firstName = ko.observable("George");
    self.lastName = ko.observable("Lopez");
    self.hobby = ko.observable();
    self.hobbies = ko.observableArray(["Acting", "Joking", "Speaking"]);
    self.addHobby = function() {
      self.hobbies.push(self.hobby());
    };
    self.removeHobby = function(hobby) {
      self.hobbies.remove(hobby);
    };

    self.fullName = ko.computed(function() {
      return self.firstName() + " " + self.lastName();
    });

    self.numberOfHobbies = ko.computed(function() {
      return self.hobbies().length;
    });

  }

  ko.applyBindings(new IndexViewModel());
</script>


person Govind Rai    schedule 24.06.2017    source источник
comment
Вам просто нужно добавить ko.track(this); в конце IndexViewModel: codepen.io/anon/pen/qjPavm. И, конечно же, используйте плагин (cdnjs .cloudflare.com/ajax/libs/knockout-es5/0.4.6/).   -  person Jose Luis    schedule 25.06.2017


Ответы (1)


Это неестественно, но здесь нужно использовать ko.unwrap(), чтобы получить значение наблюдаемого.

ko.bindingHandlers.makeDecimal = {
    update: function(element, valueAccessor) {
        var numberOfHobbies = ko.unwrap(valueAccessor());
        console.log("Number of Hobbies", numberOfHobbies);
        var formattedText = "$" + numberOfHobbies.toFixed();
        element.innerText = formattedText;
    }
};

Это из-за того, как Knockout управляет наблюдаемыми, заменяя их функциями.

person Jimbot    schedule 24.06.2017
comment
Спасибо, Джимбот. Это решает проблему! Это очень странно, потому что я следил за учебником Стива Сандерсона (первоначального автора), и его код не требовал разворачивания, хотя он получал значение вычисляемого свойства. - person Govind Rai; 25.06.2017
comment
См. видео. В 19:13 он создает пользовательскую привязку для добавления форматирования валюты к вычисляемому свойству grandTotal и никогда не разворачивает вычисляемое свойство в своей пользовательской привязке currencyText... - person Govind Rai; 25.06.2017
comment
Да, это странно, не уверен, почему это работает для него в то время. Во всяком случае, я нахожу это о разнице между () и unwrap. Кроме того, я где-то читал, что наблюдаемые функции - это функции, потому что в большинстве браузеров javascript не поддерживает инкапсулированные свойства (getter setter). Но не могу вспомнить где... - person Jimbot; 25.06.2017
comment
По этой ссылке (knockoutjs.com/documentation/custom-bindings.html) они получают последнее значение с var value = valueAccessor();. Если свойство не является наблюдаемым, то у вас есть правильное значение. Если это наблюдаемая, то value является функцией, и получить значение можно с помощью var valueUnwrapped = ko.unwrap(value);. ko.unwrap() можно вызывать и для ненаблюдаемых объектов, тогда его можно было бы использовать всегда. - person Jose Luis; 25.06.2017
comment
В этом видео автор использует собственный плагин (blog.stevensanderson.com/2013/05/20/) для упрощения синтаксиса. Вы также можете увидеть эту ссылку (stackoverflow.com/questions/44414554/), в котором рассказывается о новой версии Knockout. - person Jose Luis; 25.06.2017