Kết xuất giá trị mà không ràng buộc dữ liệu


87

Trong AngularJS, làm cách nào tôi có thể hiển thị một giá trị mà không có ràng buộc dữ liệu 2 chiều? Người ta có thể muốn làm điều này vì lý do hiệu suất, hoặc thậm chí hiển thị một giá trị tại một thời điểm nhất định.

Cả hai ví dụ sau đều sử dụng liên kết dữ liệu:

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

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

Làm cách nào để kết xuất value mà không có bất kỳ ràng buộc dữ liệu nào?


đầu vào và đầu ra của bạn là gì. làm ơn giải thích
Nitish Kumar,

3
Các ví dụ của bạn thực sự là ràng buộc dữ liệu một chiều (thay đổi mô hình -> xem cập nhật). ng-modelcung cấp cho bạn ràng buộc dữ liệu hai chiều: thay đổi mô hình -> xem cập nhật, xem thay đổi -> cập nhật mô hình.
Mark Rajcok 13/09/13

1
đã cập nhật. xin lỗi tôi có nghĩa là tôi muốn không có dữ liệu ràng buộc ở tất cả
Blowsie

10
Tôi không nghĩ câu hỏi này là khủng khiếp hay đáng được phản đối. Thực sự phổ biến là muốn vô hiệu hóa ràng buộc dữ liệu để ngăn chặn những chiếc đồng hồ không cần thiết.
Quá ghen tị vào

4
CẬP NHẬT: bất cứ ai đọc bài viết này sẽ probaly thấy video này cực kỳ hữu ích. youtube.com/watch?v=zyYpHIOrk_Y
Blowsie

Câu trả lời:


141

Góc 1.3+

Trong 1.3, Angular đã hỗ trợ điều này bằng cú pháp sau.

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

Như đã đề cập trong câu trả lời này .


Angular 1.2 trở xuống

Điều này đơn giản và không cần plugin. Kiểm tra điều này.

Chỉ thị nhỏ này sẽ dễ dàng hoàn thành những gì bạn đang cố gắng đạt được

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

Bạn có thể ràng buộc một lần như thế này

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

Bạn có thể ràng buộc như bình thường

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

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

Một số bạn có thể đang sử dụng batarang góc, và như đã đề cập trong phần nhận xét nếu bạn sử dụng chỉ thị này, phần tử vẫn hiển thị là ràng buộc khi không, tôi khá chắc chắn rằng điều này có liên quan đến các lớp được gắn với phần tử vì vậy hãy thử cái này, nó sẽ hoạt động (không thử nghiệm) . Hãy cho tôi biết trong phần bình luận nếu nó phù hợp với bạn.

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

@ x0b : Nếu bạn có OCD và bạn muốn xóa classthuộc tính trống, hãy làm điều này

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

Tôi vẫn chưa thử nghiệm plugin, nhưng tôi sẽ giả định rằng các công cụ chrome AngularJS sẽ không hiển thị phần tử bind-once dưới dạng liên kết, như ví dụ của bạn. Cách tiếp cận thú vị tho, tôi sẽ sớm thử nghiệm cả hai cách tiếp cận.
Blowsie 13/09/13

Xem điều này - nó hiển thị cả hai dưới dạng ràng buộc dl.dropboxusercontent.com/u/14037764/Development/stackoverflow/…
Blowsie

1
Không nghi ngờ gì đó là bởi vì nếu lớp ng-ràng buộc mà bạn có thể dễ dàng loại bỏ
iConnor

4
Điều này tuyệt vời và đơn giản hơn nhiều so với plugin bindonce. Tôi đã thêm khả năng đợi một điều kiện trước khi phá hủy phạm vi và nó thực sự hữu ích. cảm ơn.
Yaron

1
@Connor Tôi không đồng ý. Ví dụ: tôi đang nhận một đối tượng video ($ scope.video) từ API REST và tôi muốn liên kết một lần tiêu đề video ($ scope.video.title). Ngay cả khi tôi giải quyết lời hứa TRƯỚC KHI thêm nó vào phạm vi trong bộ điều khiển, tôi vẫn phải khai báo ng-bind = "video.title" bind-once trên DOM. Bây giờ, trước khi lời hứa được giải quyết, video.title không được xác định và phạm vi bị phá hủy trước khi video.title được xác định. Một giải pháp mà tôi có cho điều này là bọc các phần tử trong một số loại cờ loading / init, ng-if = "someLoadingFlag", nhưng đó là một mô hình kém.
SirTophamHatt,

49

Có vẻ như Angular 1.3 (bắt đầu từ phiên bản beta 10) được tích hợp sẵn liên kết một lần:

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

