Отображать значение без привязки данных


87

Как в AngularJS отобразить значение без двусторонней привязки данных? Это может потребоваться из соображений производительности или даже для визуализации значения в заданный момент времени.

В следующих примерах используется привязка данных:

<div>{{value}}</div>

<div data-ng-bind="value"></div>

Как выполнить рендеринг value без привязки данных?


каков ваш ввод и вывод. пожалуйста, объясните
Нитиш Кумар

3
Ваши примеры на самом деле являются односторонней привязкой данных (изменения модели -> просмотр обновлений). ng-modelдает вам двустороннюю привязку данных: изменения модели -> просмотр обновлений, просмотр изменений -> обновления модели.
Марк Райкок

1
обновлено. извините, я имел в виду, что не хочу никакой привязки данных вообще
Blowsie

10
Я не думаю, что этот вопрос ужасен или заслуживает отрицательной оценки. На самом деле очень часто хочется отключить привязку данных, чтобы предотвратить ненужные наблюдения.
OverZealous

4
ОБНОВЛЕНИЕ: любой, кто читает эту статью, вероятно, найдет это видео чрезвычайно полезным. youtube.com/watch?v=zyYpHIOrk_Y
Blowsie

Ответы:


141

Угловой 1.3+

В версии 1.3 Angular поддерживал это, используя следующий синтаксис.

<div>{{::message}}</div>

Как упоминалось в этом ответе .


Angular 1.2 и ниже

Это просто и не требует плагина. Проверь это.

Эта небольшая директива легко выполнит то, что вы пытаетесь достичь.

app.directive('bindOnce', function() {
    return {
        scope: true,
        link: function( $scope ) {
            setTimeout(function() {
                $scope.$destroy();
            }, 0);
        }
    }
});

Вы можете привязать один раз вот так

<div bind-once>I bind once - {{message}}</div>

Вы можете связать как обычно

<div ng-bind="message" bind-once></div>

Демо: http://jsfiddle.net/fffnb/

Некоторые из вас могут использовать angular batarang, и, как упоминалось в комментариях, если вы используете эту директиву, элемент по-прежнему отображается как привязка, когда это не так, я почти уверен, что это как-то связано с классами, которые прикреплены к элементу, поэтому попробуйте это, он должен работать (не проверено) . Дайте мне знать в комментариях, если это сработало для вас.

app.directive('bindOnce', function() {
    return {
        scope: true,
        link: function( $scope, $element ) {
            setTimeout(function() {
                $scope.$destroy();
                $element.removeClass('ng-binding ng-scope');
            }, 0);
        }
    }
});

@ x0b : если у вас ОКР и вы хотите удалить пустой classатрибут, сделайте это

!$element.attr('class') && $element.removeAttr('class')

Я еще не тестировал плагин, но я бы предположил, что инструменты Chrome AngularJS не будут отображать элемент bind-once как привязку, где, как это делает ваш пример. Интересный подход, но скоро я опробую оба подхода.
Blowsie

См. Это - он показывает оба как привязки dl.dropboxusercontent.com/u/14037764/Development/stackoverflow/…
Blowsie

1
Без сомнения, это потому, что если класс ng-binding, который вы можете легко удалить
iConnor

4
Это здорово и намного проще, чем плагин bindonce. Я добавил возможность дождаться состояния, прежде чем уничтожить прицел, и это действительно полезно. Спасибо.
Yaron

1
@ Коннор Я не согласен. Например, я получаю видеообъект ($ scope.video) из REST API и хочу одноразовую привязку заголовка видео ($ scope.video.title). Даже если я разрешаю обещание ПЕРЕД добавлением его в область видимости в контроллере, мне все равно придется объявить ng-bind = "video.title" bind-once в DOM. Теперь, прежде чем обещание будет разрешено, video.title не определено, а область видимости будет уничтожена до определения video.title. У меня есть решение для этого - заключить элементы в какой-то тип флага загрузки / инициализации, ng-if = "someLoadingFlag", но это плохой шаблон.
SirTophamHatt

49

