Sự khác biệt giữa ng-if và ng-show / ng-hide


427

Tôi đang cố gắng để hiểu sự khác biệt giữa ng-ifng-show/ ng-hide, nhưng chúng trông giống nhau đối với tôi.

Có một sự khác biệt mà tôi nên ghi nhớ khi chọn sử dụng cái này hay cái kia không?

Câu trả lời:


521

ngNếu

Lệnh ngIfnày sẽ xóa hoặc tạo lại một phần của cây DOM dựa trên biểu thức. Nếu biểu thức được gán để ngIfđánh giá một giá trị sai thì phần tử sẽ bị xóa khỏi DOM, nếu không thì một bản sao của phần tử được gắn lại vào DOM.

<!-- when $scope.myValue is truthy (element is restored) -->
<div ng-if="1"></div>

<!-- when $scope.myValue is falsy (element is removed) -->
<div ng-if="0"></div>

Khi một phần tử được loại bỏ bằng cách sử dụng ngIfphạm vi của nó bị phá hủy và một phạm vi mới được tạo khi phần tử được khôi phục. Phạm vi được tạo trong các ngIfkế thừa từ phạm vi cha của nó bằng cách sử dụng kế thừa nguyên mẫu.

Nếu ngModelđược sử dụng bên trong ngIfđể liên kết với một nguyên hàm JavaScript được xác định trong phạm vi cha, mọi sửa đổi được thực hiện cho biến trong phạm vi con sẽ không ảnh hưởng đến giá trị trong phạm vi cha, ví dụ:

<input type="text" ng-model="data">
<div ng-if="true">
    <input type="text" ng-model="data">
</div>        

Để khắc phục tình trạng này và cập nhật mô hình trong phạm vi cha từ bên trong phạm vi con, sử dụng một đối tượng:

<input type="text" ng-model="data.input">
<div ng-if="true">
    <input type="text" ng-model="data.input">
</div>

Hoặc, $parentbiến để tham chiếu đối tượng phạm vi cha:

<input type="text" ng-model="data">
<div ng-if="true">
    <input type="text" ng-model="$parent.data">
</div>

ngow

Các ngShowchỉ thị chương trình hoặc da các phần tử HTML được dựa trên biểu thức cung cấp cho các ngShowthuộc tính. Phần tử được hiển thị hoặc ẩn bằng cách xóa hoặc thêm ng-hidelớp CSS vào phần tử. Lớp .ng-hideCSS được xác định trước trong AngularJS và đặt kiểu hiển thị thành không (sử dụng !importantcờ).

<!-- when $scope.myValue is truthy (element is visible) -->
<div ng-show="1"></div>

<!-- when $scope.myValue is falsy (element is hidden) -->
<div ng-show="0" class="ng-hide"></div>

Khi ngShowbiểu thức ước lượng falsethì ng-hidelớp CSS được thêm vào classthuộc tính trên phần tử khiến nó bị ẩn đi. Khi true, ng-hidelớp CSS bị xóa khỏi phần tử khiến phần tử không xuất hiện ẩn.


31
Gợi ý: Bằng cách loại bỏ phần tử HTML bằng ng-ifmô hình, được thêm bởi ng-model, không còn tồn tại nữa.
mrzmyr

3
@CodeHater Tôi đã tận dụng thành công ng-if over ng-show / ng-hide trên một trang có thể có một dom lớn. Nó dường như làm cho trang cảm thấy nhanh hơn, nhưng không có nghĩa là phân tích khoa học.
Ed Spencer

Phần tôi gặp khó khăn với sự hiểu biết đầy đủ là làm thế nào / tại sao khi bạn có một đối tượng trong mô hình data.inputthì nó hoạt động ... nhưng datamột mình trong mô hình không hoạt động. @CodeHater
Mark Pieszak - Trilon.io

7
@mcpDESIGNS ngIftạo ra một phạm vi mới, vì vậy nhìn vào ví dụ ở trên lồng nhau ngModelsẽ tạo ra một datamô hình mới mặc dù một mô hình có cùng tên tồn tại trong phạm vi cha. Nhưng khi bạn sử dụng ký hiệu dấu chấm, bạn làm cho JS tra cứu chuỗi nguyên mẫu của phạm vi. Vì vậy, nếu nó không tìm thấy giá trị trong phạm vi hiện tại, nó sẽ cố gắng tìm kiếm nó trong phạm vi cha mẹ, v.v. Vài chỉ thị khác tạo ra một phạm vi khác nhau ngInclude, ngRepeat. Hy vọng nó rõ ràng bây giờ. :)
Luôn luôn học hỏi

3
Cái nào tốt hơn cho hiệu suất? Tôi nghĩ ng-show và ng-hide phải không?
tom10271

97

