Улучшить эту документациюИнтерполяция и привязка данных
Маркер интерполяции со встроенными выражениями используется AngularJS для привязки данных к текстовым узлам и значениям атрибутов.
Пример интерполяции показан ниже:
<a ng-href="img/{{username}}.jpg">Hello {{username}}!</a>
Как работают привязки текста и атрибутов
Во время процесса компиляции компилятор компилятор использует службу $interpolate для проверки, содержат ли текстовые узлы и атрибуты элементов маркеры интерполяции со встроенными выражениями.
В этом случае компилятор добавляет директиву interpolate к узлу и регистрирует наблюдения за вычисляемой функцией интерполяции, которая будет обновлять соответствующие текстовые узлы или значения атрибутов как часть обычного цикла переваривания.
Обратите внимание, что у interpolateDirective есть приоритет 100 и он устанавливает наблюдение в функции preLink.
Как вычисляется строковое представление
Если интерполируемое значение не является String, оно вычисляется следующим образом:
-
undefinedиnullпреобразуются в'' - если значение является объектом, который не является
Number,DateилиArray, $interpolate ищет пользовательскую функциюtoString()в объекте и использует её. Пользовательская функция означает, чтоmyObject.toString !== Object.prototype.toString. - если вышеперечисленные условия не выполняются, используется
JSON.stringify.
Привязка к булевым атрибутам
Атрибуты, такие как disabled, называются boolean атрибутами, потому что их присутствие означает true, а их отсутствие означает false. Мы не можем использовать обычные привязки атрибутов с ними, потому что спецификация HTML не требует от браузеров сохранять значения булевых атрибутов. Это означает, что если мы поместим выражение AngularJS интерполяции в такой атрибут, информация о привязке будет утеряна, потому что браузер игнорирует значение атрибута.
В следующем примере информация об интерполяции будет проигнорирована, и браузер просто интерпретирует атрибут как присутствующий, что означает, что кнопка всегда будет отключена.
Disabled: <input type="checkbox" ng-model="isDisabled" />
<button disabled="{{isDisabled}}">Disabled</button>
По этой причине AngularJS предоставляет специальные директивы с префиксом ng для следующих булевых атрибутов: disabled, required, selected, checked, readOnly и open.
Эти директивы принимают выражение внутри атрибута и устанавливают соответствующий булев атрибут в значение true, когда выражение оценивается как истинное.
Disabled: <input type="checkbox" ng-model="isDisabled" /> <button ng-disabled="isDisabled">Disabled</button>
ngAttr для привязки к произвольным атрибутам
Веб-браузеры иногда избирательны в отношении того, какие значения они считают допустимыми для атрибутов.
Например, рассмотрим этот шаблон:
<svg>
<circle cx="{{cx}}"></circle>
</svg>
Мы ожидали бы, что AngularJS сможет привязаться к этому, но при проверке консоли мы видим что-то вроде Error: Invalid value for attribute cx="{{cx}}". Из-за ограничений API DOM SVG вы не можете просто написать cx="{{cx}}".
С помощью ng-attr-cx вы можете обойти эту проблему.
Если атрибут с привязкой имеет префикс ngAttr (денормализован как ng-attr-), то во время привязки он будет применён к соответствующему атрибуту без префикса. Это позволяет привязываться к атрибутам, которые в противном случае обрабатывались бы браузерами (например, атрибуты circle[cx] элемента SVG). При использовании ngAttr, используется флаг allOrNothing службы $interpolate, поэтому если какое-либо выражение в интерполированной строке приводит к undefined, атрибут удаляется и не добавляется к элементу.
Например, мы могли бы исправить пример выше, написав:
<svg>
<circle ng-attr-cx="{{cx}}"></circle>
</svg>
Если нужно изменить атрибут с верблюжьей нотацией (элементы SVG имеют допустимые атрибуты с верблюжьей нотацией), такие как viewBox для элемента svg, можно использовать нижнее подчеркивание для обозначения того, что атрибут для привязки имеет естественную верблюжью нотацию.
Например, чтобы привязаться к viewBox, можно написать:
<svg ng-attr-view_box="{{viewBox}}">
</svg>
Другие атрибуты также могут не работать должным образом, когда они содержат маркеры интерполяции, и их можно использовать с ngAttr вместо этого. Ниже приведён список известных проблемных атрибутов:
-
size в элементах
<select>(см. вопрос 1619) -
placeholder в
<textarea>в Internet Explorer 10/11 (см. вопрос 5025) -
type в
<button>в Internet Explorer 11 (см. вопрос 14117) -
value в
<progress>в Internet Explorer 11 (см. вопрос 7218)
Известные проблемы
Динамическое изменение интерполируемого значения
Следует избегать динамического изменения содержимого интерполированной строки (например, значения атрибута или текстового узла). Ваши изменения, скорее всего, будут перезаписаны, когда исходная строка будет оценена. Это ограничение относится как к прямому изменению содержимого с помощью JavaScript, так и к непрямому использованию директивы.
Например, не следует использовать интерполяцию в значении атрибута style (например, style="color: {{ 'orange' }}; font-weight: {{ 'bold' }};") и одновременно использовать директиву, которая изменяет содержимое этого атрибута, например ngStyle.
Встраивание маркеров интерполяции внутри выражений
<div ng-show="form{{$index}}.$invalid"></div>
Вместо этого следует делегировать вычисление сложных выражений области видимости, как показано ниже:
<div ng-show="getForm($index).$invalid"></div>
function getForm(index) {
return $scope['form' + index];
}
Вы также можете получить доступ к scope с помощью this в шаблонах:
<div ng-show="this['form' + $index].$invalid"></div>
Почему смешивание интерполяции и выражений — плохая практика:
- Это увеличивает сложность разметки
- Нет гарантии, что это работает для каждой директивы, потому что сама интерполяция является директивой. Если другая директива получает доступ к данным атрибута до выполнения интерполяции, она получит исходный маркер интерполяции, а не данные.
- Это влияет на производительность, так как интерполяция добавляет ещё одно наблюдение в область видимости.
- Поскольку это не рекомендуется, мы не тестируем это, и изменения в ядре AngularJS могут сломать ваш код.
© 2010–2020 Google, Inc.
Licensed under the Creative Commons Attribution License 3.0.
https://code.angularjs.org/1.8.2/docs/guide/interpolation