Улучшить эту документациюИнтерполяция и привязка данных
Маркер интерполяции со встроенными выражениями используется AngularJS для привязки данных к текстовым узлам и значениям атрибутов.
Пример интерполяции показан ниже:
<a ng-href="img/{{username}}.jpg">Hello {{username}}!</a>
Как работают привязки текста и атрибутов
Во время процесса компиляции компилятор использует $interpolate сервис, чтобы определить, содержат ли текстовые узлы и атрибуты элементов маркер интерполяции со встроенными выражениями.
В случае наличия компилятор добавляет interpolateDirective к узлу и регистрирует наблюдения за вычисленной функцией интерполяции, которая будет обновлять соответствующие текстовые узлы или значения атрибутов в рамках обычного цикла переваривания.
Обратите внимание, что 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 SVG DOM вы не можете просто написать 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–2018 Google, Inc.
Licensed under the Creative Commons Attribution License 4.0.
https://code.angularjs.org/1.6.9/docs/guide/interpolation