Подтвердить что ты не робот

Knockout.js с использованием `value:` привязка в `foreach` над списком строк - не обновляет

Вот jsFiddle, демонстрирующий следующую проблему:

Учитывая привязку foreach к списку (наблюдаемых) строк, наблюдаемые, похоже, не обновляются из изменений в теги ввода, связанные внутри foreach. Можно было бы ожидать их. Вот пример из jsFiddle:

HTML

<ul data-bind='foreach: list'>
    <li><input data-bind='value: $data'/></li>
</ul>

<ul data-bind='foreach: list'>
    <li><span data-bind='text: $data'></span></li>
</ul>

Javascript

​var vm = { list: [ko.observable('123'), ko.observable('456')] };
ko.applyBindings(vm);​

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

Я проверил, что список не обновлялся при изменении входных элементов. Интересно, что изменения, внесенные в наблюдаемые, отражаются в обоих списках (как и следовало ожидать). А именно, vm.list[1]("444") обновит второй элемент обоих списков.

Мое воспоминание о том, что у Knockout 2.0.0 не было этой проблемы, хотя я должен быть исправлен. Я не нашел никакой документации, Google или комментариев в коде Knockout, которые дали какие-либо указания относительно того, почему это не работает или как добиться ожидаемого результата.

Почему это работает не так, как ожидалось, и существуют ли какие-либо обходные пути, которые не требуют изменения структуры данных?

4b9b3361

Ответ 1

Я работал над этим, используя value: $parent.list[$index()], как показано в этот jsFiddle. Новые привязки выглядят следующим образом:

<ul data-bind='foreach: list'>
    <li>
        <input data-bind='value: $parent.list[$index()]' />
    </li>
</ul>

Можно было бы улучшить это с помощью специальной привязки.

См. также этот связанный вопрос GitHub # 708 для Knockout.js.

Обновление для нокаута 3.0:

Нокаут теперь предоставляет $rawData:

<ul data-bind='foreach: list'>
    <li><input data-bind='value: $rawData'/></li>
</ul>

создает двустороннюю привязку, как ожидалось.

Из документа Binding Context:

$RAWDATA

Это значение модели исходного представления в текущем контексте. Обычно это будет таким же, как и $data, но если модель представления предоставлена ​​Knockout обернута в наблюдаемый, $data будет развернутой моделью просмотра, и $rawData будет наблюдаемым.

Ответ 2

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

Наблюдаемые должны быть свойствами объекта, а не заменой самого объекта. Установите наблюдаемые как свойство некоторого объекта, чтобы этого не произошло.

​var vm = {
    list: [
        { value: ko.observable('123') },
        { value: ko.observable('456') }
    ]
};
<ul data-bind='foreach: list'>
    <li><input data-bind='value: value'/></li>
</ul>

<ul data-bind='foreach: list'>
    <li><span data-bind='text: value'></span></li>
</ul>