Render nilai tanpa pengikatan data

87

Di AngularJS, bagaimana cara membuat nilai tanpa pengikatan data 2 arah? Seseorang mungkin ingin melakukan ini untuk alasan kinerja, atau bahkan memberikan nilai pada titik waktu tertentu.

Contoh berikut menggunakan data binding:

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

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

Bagaimana cara merender value tanpa pengikatan data?

Blowsie
sumber
apa masukan dan keluaran anda. tolong jelaskan
Nitish Kumar
3
Contoh Anda sebenarnya adalah pengikatan data satu arah (perubahan model -> lihat pembaruan). ng-modelmemberi Anda data binding dua arah: perubahan model -> lihat pembaruan, lihat perubahan -> pembaruan model.
Mark Rajcok
1
diperbarui. maaf maksud saya saya tidak ingin ada pengikatan data sama sekali
Blowsie
10
Menurut saya pertanyaan ini tidak buruk atau pantas mendapatkan suara negatif. Sebenarnya sangat umum ingin menonaktifkan pengikatan data untuk mencegah jam tangan yang tidak perlu.
OverZealous
4
PEMBARUAN: siapa pun yang membaca artikel ini mungkin akan menganggap video ini sangat berguna. youtube.com/watch?v=zyYpHIOrk_Y
Blowsie

Jawaban:

141

Angular 1.3+

Di 1.3, Angular telah mendukung ini menggunakan sintaks berikut.

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

Seperti yang disebutkan dalam jawaban ini .


Angular 1.2 ke bawah

Ini sederhana dan tidak membutuhkan plugin. Lihat ini.

Arahan kecil ini akan dengan mudah mencapai apa yang ingin Anda capai

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

Anda bisa mengikat sekali seperti ini

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

Anda bisa mengikat seperti biasa

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

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

Beberapa dari Anda mungkin menggunakan batarang bersudut, dan seperti yang disebutkan di komentar jika Anda menggunakan arahan ini, elemen tersebut masih menunjukkan mengikat padahal tidak, saya cukup yakin ini ada hubungannya dengan kelas yang dilampirkan ke elemen jadi coba ini, itu harus bekerja (tidak diuji) . Beri tahu saya di komentar jika itu berhasil untuk Anda.

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

@ x0b : Jika Anda memiliki OCD dan Anda ingin menghapus classatribut kosong lakukan ini

!$element.attr('class') && $element.removeAttr('class')
iConnor
sumber
saya belum menguji pluginnya, tapi saya akan berasumsi alat chrome AngularJS tidak akan menampilkan elemen bind-once sebagai pengikat, seperti contoh Anda. Pendekatan yang menarik, saya akan menguji kedua pendekatan tersebut segera.
Blowsie
Lihat ini - ini menunjukkan keduanya sebagai binding dl.dropboxusercontent.com/u/14037764/Development/stackoverflow/…
Blowsie
1
Tanpa diragukan lagi itu karena jika kelas ng-binding itu dapat Anda hapus dengan mudah
iConnor
4
Ini bagus dan jauh lebih sederhana daripada plugin bindonce. Saya menambahkan kemampuan untuk menunggu kondisi sebelum menghancurkan scope dan itu sangat membantu. Terima kasih.
Yaron
1
@ Connor Saya tidak setuju. Misalnya, saya menerima objek video ($ scope.video) dari REST API dan saya ingin satu kali pengikatan judul video ($ scope.video.title). Meskipun saya menyelesaikan janji SEBELUM menambahkannya ke cakupan di pengontrol, saya masih harus mendeklarasikan ng-bind = "video.title" bind-once di DOM. Sekarang, sebelum janji diselesaikan, video.title tidak ditentukan, dan cakupan dihancurkan sebelum video.title ditentukan. Solusi yang saya miliki untuk ini adalah membungkus elemen dalam beberapa jenis pemuatan / bendera init, ng-if = "someLoadingFlag", tetapi ini adalah pola yang buruk.
SirTophamHatt
49

Sepertinya Angular 1.3 (dimulai dengan beta 10) memiliki pengikatan satu kali bawaan:

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

Penjilidan satu kali

