不使用数据绑定呈现值

在 AngularJS 中,如何在没有双向数据绑定的情况下呈现值?出于性能方面的原因,人们可能希望这样做,甚至在给定的时间点呈现一个值。

以下示例都使用数据绑定:

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

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

如何呈现 value 没有数据绑定?

49750 次浏览

Use the bindonce module. You'll need to include the JS file and add it as a dependency to your app module:

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

This library allows you to render items that are bound only once — when they are first initialized. Any further updates to those values will be ignored. It's a great way to reduce the number of watches on the page for things that won't change after they are rendered.

Usage example:

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

When used like this, the property under value will be set once it is available, but then the watch will be disabled.

Angular 1.3+

In 1.3, Angular has supported this using the following syntax.

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

As mentioned in this answer.


Angular 1.2 and below

This is simple and doesn't need a plugin. Check this out.

This small directive will easily accomplish what you are trying to achieve

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

You can bind once like this

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

You can bind like normal

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

Demo: http://jsfiddle.net/fffnb/

Some of you may be using angular batarang, and as mentioned in the comments if you use this directive the element still shows as binding when it is not, I am pretty sure this has something to do with the classes that are attached to the element so try this, it should work (not tested). Let me know in the comments if it worked for you.

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

@x0b: If you have OCD and you want to remove the empty class attribute do this

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

Comparison between @OverZealous and @Connor answers :

With the traditional ngRepeat of angular : 15s for 2000 rows and 420mo of RAM (Plunker)

With ngRepeat and the module of @OverZealous : 7s for 2000 rows and 240mo of RAM(Plunker)

With ngRepeat and the directive of @Connor : 8s for 2000 rows and 500mo of RAM (Plunker)

I made my tests with Google Chrome 32.

It looks like Angular 1.3 (starting with beta 10) has one-time binding built in:

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

One-time binding

An expression that starts with :: is considered a one-time expression. One-time expressions will stop recalculating once they are stable, which happens after the first digest if the expression result is a non-undefined value (see value stabilization algorithm below).

As an alternative, there is angular-once package:

If you use AngularJS, have performance issues and need to display lots of readonly data, this project is for you!

angular-once was actually inspired by bindonce and provides similar once-* attributes:

<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>