ฉันพยายามเข้าใจความแตกต่างระหว่างng-if
และng-show
/ ng-hide
แต่พวกเขาดูเหมือนฉัน
มีความแตกต่างที่ฉันควรจำไว้ว่าเลือกใช้อย่างใดอย่างหนึ่งหรือไม่
ฉันพยายามเข้าใจความแตกต่างระหว่างng-if
และng-show
/ ng-hide
แต่พวกเขาดูเหมือนฉัน
มีความแตกต่างที่ฉันควรจำไว้ว่าเลือกใช้อย่างใดอย่างหนึ่งหรือไม่
คำตอบ:
ngIf
สั่งลบหรือสร้างส่วนของต้นไม้ DOM อยู่บนพื้นฐานของการแสดงออกอีกด้วย หากการแสดงออกที่กำหนดให้ngIf
ประเมินค่าเท็จแล้วองค์ประกอบจะถูกลบออกจาก DOM มิฉะนั้นโคลนขององค์ประกอบจะถูกแทรกเข้าไปใน 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>
เมื่อองค์ประกอบถูกลบออกโดยใช้ngIf
ขอบเขตของมันจะถูกทำลายและขอบเขตใหม่จะถูกสร้างขึ้นเมื่อองค์ประกอบถูกกู้คืน ขอบเขตที่สร้างขึ้นภายในการngIf
สืบทอดจากขอบเขตพาเรนต์โดยใช้การสืบทอดต้นแบบ
หากngModel
ใช้ภายในngIf
เพื่อเชื่อมโยงกับ JavaScript ดั้งเดิมที่กำหนดในขอบเขตพาเรนต์การแก้ไขใด ๆ ที่ทำกับตัวแปรภายในขอบเขตลูกจะไม่ส่งผลต่อค่าในขอบเขตพาเรนต์เช่น
<input type="text" ng-model="data">
<div ng-if="true">
<input type="text" ng-model="data">
</div>
หากต้องการแก้ไขสถานการณ์นี้และอัพเดตโมเดลในขอบเขตพาเรนต์จากภายในขอบเขตชายด์ให้ใช้อ็อบเจ็กต์:
<input type="text" ng-model="data.input">
<div ng-if="true">
<input type="text" ng-model="data.input">
</div>
หรือ$parent
ตัวแปรเพื่ออ้างอิงวัตถุขอบเขตหลัก:
<input type="text" ng-model="data">
<div ng-if="true">
<input type="text" ng-model="$parent.data">
</div>
ngShow
สั่งแสดงหรือซ่อนองค์ประกอบ HTML ให้อยู่บนพื้นฐานของการแสดงออกให้กับngShow
แอตทริบิวต์ องค์ประกอบนั้นถูกแสดงหรือซ่อนโดยการลบหรือเพิ่มng-hide
คลาส CSS ลงบนองค์ประกอบ .ng-hide
คลาส CSS ถูกกำหนดไว้ล่วงหน้าใน AngularJS และการตั้งค่ารูปแบบการแสดงที่จะไม่มี (ใช้!important
ธง)
<!-- 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>
เมื่อngShow
นิพจน์ประเมินค่าfalse
จากนั้นng-hide
คลาส CSS จะถูกเพิ่มไปยังclass
แอ็ตทริบิวต์บนอิลิเมนต์ที่ทำให้มันซ่อนอยู่ เมื่อtrue
ใดที่ng-hide
คลาส CSS จะถูกลบออกจากองค์ประกอบทำให้องค์ประกอบนั้นไม่ปรากฏขึ้น
data.input
มันทำงานได้ ... แต่data
เพียงอย่างเดียวในแบบจำลองไม่ทำงาน @CodeHater
ngIf
สร้างขอบเขตใหม่ดังนั้นการดูตัวอย่างด้านบนที่ซ้อนกันngModel
จะสร้างdata
โมเดลใหม่แม้ว่าจะมีโมเดลที่มีชื่อเดียวกันอยู่ในขอบเขตพาเรนต์ แต่เมื่อคุณใช้เครื่องหมายจุดคุณจะทำให้ JS ค้นหาห่วงโซ่ต้นแบบของขอบเขต ดังนั้นหากไม่พบค่าในขอบเขตปัจจุบันก็จะพยายามหาค่าในขอบเขตพาเรนต์เป็นต้น สั่งอื่น ๆ บางที่สร้างขอบเขตที่แตกต่างกัน,ngInclude
ngRepeat
หวังว่ามันชัดเจนในขณะนี้ :)
บางทีจุดที่น่าสนใจคือความแตกต่างระหว่างลำดับความสำคัญระหว่างทั้งสอง
เท่าที่ฉันสามารถบอกได้คำสั่ง ng-if มีหนึ่งในลำดับความสำคัญสูงสุด (ถ้าไม่ใช่สูงสุด) ของคำสั่งเชิงมุมทั้งหมด ซึ่งหมายความว่า: มันจะรัน FIRST ก่อนคำสั่งอื่น ๆ ทั้งหมดจัดลำดับความสำคัญต่ำกว่าคำสั่ง ความจริงที่ว่ามันทำงานครั้งแรกหมายความว่ามีประสิทธิภาพองค์ประกอบจะถูกลบออกก่อนที่จะมีการประมวลผลคำสั่งภายใน หรืออย่างน้อย: นั่นคือสิ่งที่ฉันทำมัน
ฉันสังเกตการณ์และใช้สิ่งนี้ใน UI ที่ฉันสร้างให้กับลูกค้าปัจจุบันของฉัน UI ทั้งหมดนั้นค่อนข้างหนาแน่นและมันมี ng-show และ ng-hide อยู่ทั่ว เพื่อไม่ให้ละเอียดมากนัก แต่ฉันสร้างส่วนประกอบทั่วไปขึ้นมาซึ่งสามารถจัดการได้โดยใช้การกำหนดค่า JSON ดังนั้นฉันจึงต้องทำการสลับภายในเทมเพลต มีการนำเสนอ ng-repeat และภายใน ng-repeat ตารางจะแสดงซึ่งมีจำนวนมากของ ng-shows, ng-hides และแม้กระทั่ง ng-switches พวกเขาต้องการแสดงซ้ำอย่างน้อย 50 ครั้งในรายการซึ่งจะส่งผลให้มีการแก้ไขคำสั่งมากกว่า 1,500-2,000 รายการ ฉันตรวจสอบรหัสและ Java แบ็กเอนด์ + JS ที่กำหนดเองที่ด้านหน้าจะใช้เวลาประมาณ 150 มิลลิวินาทีในการประมวลผลข้อมูลแล้วแองกูลาร์จะเคี้ยว 2-3 วินาทีก่อนที่จะแสดง ลูกค้าไม่ได้บ่น แต่ฉันก็ตกใจ :-)
ในการค้นหาของฉันฉันพบคำสั่ง ng-if ตอนนี้อาจจะเป็นการดีที่สุดที่จะชี้ให้เห็นว่าในขณะที่ให้กำเนิด UI นี้จะไม่มี ng-if เนื่องจาก ng-show และ ng-hide มีฟังก์ชั่นในตัวพวกเขาซึ่งคืนบูลีนฉันจึงสามารถแทนที่พวกมันทั้งหมดด้วย ng-if ได้อย่างง่ายดาย โดยการทำเช่นนั้นคำสั่งภายในทั้งหมดดูเหมือนจะไม่ถูกประเมินอีกต่อไป นั่นหมายความว่าฉันย้อนกลับไปประมาณหนึ่งในสามของคำสั่งทั้งหมดที่ถูกประเมินและดังนั้น UI จึงเร่งความเร็วในการโหลดได้สูงถึงประมาณ 500ms - 1 วินาที (ฉันไม่มีวิธีกำหนดวินาทีที่แน่นอน)
หมายเหตุ: ความจริงที่ว่าคำสั่งนั้นไม่ได้รับการประเมินนั้นเป็นการเดาที่มีการศึกษาเกี่ยวกับสิ่งที่เกิดขึ้นภายใต้
ดังนั้นในความคิดของฉัน: หากคุณต้องการองค์ประกอบที่จะปรากฏบนหน้า (เช่น: สำหรับการตรวจสอบองค์ประกอบหรืออะไรก็ตาม) แต่เพียงซ่อนให้ใช้ ng-show / ng-hide ในกรณีอื่น ๆ ให้ใช้ ng-if
ng-if
สั่งเอาเนื้อหาจากหน้าและng-show/ng-hide
ใช้แบบ CSS display
คุณสมบัติการซ่อนเนื้อหา
สิ่งนี้มีประโยชน์ในกรณีที่คุณต้องการใช้:first-child
และ:last-child
ตัวเลือกหลอกแบบ
:first-child
และ:last-child
developer.mozilla.org/en-US/docs/Web/CSS/:first-child developer.mozilla.org/en-US/docs/Web/CSS/:last-child
@EdSpencer ถูกต้อง หากคุณมีองค์ประกอบจำนวนมากและคุณใช้ ng-if เพื่อสร้างอินสแตนซ์ที่เกี่ยวข้องเท่านั้นคุณกำลังประหยัดทรัพยากร @CodeHater ก็ค่อนข้างถูกต้องเช่นกันถ้าคุณจะลบและแสดงองค์ประกอบบ่อยๆการซ่อนมันไว้แทนที่จะลบมันจะช่วยปรับปรุงประสิทธิภาพได้
กรณีการใช้งานหลักที่ฉันค้นหาสำหรับ ng-if คือช่วยให้ฉันสามารถตรวจสอบความถูกต้องและกำจัดองค์ประกอบหากเนื้อหานั้นผิดกฎหมาย เช่นฉันสามารถอ้างอิงตัวแปรชื่อภาพ null และนั่นจะทำให้เกิดข้อผิดพลาด แต่ถ้าฉัน ng-if และตรวจสอบว่ามันว่างเปล่ามันดีทั้งหมด ถ้าฉันทำรายการ -GG ข้อผิดพลาดจะยังคงทำงานอยู่
สิ่งสำคัญสิ่งหนึ่งที่ควรทราบเกี่ยวกับ ng-if และ ng-show คือเมื่อใช้การควบคุมแบบฟอร์มจะเป็นการดีกว่าที่จะใช้ng-if
เพราะจะลบองค์ประกอบออกจาก dom อย่างสมบูรณ์
ความแตกต่างนี้มีความสำคัญเพราะถ้าคุณสร้างช่องป้อนข้อมูลด้วยrequired="true"
แล้วตั้งค่าng-show="false"
ให้ซ่อน Chrome จะโยนข้อผิดพลาดต่อไปนี้เมื่อผู้ใช้พยายามส่งแบบฟอร์ม:
An invalid form control with name='' is not focusable.
เหตุผลที่เป็นช่องป้อนข้อมูลอยู่และเป็นrequired
เพราะมันซ่อนอยู่ Chrome ไม่สามารถมุ่งเน้นไปที่มัน สิ่งนี้สามารถทำลายรหัสของคุณได้อย่างแท้จริงเนื่องจากข้อผิดพลาดนี้หยุดการทำงานของสคริปต์ ดังนั้นระวัง!
@Gajus Kuizinas และ @CodeHater ถูกต้อง ที่นี่ฉันแค่ยกตัวอย่าง ในขณะที่เรากำลังทำงานกับ ng-if หากค่าที่กำหนดเป็นเท็จองค์ประกอบ html ทั้งหมดจะถูกลบออกจาก DOM และหากค่าที่กำหนดเป็นจริงองค์ประกอบ html จะปรากฏบน DOM และขอบเขตจะแตกต่างกันเมื่อเทียบกับขอบเขตหลัก แต่ในกรณีของ ng-show มันจะแสดงและซ่อนองค์ประกอบตามค่าที่กำหนด แต่มันจะอยู่ใน DOM เสมอ เฉพาะทัศนวิสัยที่เปลี่ยนแปลงตามค่าที่กำหนด
http://plnkr.co/edit/3G0V9ivUzzc8kpLb1OQn?p=preview
หวังว่าตัวอย่างนี้จะช่วยคุณในการทำความเข้าใจขอบเขต ลองให้ค่าเท็จกับ ng-show และ ng-if และตรวจสอบ DOM ในคอนโซล ลองป้อนค่าในกล่องอินพุตและสังเกตความแตกต่าง
<!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}}
ความจริงng-if
คำสั่งนั้นไม่เหมือนng-show
สร้างขอบเขตของตัวเองนำไปสู่ความแตกต่างที่น่าสนใจ:
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>
ที่รายการแรก, on-click
กิจกรรม, show
ตัวแปร, จากขอบเขตภายใน / ของตัวเองมีการเปลี่ยนแปลง แต่ng-if
กำลังดูตัวแปรอื่นจากขอบเขตด้านนอกที่มีชื่อเดียวกันดังนั้นโซลูชันไม่ทำงาน ในกรณีที่ng-show
เรามีshow
ตัวแปรเพียงตัวเดียวนั่นคือสาเหตุที่ใช้งานได้ ในการแก้ไขปัญหาความพยายามครั้งแรกที่เราควรจะอ้างอิงถึงshow
จากผู้ปกครอง / $parent.show
ขอบเขตด้านนอกผ่านทาง
ng-if ถ้า false จะลบองค์ประกอบออกจาก DOM ซึ่งหมายความว่ากิจกรรมทั้งหมดคำสั่งที่แนบกับองค์ประกอบเหล่านั้นจะหายไป ตัวอย่างเช่น ng-click เป็นหนึ่งในองค์ประกอบย่อยเมื่อ ng-if ประเมินว่าเป็นเท็จองค์ประกอบนั้นจะถูกลบออกจาก DOM และอีกครั้งเมื่อเป็นจริงจะถูกสร้างขึ้นใหม่
ng-show / ng-hide ไม่ได้ลบองค์ประกอบออกจาก DOM มันใช้สไตล์ CSS (.ng-hide) เพื่อซ่อน / แสดงองค์ประกอบวิธีนี้เหตุการณ์คำสั่งที่แนบกับเด็ก ๆ ของคุณจะไม่สูญหาย
ng-if สร้างขอบเขตลูกในขณะที่ ng-show / ng-hide ไม่ได้
ng-show และ ng-hide ทำงานในทางตรงข้าม แต่ความแตกต่างระหว่าง ng-hide หรือ ng-show กับ ng-if คือถ้าเราใช้ ng-if ก็จะสร้างองค์ประกอบใน dom แต่ด้วยองค์ประกอบ ng-hide / ng-show จะถูกซ่อนอย่างสมบูรณ์
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.
สิ่งที่เกิดขึ้นกับฉันตอนนี้: ng-show ซ่อนเนื้อหาผ่าน css ใช่ แต่มันทำให้เกิดข้อผิดพลาดแปลก ๆ ใน div ที่ควรจะเป็นปุ่ม
ฉันมีการ์ดที่มีสองปุ่มที่ด้านล่างและขึ้นอยู่กับสถานะที่แท้จริงหนึ่งแลกเปลี่ยนกับที่สามตัวอย่างปุ่มแก้ไขกับรายการใหม่ การใช้ ng-show = false เพื่อซ่อนสิ่งที่เหลือไว้ (ปรากฏก่อนในไฟล์) มันเกิดขึ้นว่าปุ่มต่อไปนี้จบลงด้วยขอบด้านขวาด้านนอกของการ์ด ng-if แก้ไขโดยไม่ใส่รหัสเลย (เพียงตรวจสอบที่นี่หากมีความประหลาดใจที่ซ่อนอยู่โดยใช้ ng-if แทน ng-show)
ngIfทำการจัดการกับ DOM โดยการลบหรือสร้างองค์ประกอบใหม่
โดยที่ngShowใช้กฎ css เพื่อซ่อน / แสดงสิ่งต่าง ๆ
สำหรับกรณีส่วนใหญ่ (ไม่เสมอไป)ฉันจะสรุปสิ่งนี้หากคุณต้องการตรวจสอบหนึ่งครั้งเพื่อแสดง / ซ่อนสิ่งใช้ng-if
หากคุณต้องการแสดง / ซ่อนสิ่งต่าง ๆ ตามการกระทำของผู้ใช้บนหน้าจอ (เช่นตรวจสอบแล้ว ช่องทำเครื่องหมายนั้นแสดงกล่องข้อความไม่ถูกตรวจสอบแล้วซ่อนกล่องข้อความ ฯลฯ .. ) จากนั้นใช้ng-show
ข้อแตกต่างที่น่าสนใจอย่างหนึ่งของ ng-if และ ng-show คือ:
การรักษาความปลอดภัย
องค์ประกอบ DOM มีอยู่ในบล็อก ng-if จะไม่ถูกแสดงผลในกรณีที่ค่าเป็นเท็จ
โดยที่ในกรณีของ ng-show ผู้ใช้สามารถเปิดหน้าต่างองค์ประกอบการตรวจสอบและตั้งค่าเป็น TRUE
และด้วยเสียงโห่ร้องเนื้อหาทั้งหมดที่ตั้งใจจะซ่อนจะถูกแสดงซึ่งเป็นการละเมิดความปลอดภัย :)
ng-if
โมเดลที่เพิ่มโดยng-model
จะไม่มีอยู่อีกต่อไป