Veri bağlamadan değer oluşturma


87

AngularJS'de 2 yönlü veri bağlama olmadan bir değeri nasıl işleyebilirim? Bunu performans nedenleriyle yapmak, hatta belirli bir zamanda belirli bir noktada bir değer oluşturmak isteyebilirsiniz.

Aşağıdaki örneklerin her ikisi de veri bağlamayı kullanır:

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

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

value Herhangi bir veri bağlama olmadan nasıl render edebilirim ?


girdiniz ve çıktınız nedir. plz açıkla
Nitish Kumar

3
Örnekleriniz aslında tek yönlü veri bağlamadır (model değişiklikleri -> güncellemeleri görüntüle). ng-modelsize iki yönlü veri bağlamayı sağlar: model değişiklikleri -> güncellemeleri görüntüleyin, değişiklikleri görüntüleyin -> model güncellemeleri.
Mark Rajcok

1
güncellenmiş. üzgünüm ben hiçbir hiç veri bağlama istiyorum demek
Blowsie

10
Bu sorunun korkunç olduğunu veya olumsuz oyu hak ettiğini düşünmüyorum. Gereksiz izlemeleri önlemek için veri bağlamayı devre dışı bırakmak gerçekten çok yaygındır.
OverZealous

4
GÜNCELLEME: Bu makaleyi okuyan herkes muhtemelen bu videoyu son derece yararlı bulacaktır. youtube.com/watch?v=zyYpHIOrk_Y
Blowsie

Yanıtlar:


141

Açısal 1.3+

1.3'te Angular, aşağıdaki sözdizimini kullanarak bunu destekledi.

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

Bu cevapta belirtildiği gibi .


Açısal 1.2 ve altı

Bu basittir ve bir eklentiye ihtiyaç duymaz. Şuna bak.

Bu küçük yönerge, başarmaya çalıştığınız şeyi kolayca gerçekleştirecek

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

Böyle bir kez bağlayabilirsin

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

Normal gibi bağlanabilirsin

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

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

Bazılarınız açısal batarang kullanıyor olabilir ve yorumlarda da belirtildiği gibi, bu yönergeyi kullanırsanız, öğe, olmadığı halde hala bağlayıcı olarak gösterilir, bunun öğeye eklenmiş sınıflarla bir ilgisi olduğundan oldukça eminim. bunu deneyin, çalışmalıdır (test edilmemiştir) . Sizin için işe yarayıp yaramadığını yorumlarda bana bildirin.

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

@ x0b : OKB'niz varsa ve boş classniteliği kaldırmak istiyorsanız bunu yapın

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

Eklentiyi henüz test etmedim, ancak AngularJS krom araçlarının örneğinizde olduğu gibi bir kez bağlama öğesini bir bağlama olarak göstermeyeceğini varsayıyorum. İlginç bir yaklaşım tho, yakında her iki yaklaşımı da test edeceğim.
Blowsie


1
Şüphesiz, çünkü kolayca kaldırabileceğiniz ng bağlayıcı sınıf
iConnor

4
Bu harika ve bindonce eklentisinden çok daha basit. Kapsamı yok etmeden önce bir durumu bekleme yeteneği ekledim ve bu gerçekten yardımcı oldu. Teşekkürler.
Yaron

1
@Connor Katılmıyorum. Örneğin, bir REST API'den bir video nesnesi ($ kapsam.video) alıyorum ve video başlığının ($ kapsam.video.title) bir kerelik bağlanmasını istiyorum. Sözü denetleyicide kapsama eklemeden ÖNCE çözsem bile, DOM üzerinde ng-bind = "video.title" bind-bir kez bildirmek zorundayım. Şimdi, söz çözülmeden önce, video.title tanımsızdır ve video.title tanımlanmadan önce kapsam yok edilir. Bunun için sahip olduğum bir çözüm, öğeleri bir tür yükleme / başlatma bayrağı, ng-if = "someLoadingFlag" ile sarmalamak, ancak bu zayıf bir model.
SirTophamHatt

49