Có lẽ một điểm thú vị để thực hiện, là sự khác biệt giữa các ưu tiên giữa cả hai.

Theo như tôi có thể nói, chỉ thị ng-if có một trong những ưu tiên cao nhất (nếu không phải là cao nhất) trong tất cả các chỉ thị Angular. Điều đó có nghĩa là: nó sẽ chạy FIRST trước tất cả các chỉ thị khác, ưu tiên thấp hơn. Thực tế là nó chạy FIRST, có nghĩa là một cách hiệu quả, phần tử được loại bỏ trước khi bất kỳ chỉ thị bên trong nào được xử lý. Hoặc ít nhất: đó là những gì tôi làm cho nó.

Tôi quan sát và sử dụng nó trong UI tôi đang xây dựng cho khách hàng hiện tại của mình. Toàn bộ giao diện người dùng được đóng gói khá nhiều, và nó có ng-show và ng-ẩn trên tất cả. Không đi sâu vào chi tiết, nhưng tôi đã xây dựng một thành phần chung, có thể được quản lý bằng cấu hình JSON, vì vậy tôi phải thực hiện một số chuyển đổi bên trong khuôn mẫu. Có một hiện tại ng-repeat và bên trong ng-repeat, một bảng được hiển thị, trong đó có rất nhiều ng-shows, ng-ẩn và thậm chí ng-switch hiện diện. Họ muốn hiển thị ít nhất 50 lần lặp lại trong danh sách, điều này sẽ dẫn đến ít nhất 1500-2000 chỉ thị được giải quyết. Tôi đã kiểm tra mã và phần phụ trợ Java + JS tùy chỉnh ở phía trước sẽ mất khoảng 150ms để xử lý dữ liệu và sau đó Angular sẽ nhai khoảng 2-3 giây trước khi hiển thị. Khách hàng không phàn nàn, nhưng tôi đã kinh hoàng :-)

Trong quá trình tìm kiếm, tôi tình cờ thấy chỉ thị ng-if. Bây giờ, có lẽ tốt nhất là chỉ ra rằng tại thời điểm hình thành giao diện người dùng này, không có ng-nếu có. Bởi vì ng-show và ng-hide có chức năng trong đó, trả về booleans, tôi có thể dễ dàng thay thế tất cả bằng ng-if. Bằng cách làm như vậy, tất cả các chỉ thị nội bộ dường như không còn được đánh giá. Điều đó có nghĩa là tôi đã giảm xuống còn khoảng một phần ba tất cả các chỉ thị được đánh giá, và do đó, UI đã tăng tốc lên đến khoảng 500ms - 1 giây thời gian tải. (Tôi không có cách nào để xác định giây chính xác)

Xin lưu ý: thực tế là các chỉ thị không được đánh giá, là một phỏng đoán có giáo dục về những gì đang xảy ra bên dưới.

Vì vậy, theo tôi: nếu bạn cần phần tử hiện diện trên trang (nghĩa là: để kiểm tra phần tử, hoặc bất cứ điều gì), nhưng chỉ cần ẩn đi, hãy sử dụng ng-show / ng-hide. Trong tất cả các trường hợp khác, sử dụng ng-if.


1
Vâng, tôi đoán đây là mục tiêu của ng-if: để giảm thời gian xử lý. Lệnh này tồn tại chắc chắn không chỉ do một số giả giả CSS. Bài đăng tốt +1
Bartłomiej Zalewski

36

Lệnh ng-ifnày sẽ xóa nội dung khỏi trang và ng-show/ng-hidesử dụng thuộc tính CSS displayđể ẩn nội dung.

Điều này rất hữu ích trong trường hợp bạn muốn sử dụng :first-child:last-childbộ chọn giả để tạo kiểu.


bạn có ý nghĩa gì khi sử dụng bộ chọn: đầu tiên và: cuối cùng?
Stephane Rolland


16

@EdSpencer là chính xác. Nếu bạn có nhiều yếu tố và bạn sử dụng ng-if để chỉ khởi tạo những yếu tố có liên quan, bạn đang tiết kiệm tài nguyên. @CodeHater cũng có phần đúng, nếu bạn định loại bỏ và hiển thị một phần tử rất thường xuyên, việc ẩn nó thay vì xóa nó có thể cải thiện hiệu suất.

Trường hợp sử dụng chính mà tôi tìm thấy cho ng-if là nó cho phép tôi xác nhận rõ ràng và loại bỏ một yếu tố nếu nội dung là bất hợp pháp. Chẳng hạn, tôi có thể tham chiếu đến một biến tên hình ảnh null và điều đó sẽ gây ra lỗi nhưng nếu tôi ng-if và kiểm tra xem nó có null không, tất cả đều tốt. Nếu tôi thực hiện một chương trình ng, lỗi vẫn sẽ cháy.


