Valore di rendering senza associazione dati


87

In AngularJS, come posso eseguire il rendering di un valore senza data binding a 2 vie? Si potrebbe desiderare di farlo per motivi di prestazioni, o anche per rendere un valore in un dato momento.

I seguenti esempi utilizzano entrambi l'associazione dati:

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

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

Come eseguo il rendering value senza alcuna associazione di dati?


qual è il tuo input e output. per favore spiega
Nitish Kumar

3
I tuoi esempi sono in realtà un data binding unidirezionale (modifiche al modello -> visualizza aggiornamenti). ng-modelti offre l'associazione dati a due vie: modifiche al modello -> visualizza aggiornamenti, visualizza modifiche -> aggiornamenti del modello.
Mark Rajcok

1
aggiornato. scusate volevo dire che non voglio alcun collegamento dati
Blowsie

10
Non penso che questa domanda sia terribile o meritasse un voto negativo. In realtà è molto comune voler disabilitare l'associazione dei dati per evitare orologi non necessari.
OverZealous

4
AGGIORNAMENTO: chiunque legga questo articolo troverà probabilmente questo video estremamente utile. youtube.com/watch?v=zyYpHIOrk_Y
Blowsie

Risposte:


141

Angular 1.3+

In 1.3, Angular lo ha supportato utilizzando la seguente sintassi.

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

Come accennato in questa risposta .


Angolare 1.2 e inferiore

Questo è semplice e non necessita di plugin. Controllalo.

Questa piccola direttiva realizzerà facilmente ciò che stai cercando di ottenere

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

Puoi legare una volta in questo modo

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

Puoi legarti come al solito

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

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

Alcuni di voi potrebbero usare il batarang angolare e, come menzionato nei commenti, se usate questa direttiva l'elemento si mostra ancora come vincolante quando non lo è, sono abbastanza sicuro che questo abbia qualcosa a che fare con le classi che sono attaccate all'elemento quindi prova questo, dovrebbe funzionare (non testato) . Fammi sapere nei commenti se ha funzionato per te.

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

@ x0b : se hai un disturbo ossessivo compulsivo e desideri rimuovere l' classattributo vuoto, fallo

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

Devo ancora testare il plug-in, ma presumo che gli strumenti di Chrome di AngularJS non mostrino l'elemento bind-once come vincolante, dove come fa il tuo esempio. Approccio interessante, testerò presto entrambi gli approcci.
Blowsie

Guarda questo - mostra entrambi come binding dl.dropboxusercontent.com/u/14037764/Development/stackoverflow/…
Blowsie

1
Senza dubbio è perché se la classe ng-binding che puoi rimuovere facilmente
iConnor

4
Questo è fantastico e molto più semplice del plugin bindonce. Ho aggiunto la possibilità di attendere una condizione prima di distruggere l'ambito ed è davvero utile. Grazie.
Yaron

1
@Connor Non sono d'accordo. Ad esempio, ricevo un oggetto video ($ scope.video) da un'API REST e desidero il binding una tantum del titolo del video ($ scope.video.title). Anche se risolvo la promessa PRIMA di aggiungerla all'ambito nel controller, devo comunque dichiarare ng-bind = "video.title" bind-once sul DOM. Ora, prima che la promessa venga risolta, video.title non è definito e l'ambito viene distrutto prima che video.title venga definito. Una soluzione che ho per questo è racchiudere gli elementi in un tipo di flag di caricamento / init, ng-if = "someLoadingFlag", ma è un modello scadente.
SirTophamHatt

49

Sembra che Angular 1.3 (a partire dalla beta 10) abbia l'associazione una tantum incorporata:

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

Rilegatura una tantum

Un'espressione che inizia con :: è considerata un'espressione occasionale. Le espressioni occasionali interromperanno il ricalcolo una volta che sono stabili, cosa che accade dopo il primo digest se il risultato dell'espressione è un valore non indefinito (vedere l'algoritmo di stabilizzazione del valore di seguito).


1
Questa risposta ancora e ancora. Non posso lodarti abbastanza Karl! Consiglio vivamente l'uso aggressivo di questa funzione ovunque abbia senso.
XDS

1
Wow, sono davvero contento di aver fatto scorrere verso il basso. Chiederò a Connor di fare riferimento a questo nella sua risposta accettata.
JSager

Ho una tabella / elenco con 2000 righe e utilizzando l'operatore di associazione una tantum la mia app diventa estremamente lenta quando mostra / visualizza l'elenco per la prima volta. Così lento, che il browser mi chiede due o tre volte se voglio interrompere l'esecuzione dello script!
Billy G

@ billy-g Puoi pubblicare un jsfiddle o un plunker che illustri il problema?
James Daily

@James Daily: Ecco il caso "normale" plnkr.co/edit/rCRP0T5fSgNIllx7F27y e qui il caso "espressione una tantum" plnkr.co/edit/Rd5VBVjkcX3sTJYGypUr ma ... non posso riprodurlo lì. Ad ogni modo, non è più veloce con l '"espressione una tantum" e devo fare ulteriori indagini per scoprire perché accade nel mio ambiente (io uso 1.3 beta 18 di angularjs)
Billy G

20

Usa il modulo bindonce . Dovrai includere il file JS e aggiungerlo come dipendenza al modulo dell'app:

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

Questa libreria consente di eseguire il rendering di elementi associati solo una volta, quando vengono inizializzati per la prima volta. Eventuali ulteriori aggiornamenti a tali valori verranno ignorati. È un ottimo modo per ridurre il numero di visualizzazioni sulla pagina per cose che non cambieranno dopo il rendering.

Esempio di utilizzo:

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

Quando viene utilizzato in questo modo, la proprietà sotto valueverrà impostata una volta che è disponibile, ma l'orologio verrà disabilitato.


1
Stavo per scrivere una risposta "scrivi la tua direttiva ...", ma sembra che qualcuno l'abbia già fatto per noi, gentile.
Mark Rajcok

3
Bindonce è abbastanza utile da poter essere incluso come libreria opzionale incorporata, come $resource.
OverZealous

6
questo è quello che stavo cercando, tuttavia mi aspettavo che qualcosa del genere fosse integrato in angolare!
Blowsie

7

Confronto tra le risposte @OverZealous e @Connor:

Con il tradizionale ngRepeat di angular: 15s per 2000 file e 420mo di RAM ( Plunker )

Con ngRepeat e il modulo di @OverZealous: 7s per 2000 righe e 240mo di RAM ( Plunker )

Con ngRepeat e la direttiva di @Connor: 8s per 2000 righe e 500mo di RAM ( Plunker )

Ho fatto i miei test con Google Chrome 32.


1
Sarebbe bello anche aver angular-onceconfrontato. Grazie.
alecxe

@alecxe: avevo pianificato di fare i test quando sarebbe stata pubblicata una build stabile di AngularJS 1.3.
Gabriel

Grazie, non dimenticare di includere il angular-oncepacchetto (l'ho pubblicato come opzione alternativa qui).
alecxe,

5

In alternativa, c'è il angular-oncepacchetto:

Se usi AngularJS, hai problemi di prestazioni e hai bisogno di visualizzare molti dati di sola lettura, questo progetto è per te!

angular-onceè stato effettivamente ispirato bindoncee fornisce once-*attributi simili :

<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>
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.