Ràng buộc một lần

Biểu thức bắt đầu bằng :: được coi là biểu thức một lần. Các biểu thức một lần sẽ ngừng tính toán lại khi chúng ổn định, điều này xảy ra sau lần thông báo đầu tiên nếu kết quả biểu thức là một giá trị không xác định (xem thuật toán ổn định giá trị bên dưới).


1
Câu trả lời này một lần nữa và một lần nữa. Tôi không thể khen ngợi bạn đủ Karl! Tôi thực sự khuyên bạn nên sử dụng tính năng này một cách mạnh mẽ bất cứ nơi nào nó có ý nghĩa.
XDS

1
Wow, tôi thực sự vui mừng vì tôi đã cuộn xuống. Tôi sẽ yêu cầu Connor tham khảo điều này trong câu trả lời được chấp nhận của anh ấy.
JSager

Tôi có một bảng / danh sách với 2000 dòng và sử dụng toán tử liên kết một lần, ứng dụng của tôi rất chậm khi lần đầu tiên hiển thị / hiển thị danh sách. Quá chậm, trình duyệt hỏi tôi hai hoặc ba lần nếu tôi muốn dừng thực thi tập lệnh!
Billy G

@ billy-g Bạn có thể đăng jsfiddle hoặc plunker minh họa vấn đề này không?
James hàng ngày

@James Daily: Đây là trường hợp "bình thường" plnkr.co/edit/rCRP0T5fSgNIllx7F27y và đây là trường hợp "biểu thức một lần" plnkr.co/edit/Rd5VBVjkcX3sTJYGypUr nhưng ... Tôi không thể tái tạo nó ở đó. Dù sao, nó không nhanh hơn với các "biểu hiện một lần" là gì và tôi phải làm điều tra thêm để tìm lý do tại sao nó xảy ra trong môi trường của tôi (tôi sử dụng 1.3 beta 18 của angularjs)
Billy G

20

Sử dụng mô-đun bindonce . Bạn sẽ cần bao gồm tệp JS và thêm nó làm phụ thuộc vào mô-đun ứng dụng của bạn:

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

Thư viện này cho phép bạn hiển thị các mục chỉ bị ràng buộc một lần - khi chúng được khởi tạo lần đầu tiên. Mọi cập nhật thêm cho các giá trị đó sẽ bị bỏ qua. Đó là một cách tuyệt vời để giảm số lượng đồng hồ trên trang cho những thứ sẽ không thay đổi sau khi chúng được hiển thị.

Ví dụ sử dụng:

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

Khi được sử dụng như vậy, thuộc tính bên dưới valuesẽ được thiết lập khi nó có sẵn, nhưng sau đó đồng hồ sẽ bị vô hiệu hóa.


1
Tôi đã định viết một câu trả lời "viết chỉ thị của riêng bạn ...", nhưng có vẻ như ai đó đã làm điều đó cho chúng tôi, thật tuyệt.
Mark Rajcok 13/09/13

3
Bindonce đủ hữu ích để nó có thể được đưa vào như một thư viện tùy chọn được tích hợp sẵn, chẳng hạn như $resource.
Quá ghen tị.

6
đây là những gì tôi đang tìm kiếm, tuy nhiên tôi đã mong đợi một cái gì đó như thế này được xây dựng thành góc cạnh!
Blowsie 13/09/13

7

So sánh giữa câu trả lời @OverZtyles và @Connor:

Với ngRepeat of angle truyền thống: 15 giây cho 2000 hàng và 420mo RAM ( Plunker )

Với ngRepeat và mô-đun của @OverZionary: 7 giây cho 2000 hàng và 240 triệu RAM ( Plunker )

Với ngRepeat và chỉ thị của @Connor: 8 giây cho 2000 hàng và 500 triệu RAM ( Plunker )

Tôi đã thực hiện các bài kiểm tra của mình với Google Chrome 32.


1
Sẽ rất vui nếu cũng được angular-onceso sánh. Cảm ơn.
alecxe

@alecxe: Tôi đã lên kế hoạch thực hiện các bài kiểm tra khi bản dựng ổn định của AngularJS 1.3 được xuất bản.
Gabriel

Cảm ơn, đừng quên bao gồm angular-oncegói (Tôi đã đăng nó như một tùy chọn thay thế ở đây).
alecxe

5

Để thay thế, có angular-oncegói:

Nếu bạn sử dụng AngularJS, gặp vấn đề về hiệu suất và cần hiển thị nhiều dữ liệu chỉ đọc, thì dự án này là dành cho bạn!

angular-oncethực sự được lấy cảm hứng từ bindoncevà cung cấp các once-*thuộc tính tương tự :

<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>
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.