7

Một điều quan trọng cần lưu ý về ng-if và ng-show là khi sử dụng điều khiển biểu mẫu sẽ tốt hơn khi sử dụng ng-ifvì nó loại bỏ hoàn toàn phần tử khỏi dom.

Sự khác biệt này rất quan trọng vì nếu bạn tạo trường nhập liệu required="true"và sau đó được đặt ng-show="false"để ẩn nó, Chrome sẽ đưa ra lỗi sau khi người dùng cố gắng gửi biểu mẫu:

An invalid form control with name='' is not focusable.

Lý do là trường đầu vào có mặt và đó là requiredvì nó bị ẩn nên Chrome không thể tập trung vào nó. Điều này có thể phá vỡ mã của bạn theo nghĩa đen vì lỗi này tạm dừng thực thi tập lệnh. Vì vậy, hãy cẩn thận!


Đây là thực tế, nếu bạn đang sử dụng điều khiển biểu mẫu để xác thực thì bạn sẽ phải chịu đựng rất nhiều nếu bạn sử dụng ng-show / ng-hide. Và nếu bạn có nhiều phần bị ẩn / hiển thị dựa trên biểu thức. Vì vậy, nếu bạn sử dụng ng-show / ẩn, các yếu tố sẽ vẫn ở đó và xác thực sẽ thất bại, mặc dù chúng không xuất hiện trên màn hình. vì vậy hãy giải cứu bạn :)
NeverGiveUp161

5

@Gajus Kuizinas và @CodeHater là chính xác. Ở đây tôi chỉ đưa ra một ví dụ. Trong khi chúng tôi đang làm việc với ng-if, nếu giá trị được gán là sai thì toàn bộ phần tử html sẽ bị xóa khỏi DOM. và nếu giá trị được gán là đúng, thì các phần tử html sẽ hiển thị trên DOM. Và phạm vi sẽ khác so với phạm vi cha. Nhưng trong trường hợp ng-show, nó sẽ chỉ hiển thị và ẩn các phần tử dựa trên giá trị được gán. Nhưng nó luôn ở trong DOM. Chỉ có tầm nhìn thay đổi theo giá trị được chỉ định.

http://plnkr.co/edit/3G0V9ivUzzc8kpLb1OQn?p=preview

Hy vọng ví dụ này sẽ giúp bạn trong việc hiểu phạm vi. Hãy thử đưa ra các giá trị sai cho ng-show và ng-if và kiểm tra DOM trong bảng điều khiển. Hãy thử nhập các giá trị trong các hộp đầu vào và quan sát sự khác biệt.

<!DOCTYPE html>

Xin chào Plunker!

<input type="text" ng-model="data">
<div ng-show="true">
    <br/>ng-show=true :: <br/><input type="text" ng-model="data">
</div>
<div ng-if="true">
    <br/>ng-if=true :: <br/><input type="text" ng-model="data">
</div> 
{{data}}


2

Thực tế, ng-ifchỉ thị đó , không giống như ng-show, tạo ra phạm vi riêng của nó, dẫn đến sự khác biệt thực tế thú vị:

