В Knockout применяется концепция иерархии контекстов привязки для родительских и дочерних элементов html.
В Knockout есть ряд встроенных переменных, с помощью которых можно обращаться к различным уровням иерархии контекстов привязки:
$root: представляет корневой контекст привязки (то есть непосредственно объект ViewModel) в любом из дочерних контекстов
$parent: позволяет получить данные родительского контекста по отношению к текущему
$parents: позволяет получить все родительские контексты вверх по иерархии вплоть до корневого контекста.
Представляет массив контекстов, где $parents[0]
является самым ближним родительским контекстом и аналогичен $parent
.
А последний контекст в этом массе $parents[$parents.length - 1]
аналогичен значению $root, то есть представляет корневой контекст.
$data: предоставляет доступ к модели данных в текущем контексте
$rawData: также предоставляет доступ к модели данных в текущем контексте привязки и может рассматриваться как аналог $data. Но если модель данных представляет наблюдаемый объект (observable), то $data предоставляет доступ к той модели, которая помещена в observable, а $rawData представляет сам observable
$index: используется в циклах для доступа к элементам набора по индексу
$element: позволяет получить доступ к элементу. Например:
<div id="content" data-bind="text: $element.id"></div>
Пример обращения к разным контекстам:
<div data-bind="with: company"> <h2 data-bind="text: $root.model"></h2> <p data-bind="text: name"></p> <p data-bind="text: country"></p> <p>Цена: <span data-bind="text: $parent.price"></span></p> </div> <script> var phoneViewModel = { model: "Galaxy S7 Edge", price: 50000, company:{ name: "Samsung", country: "Республика Корея" } }; ko.applyBindings(phoneViewModel); </script>
Блок div здесь в рамках контекста привязки ограничен объектом company
. Поскольку свойства name
и price
расположены уровнем выше в
корне ViewModel, то мы можем получить к ним доступ через ключевое слово $parent
или $root
:
<p>Цена: <span data-bind="text: $parent.price"></span></p>
или так:
<p>Цена: <span data-bind="text: $root.price"></span></p>
Использование индексов при выводе элементов массива:
<div data-bind="foreach: phones"> <p><span data-bind="text: ($index() + 1)"></span>. <span data-bind="text: $data"></span></p> </div> <script> var phoneViewModel = { phones: ["Galaxy S7", "iPhone SE", "LG G5"] }; ko.applyBindings(phoneViewModel); </script>
Привязка with создает новый контекст привязки, благодаря чему для вложенных элементов устанавливается привязка к определенному объекту внутри ViewModel.
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Привязка в KnockoutJS</title> </head> <body> <h2 data-bind="text: model"></h2> <p>Цена: <span data-bind="text: price"></span></p> <h3>Производитель</h3> <div data-bind="with: company"> <p data-bind="text: name"></p> <p data-bind="text: country"></p> </div> <script type="text/javascript" src="https://ajax.aspnetcdn.com/ajax/knockout/knockout-3.4.0.js"></script> <script> var phoneViewModel = { model: "Galaxy S7 Edge", price: 50000, company:{ name: "Samsung", country: "Республика Корея" } }; ko.applyBindings(phoneViewModel); </script> </body> </html>
Здесь для вложенного блока div в качестве контекста устанавливается не весь объект ViewModel, а только объект company
внутри ViewModel:
<div data-bind="with: company">
Далее в этом блоке div ко всем вложенным элементам мы можем использовать привязку напрямую к свойствам объекта company:
<div data-bind="with: company"> <p data-bind="text: name"></p> <p data-bind="text: country"></p> </div>
То есть если для всего представления в виде веб-страницы в качестве контекста привязки используется вся ViewModel - объект phoneViewModel, то конкретно для этого блока контекстом привязки является только объект company. А всех тех свойств, которые существуют вне объекта company, например, свойство model или price, они для блока div не существуют.
Но так как эти свойства находятся в родительском контексте, то через ключевое слово $parent
мы можем получить к ним доступ:
<div data-bind="with: company"> <p data-bind="text: name"></p> <p data-bind="text: country"></p> <p>Цена: <span data-bind="text: $parent.price"></span></p> </div>