Tôi đang cố gắng để hiểu sự khác biệt giữa ng-if
và ng-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?
Tôi đang cố gắng để hiểu sự khác biệt giữa ng-if
và ng-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:
Lệnh ngIf
nà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 ngIf
phạ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 ngIf
kế 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, $parent
biế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>
Các ngShow
chỉ 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 ngShow
thuộc tính. Phần tử được hiển thị hoặc ẩn bằng cách xóa hoặc thêm ng-hide
lớp CSS vào phần tử. Lớp .ng-hide
CSS được xác định trước trong AngularJS và đặt kiểu hiển thị thành không (sử dụng !important
cờ).
<!-- 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 ngShow
biểu thức ước lượng false
thì ng-hide
lớp CSS được thêm vào class
thuộc tính trên phần tử khiến nó bị ẩn đi. Khi true
, ng-hide
lớp CSS bị xóa khỏi phần tử khiến phần tử không xuất hiện ẩn.
data.input
thì nó hoạt động ... nhưng data
một mình trong mô hình không hoạt động. @CodeHater
ngIf
tạo ra một phạm vi mới, vì vậy nhìn vào ví dụ ở trên lồng nhau ngModel
sẽ tạo ra một data
mô 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ờ. :)
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.
Lệnh ng-if
này sẽ xóa nội dung khỏi trang và ng-show/ng-hide
sử 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
và :last-child
bộ chọn giả để tạo kiểu.
:first-child
và :last-child
developer.mozilla.org/en-US/docs/Web/CSS/:first-child developer.mozilla.org/en-US/docs/Web/CSS/:last-child
@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.
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-if
vì 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à required
vì 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!
@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>
<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}}
Thực tế, ng-if
chỉ 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-click
sự kiện, show
biế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-show
chúng ta chỉ có một show
biế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 show
từ phạm vi cha / bên ngoài thông qua $parent.show
.
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.
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.
ng-if tạo phạm vi con trong khi ng-show / ng-hide thì không.
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.
Để 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)
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
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. :)
ng-if
mô hình, được thêm bởing-model
, không còn tồn tại nữa.