Значення візуалізації без прив'язки даних


87

В AngularJS, як я можу відтворити значення без двостороннього прив'язки даних? Можна захотіти зробити це з міркувань продуктивності, або навіть відтворення значення в певний момент часу.

У наступних прикладах обидва використовують прив'язку даних:

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

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

Як зробити візуалізацію value без прив'язки даних?


який ваш вхід і вихід. plz пояснення
Nitish Kumar

3
Ваші приклади насправді є одностороннім прив'язуванням даних (зміни моделі -> перегляд оновлень). ng-modelнадає двостороннє прив'язку даних: зміни моделі -> перегляд оновлень, перегляд змін -> оновлення моделі.
Mark Rajcok

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

10
Я не думаю, що це питання є жахливим або заслуговує на голосування. Насправді дуже часто потрібно вимкнути прив'язку даних, щоб запобігти непотрібним годинникам.
OverZealous

4
ОНОВЛЕННЯ: будь-хто, хто читає цю статтю, виявить це відео надзвичайно корисним. youtube.com/watch?v=zyYpHIOrk_Y
Blowsie

Відповіді:


141

Кутова 1,3+

У версії 1.3 Angular підтримує це, використовуючи такий синтаксис.

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

Як зазначено у цій відповіді .


Кутова 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/

Деякі з вас, можливо, використовують кутовий batarang, і, як згадувалося в коментарях, якщо ви використовуєте цю директиву, елемент все ще відображається як прив'язуючий, коли це не так, я майже впевнений, що це має щось спільне з класами, прикріпленими до елемента, тому спробуйте це, це повинно спрацювати (не перевірено) . Повідомте мене в коментарях, чи це спрацювало у вас.

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

@ x0b : Якщо у вас OCD і ви хочете видалити порожній classатрибут, зробіть це

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

я ще не тестую плагін, але я б припустив, що інструменти AngularJS chrome не відображатимуть елемент bind-Once як прив'язку, де, як це робить ваш приклад. Цікавий підхід, я скоро протестую обидва підходи.
Blowsie

Дивіться це - це відображає як прив’язки dl.dropboxusercontent.com/u/14037764/Development/stackoverflow/…
Blowsie

1
Без сумніву, це тому, що якщо клас ng-прив'язки, який ви можете легко видалити
iConnor

4
Це чудово і набагато простіше, ніж плагін bindonce. Я додав можливість чекати умови перед тим, як знищити область дії, і це дійсно корисно. Дякую.
Ярон

1
@Connor Я не згоден. Наприклад, я отримую відеооб’єкт ($ 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 (починаючи з бета-версії 10) вбудовано одноразове прив’язування:

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

Одноразова палітурка

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


1
Ця відповідь знову і знову. Я не можу похвалити тебе досить Карл! Я настійно рекомендую агресивне використання цієї функції там, де це має сенс.
XDS

1
Ого, я дуже рада, що прокрутила вниз. Я попрошу Коннора посилатися на це у своїй прийнятій відповіді.
JSager

У мене є таблиця / список із 2000 рядків, і за допомогою оператора одноразової прив'язки мій додаток стає надзвичайно повільним під час першого показу / відтворення списку. Настільки повільний, що браузер запитує мене два-три рази, чи хочу я припинити виконувати сценарій!
Billy G

@ billy-g Чи можете ви опублікувати jsfiddle або plunker, що ілюструє проблему?
James Daily

@James Daily: Ось "звичайний" випадок plnkr.co/edit/rCRP0T5fSgNIllx7F27y, а тут випадок "одноразового виразу" plnkr.co/edit/Rd5VBVjkcX3sTJYGypUr, але ... я не можу його там відтворити. У будь-якому випадку, це не швидше з "одноразовим виразом", і я повинен провести більше розслідування, щоб з'ясувати, чому це трапляється у моєму середовищі (я використовую 1.3 бета-версію 18 angularjs)
Біллі Г,

20

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

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

Ця бібліотека дозволяє візуалізувати елементи, які пов’язані лише один раз - при їх першій ініціалізації. Будь-яке подальше оновлення цих значень буде проігноровано. Це чудовий спосіб зменшити кількість переглядів на сторінці для речей, які не будуть змінюватися після їх відтворення.

Приклад використання:

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

При такому використанні властивість під valueбуде встановлено, коли воно стане доступним, але тоді годинник буде вимкнено.


1
Я збирався написати відповідь "напишіть свою власну директиву ...", але схоже, хтось це вже зробив для нас, приємно.
Mark Rajcok

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

6
це те, що я шукав, однак я очікував, що щось подібне буде вбудовано в кутовий!
Blowsie

7

Порівняння відповідей @OverZealous та @Connor:

З традиційним ngRepeat кутового: 15 секунд для 2000 рядків і 420mo оперативної пам'яті ( Plunker )

За допомогою ngRepeat та модуля @OverZealous: 7 секунд для 2000 рядків та 240 місяців оперативної пам'яті ( Plunker )

За допомогою ngRepeat та директиви @Connor: 8 с для 2000 рядків та 500 міс оперативної пам'яті ( 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.