Görünüşe göre Angular 1.3 (beta 10'dan başlayarak) yerleşik tek seferlik bağlama içerir:

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

Tek seferlik ciltleme

:: ile başlayan bir ifade, tek seferlik bir ifade olarak kabul edilir. Tek seferlik ifadeler, kararlı olduklarında yeniden hesaplamayı durdurur; bu, ifade sonucu tanımlanmamış bir değerse ilk özetten sonra gerçekleşir (aşağıdaki değer sabitleme algoritmasına bakın).


1
Bu cevap tekrar tekrar. Seni yeterince övemiyorum Karl! Bu özelliğin mantıklı olduğu her yerde agresif kullanılmasını şiddetle tavsiye ederim.
XDS

1
Vay, aşağı kaydırdığıma gerçekten çok memnunum Connor'dan kabul ettiği cevabında buna referans vermesini isteyeceğim.
JSager

2000 satırlık bir tablom / listem var ve tek seferlik bağlama operatörünü kullanarak listeyi ilk kez gösterirken / oluştururken uygulamam aşırı derecede yavaşlıyor. O kadar yavaş ki, tarayıcı betiği çalıştırmayı durdurmak isteyip istemediğimi iki veya üç kez soruyor!
Billy G

@ billy-g Sorunu açıklayan bir jsfiddle veya plunker gönderebilir misiniz?
James Daily

@James Daily: İşte "normal" durum plnkr.co/edit/rCRP0T5fSgNIllx7F27y ve burada "tek seferlik ifade" durumu plnkr.co/edit/Rd5VBVjkcX3sTJYGypUr ama ... Onu orada yeniden üretemiyorum . Her neyse, "tek seferlik ifade" ile daha hızlı değil ve neden çevremde olduğunu bulmak için daha fazla araştırma yapmam gerekiyor (1.3 beta 18 of angularjs kullanıyorum)
Billy G

20

Bindonce modülünü kullanın . JS dosyasını eklemeniz ve bunu bir bağımlılık olarak uygulama modülünüze eklemeniz gerekir:

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

Bu kitaplık, yalnızca bir kez bağlanan öğeleri - ilk başlatıldıklarında - oluşturmanıza olanak tanır. Bu değerlerde yapılacak diğer güncellemeler dikkate alınmayacaktır. Oluşturulduktan sonra değişmeyecek şeyler için sayfadaki izlenme sayısını azaltmanın harika bir yoludur.

Kullanım örneği:

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

Bu şekilde kullanıldığında, altındaki özellik kullanılabilir valueolduğunda ayarlanacak, ancak saat devre dışı bırakılacaktır.


1
"Kendi direktifini yaz ..." cevabını yazmak üzereydim, ama görünüşe göre birisi bunu bizim için çoktan yapmış, güzel.
Mark Rajcok

3
Bindonce, yerleşik bir isteğe bağlı kitaplık olarak dahil edilebilecek kadar kullanışlıdır $resource.
OverZealous

6
aradığım şey buydu, ancak bunun gibi bir şeyin köşeli hale getirilmesini bekliyordum!
Blowsie

7

@OverZealous ve @Connor cevapları arasındaki karşılaştırma:

Geleneksel ngRepeat of angular ile: 2000 sıra için 15s ve 420mo RAM ( Plunker )

NgRepeat ve @OverZealous modülü ile: 2000 satır için 7s ve 240mo RAM ( Plunker )

NgRepeat ve @Connor yönergesi ile: 2000 satır için 8s ve 500mo RAM ( Plunker )

Testlerimi Google Chrome 32 ile yaptım.


1
Karşılaştırmak da güzel olurdu angular-once. Teşekkürler.
alecxe

@alecxe: Testleri, AngularJS 1.3'ün kararlı bir yapısı yayınlandığında yapmayı planladım.
Gabriel

Teşekkürler, angular-oncepaketi eklemeyi unutmayın (Alternatif bir seçenek olarak burada yayınladım).
alecxe

5

Alternatif olarak angular-oncepaket var:

AngularJS kullanıyorsanız, performans sorunları yaşıyorsanız ve çok sayıda salt okunur veriyi görüntülemeniz gerekiyorsa, bu proje tam size göre!

angular-onceaslında esinlenmiştir bindonceve benzer once-*özellikler sağlar:

<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>
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.