Похоже, что в Angular 1.3 (начиная с beta 10) встроена одноразовая привязка:

https://docs.angularjs.org/guide/expression#one-time-binding

Одноразовая привязка

Выражение, которое начинается с ::, считается одноразовым выражением. Одноразовые выражения перестанут пересчитываться, как только они станут стабильными, что происходит после первого дайджеста, если результатом выражения является не неопределенное значение (см. Алгоритм стабилизации значения ниже).


1
Этот ответ снова и снова. Я не могу достаточно хвалить тебя, Карл! Я настоятельно рекомендую активно использовать эту функцию везде, где это имеет смысл.
XDS

1
Вау, я действительно рад, что прокрутил страницу вниз. Я попрошу Коннора упомянуть об этом в принятом ответе.
JSager

У меня есть таблица / список с 2000 строками, и с использованием оператора одноразовой привязки мое приложение становится очень медленным при первом отображении / рендеринге списка. Настолько медленно, что браузер два или три раза спрашивает меня, хочу ли я прекратить выполнение скрипта!
Billy G

@ billy-g Можете ли вы опубликовать jsfiddle или plunker, иллюстрирующие проблему?
Джеймс Дейли,

@James Daily: Вот "нормальный" случай plnkr.co/edit/rCRP0T5fSgNIllx7F27y, а здесь случай "одноразового выражения" plnkr.co/edit/Rd5VBVjkcX3sTJYGypUr, но ... я не могу воспроизвести его там. В любом случае, это не быстрее с «одноразовым выражением», и мне нужно провести дополнительное исследование, чтобы выяснить, почему это происходит в моей среде (я использую 1.3 beta 18 angularjs)
Билли Джи

20

Используйте модуль bindonce . Вам нужно будет включить JS-файл и добавить его как зависимость к вашему модулю приложения:

var myApp = angular.module("myApp", ['pasvaz.bindonce']);

Эта библиотека позволяет отображать элементы, которые связаны только один раз - при их первой инициализации. Любые дальнейшие обновления этих значений будут проигнорированы. Это отличный способ уменьшить количество отслеживаний на странице вещей, которые не изменятся после рендеринга.

Пример использования:

<div bo-text="value"></div>

При таком использовании свойство ниже valueбудет установлено, как только оно станет доступным, но затем часы будут отключены.


1
Я собирался написать ответ «напишите свою директиву ...», но похоже, что кто-то уже сделал это за нас, приятно.
Марк Райкок

3
Bindonce достаточно полезен, чтобы его можно было включить как встроенную дополнительную библиотеку, например $resource.
OverZealous

6
это то, что я искал, однако я ожидал, что что-то подобное будет встроено в angular!
Blowsie

7

Сравнение ответов @OverZealous и @Connor:

С традиционным ngRepeat angular: 15 с для 2000 строк и 420 МБ ОЗУ ( Plunker )

С ngRepeat и модулем @OverZealous: 7 с для 2000 строк и 240 млн ОЗУ ( Plunker )

С ngRepeat и директивой @Connor: 8s для 2000 строк и 500mo RAM ( Plunker )

Я провел свои тесты с Google Chrome 32.


1
Было бы неплохо тоже angular-onceсравнить. Спасибо.
alecxe

@alecxe: Я планировал провести тесты, когда будет опубликована стабильная сборка AngularJS 1.3.
Габриэль

Спасибо, не забудьте включить angular-onceпакет (я разместил его здесь как альтернативный вариант).
alecxe

5

В качестве альтернативы есть angular-onceпакет:

Если вы используете AngularJS, имеете проблемы с производительностью и вам нужно отображать много данных только для чтения, этот проект для вас!

angular-onceбыл фактически вдохновлен bindonceи предоставляет похожие once-*атрибуты:

<ul>
    <li ng-repeat="user in users">
      <a once-href="user.profileUrl" once-text="user.name"></a>
        <a once-href="user.profileUrl"><img once-src="user.avatarUrl"></a>
        <div once-class="{'formatted': user.description}" once-bind="user.description"></div>
    </li>
</ul>
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.