angular.module('app', []).controller('ctrl', function($scope){
  $scope.delete = function(array, item){
    array.splice(array.indexOf(item), 1);
  }
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<div ng-app='app' ng-controller='ctrl'>
   <h4>ng-if:</h4>
   <ul ng-init='arr1 = [1,2,3]'>
      <li ng-repeat='x in arr1'>
        {{show}}
        <button ng-if='!show' ng-click='show=!show'>Delete {{show}}</button>
        <button ng-if='show' ng-click='delete(arr1, x)'>Yes {{show}}</button>
        <button ng-if='show' ng-click='show=!show'>No</button>
      </li>
   </ul>
   
   <h4>ng-show:</h4>
   <ul ng-init='arr2 = [1,2,3]'>
      <li ng-repeat='x in arr2'>
        {{show}}
        <button ng-show='!show' ng-click='show=!show'>Delete {{show}}</button>
        <button ng-show='show' ng-click='delete(arr2, x)'>Yes {{show}}</button>
        <button ng-show='show' ng-click='show=!show'>No</button>
      </li>
   </ul>
   
   <h4>ng-if with $parent:</h4>
    <ul ng-init='arr3 = [1,2,3]'>
      <li ng-repeat='item in arr3'>
        {{show}}
        <button ng-if='!show' ng-click='$parent.show=!$parent.show'>Delete {{$parent.show}}</button>
        <button ng-if='show' ng-click='delete(arr3, x)'>Yes {{$parent.show}}</button>
        <button ng-if='show' ng-click='$parent.show=!$parent.show'>No</button>
      </li>
   </ul>
</div>

Ở danh sách đầu tiên, on-clicksự kiện, showbiến, từ phạm vi innner / own , được thay đổi, nhưng ng-ifđang xem trên một biến khác từ phạm vi bên ngoài có cùng tên, vì vậy giải pháp không hoạt động. Trong trường hợp ng-showchúng ta chỉ có một showbiến duy nhất , đó là lý do tại sao nó hoạt động. Để khắc phục lần thử đầu tiên, chúng ta nên tham chiếu showtừ phạm vi cha / bên ngoài thông qua $parent.show.


1
  1. ng-if if false sẽ xóa các phần tử khỏi DOM. Điều này có nghĩa là tất cả các sự kiện, chỉ thị của bạn gắn liền với các yếu tố đó sẽ bị mất. Ví dụ: ng-click vào một trong các phần tử con, khi ng-if ước lượng thành false, phần tử đó sẽ bị xóa khỏi DOM và một lần nữa khi nó đúng, nó được tạo lại.

  2. ng-show / ng-hide không xóa các thành phần khỏi DOM. Nó sử dụng các kiểu CSS (.ng-hide) để ẩn / hiển thị các thành phần. Bằng cách này, các sự kiện, chỉ thị của bạn được đính kèm với trẻ em sẽ không bị mất.

  3. ng-if tạo phạm vi con trong khi ng-show / ng-hide thì không.


1

ng-show và ng-giấu công việc theo cách ngược lại. Nhưng sự khác biệt giữa ng-hide hoặc ng-show với ng-if là, nếu chúng ta sử dụng ng-if thì phần tử sẽ được tạo trong dom nhưng với phần tử ng-hide / ng-show sẽ bị ẩn hoàn toàn.

ng-show=true/ng-hide=false:
Element will be displayed

ng-show=false/ng-hide=true:
element will be hidden

ng-if =true
element will be created

ng-if= false
element will be created in the dom. 

0

Để lưu ý, một điều đã xảy ra với tôi bây giờ: ng-show không ẩn nội dung thông qua css, vâng, nhưng nó đã dẫn đến những trục trặc kỳ lạ trong div được cho là các nút.

Tôi đã có một thẻ với hai nút ở phía dưới và tùy thuộc vào trạng thái thực tế, một nút được trao đổi với nút thứ ba, ví dụ nút chỉnh sửa với mục nhập mới. Sử dụng ng-show = false để ẩn cái bên trái (xuất hiện đầu tiên trong tệp), điều xảy ra là nút sau kết thúc với đường viền bên phải bên ngoài thẻ. ng-if sửa lỗi đó bằng cách không bao gồm mã. (Chỉ cần kiểm tra ở đây nếu có một số bất ngờ ẩn bằng cách sử dụng ng-if thay vì ng-show)


0

ngNếu thực hiện thao tác trên DOM bằng cách xóa hoặc tạo lại phần tử.

Trong khi đó ngShow áp dụng quy tắc css để ẩn / hiển thị mọi thứ.

Trong hầu hết các trường hợp (không phải luôn luôn) , tôi sẽ tóm tắt điều này như, nếu bạn cần kiểm tra một lần để hiển thị / ẩn mọi thứ, hãy sử dụng ng-if, nếu bạn cần hiển thị / ẩn mọi thứ dựa trên hành động của người dùng trên màn hình (như đã chọn một hộp kiểm sau đó hiển thị hộp văn bản, bỏ chọn rồi ẩn hộp văn bản, v.v.), sau đó sử dụngng-show


-17

Một sự khác biệt thú vị trong ng-if và ng-show là:

BẢO VỆ

Các phần tử DOM có trong khối ng-if sẽ không được hiển thị trong trường hợp giá trị của nó là false

trong trường hợp ng-show, người dùng có thể mở Cửa sổ phần tử kiểm tra của bạn và đặt giá trị của nó thành TRUE.

Và với một cú hích, toàn bộ nội dung có nghĩa là bị ẩn sẽ được hiển thị, đó là một vi phạm an ninh. :)


27
Đây là một hình thức bảo mật cực kỳ yếu. Nếu máy chủ được cung cấp cho máy khách, thì bạn phải cho rằng người dùng / kẻ tấn công có thể truy cập nội dung đó, bất kể nó có trong DOM hay không. Tất cả logic ủy quyền phải được thực thi bởi máy chủ.
tlrobinson

hãy nghĩ về html chứ không phải jsp ... bây giờ nếu bạn muốn thực thi bảo mật trên các thành phần html .. nếu bạn muốn ẩn một số thành phần khỏi người dùng ... bạn sẽ đạt được điều đó như thế nào. Và trong trường hợp cấu hình của bạn được chia thành phía máy chủ cho phụ trợ và phía máy khách cho giao diện người dùng ..
Ashish_B
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.