Ekspresi yang dimulai dengan :: dianggap sebagai ekspresi satu kali. Ekspresi satu kali akan berhenti menghitung ulang setelah stabil, yang terjadi setelah intisari pertama jika hasil ekspresi adalah nilai yang tidak ditentukan (lihat algoritme stabilisasi nilai di bawah).

Karen Zilles
sumber
1
Jawaban ini berulang kali. Saya tidak bisa cukup memuji Anda, Karl! Saya sangat merekomendasikan penggunaan fitur ini secara agresif jika memungkinkan.
XDS
1
Wow, saya sangat senang saya menggulir ke bawah. Saya akan meminta Connor untuk merujuk hal ini dalam jawaban yang diterima.
JSager
Saya memiliki tabel / daftar dengan 2000 baris dan menggunakan operator yang mengikat satu kali aplikasi saya menjadi sangat lambat saat pertama kali menampilkan / merender daftar. Sangat lambat, sehingga browser bertanya kepada saya dua atau tiga kali apakah saya ingin berhenti menjalankan skrip!
Billy G
@ billy-g Dapatkan Anda memposting jsfiddle atau plunker yang menggambarkan masalah ini?
James Daily
@James Daily: Ini adalah kasus "normal" plnkr.co/edit/rCRP0T5fSgNIllx7F27y dan di sini kasus "ekspresi satu kali" plnkr.co/edit/Rd5VBVjkcX3sTJYGypUr tetapi ... Saya tidak dapat mereproduksinya di sana. Bagaimanapun, ini tidak lebih cepat dengan "ekspresi satu kali" dan saya harus melakukan penyelidikan lebih lanjut untuk menemukan mengapa hal itu terjadi di lingkungan saya (saya menggunakan 1,3 beta 18 dari angularjs)
Billy G
20

Gunakan modul bindonce . Anda harus menyertakan file JS dan menambahkannya sebagai dependensi ke modul aplikasi Anda:

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

Pustaka ini memungkinkan Anda untuk merender item yang terikat hanya sekali - saat pertama kali diinisialisasi. Setiap pembaruan lebih lanjut untuk nilai-nilai tersebut akan diabaikan. Ini cara yang bagus untuk mengurangi jumlah jam tangan di halaman untuk hal-hal yang tidak akan berubah setelah dirender.

Contoh penggunaan:

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

Jika digunakan seperti ini, properti di bawah valueakan disetel setelah tersedia, tetapi jam tangan akan dinonaktifkan.

Terlalu bersemangat
sumber
1
Aku baru saja akan menulis jawaban "tulis perintahmu sendiri ...", tapi sepertinya seseorang telah melakukannya untuk kita, bagus.
Mark Rajcok
3
Bindonce cukup berguna sehingga dapat disertakan sebagai pustaka opsional bawaan, seperti $resource.
OverZealous
6
inilah yang saya cari, namun saya mengharapkan sesuatu seperti ini akan dibuat bersudut!
Blowsie
7

Perbandingan antara jawaban @OverZealous dan @Connor:

Dengan ngRepeat tradisional dari sudut: 15 detik untuk 2000 baris dan 420 bulan RAM ( Plunker )

Dengan ngRepeat dan modul @OverZealous: 7s untuk 2000 baris dan 240 bulan RAM ( Plunker )

Dengan ngRepeat dan direktif @Connor: 8s untuk 2000 baris dan 500 bulan RAM ( Plunker )

Saya melakukan pengujian dengan Google Chrome 32.

Gabriel
sumber
1
Alangkah baiknya juga angular-oncemembandingkan. Terima kasih.
alecxe
@alecxe: Saya berencana melakukan pengujian ketika build stabil AngularJS 1.3 dipublikasikan.
Gabriel
Terima kasih, jangan lupa untuk menyertakan angular-oncepaket (saya telah mempostingnya sebagai opsi alternatif di sini).
alecxe
5

Sebagai alternatif, ada angular-oncepaket:

Jika Anda menggunakan AngularJS, memiliki masalah kinerja dan perlu menampilkan banyak data hanya-baca, proyek ini cocok untuk Anda!

angular-oncesebenarnya terinspirasi oleh bindoncedan memberikan once-*atribut serupa :

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