ความแตกต่างระหว่าง ng-if และ ng-show / ng-hide คืออะไร


427

ฉันพยายามเข้าใจความแตกต่างระหว่างng-ifและng-show/ ng-hideแต่พวกเขาดูเหมือนฉัน

มีความแตกต่างที่ฉันควรจำไว้ว่าเลือกใช้อย่างใดอย่างหนึ่งหรือไม่

คำตอบ:


521

ngIf

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

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 จะถูกลบออกจากองค์ประกอบทำให้องค์ประกอบนั้นไม่ปรากฏขึ้น


31
คำแนะนำ: ด้วยการลบองค์ประกอบ HTML ของตัวเองด้วยng-ifโมเดลที่เพิ่มโดยng-modelจะไม่มีอยู่อีกต่อไป
mrzmyr

3
@CodeHater ฉันได้ใช้ประโยชน์จาก ng-if สำเร็จมากกว่า ng-show / ng-hide บนหน้าเว็บที่อาจมีขนาดใหญ่ ดูเหมือนว่าจะทำให้หน้าเว็บรู้สึกเร็วขึ้น แต่ก็ไม่ใช่การวิเคราะห์ทางวิทยาศาสตร์
Ed Spencer

ส่วนที่ฉันมีปัญหากับการทำความเข้าใจอย่างสมบูรณ์คือวิธี / ทำไมเมื่อคุณมีวัตถุในแบบจำลองdata.inputมันทำงานได้ ... แต่dataเพียงอย่างเดียวในแบบจำลองไม่ทำงาน @CodeHater
Mark Pieszak - Trilon.io

7
@mcpDESIGNS ngIfสร้างขอบเขตใหม่ดังนั้นการดูตัวอย่างด้านบนที่ซ้อนกันngModelจะสร้างdataโมเดลใหม่แม้ว่าจะมีโมเดลที่มีชื่อเดียวกันอยู่ในขอบเขตพาเรนต์ แต่เมื่อคุณใช้เครื่องหมายจุดคุณจะทำให้ JS ค้นหาห่วงโซ่ต้นแบบของขอบเขต ดังนั้นหากไม่พบค่าในขอบเขตปัจจุบันก็จะพยายามหาค่าในขอบเขตพาเรนต์เป็นต้น สั่งอื่น ๆ บางที่สร้างขอบเขตที่แตกต่างกัน,ngInclude ngRepeatหวังว่ามันชัดเจนในขณะนี้ :)
AlwaysALearner

3
อันไหนดีกว่าสำหรับประสิทธิภาพ? ฉันคิดว่า ng-show และ ng-hide ใช่ไหม
tom10271

97

บางทีจุดที่น่าสนใจคือความแตกต่างระหว่างลำดับความสำคัญระหว่างทั้งสอง

เท่าที่ฉันสามารถบอกได้คำสั่ง 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


1
ใช่ฉันคิดว่านี่เป็นเป้าหมายของ ng-if: เพื่อลดเวลาในการประมวลผล คำสั่งนี้มีอยู่แน่นอนไม่เพียง แต่เนื่องจากบาง pseudoselectors CSS โพสต์ที่ดี! +1
Bartłomiej Zalewski

36

ng-ifสั่งเอาเนื้อหาจากหน้าและng-show/ng-hideใช้แบบ CSS displayคุณสมบัติการซ่อนเนื้อหา

สิ่งนี้มีประโยชน์ในกรณีที่คุณต้องการใช้:first-childและ:last-childตัวเลือกหลอกแบบ


คุณหมายถึงอะไรโดยใช้: ตัวเลือกแรกและตัวเลือกสุดท้าย
Stephane Rolland

โอ๊ะโอฉันหมายถึง:first-childและ:last-child developer.mozilla.org/en-US/docs/Web/CSS/:first-child developer.mozilla.org/en-US/docs/Web/CSS/:last-child
Andrei

16

@EdSpencer ถูกต้อง หากคุณมีองค์ประกอบจำนวนมากและคุณใช้ ng-if เพื่อสร้างอินสแตนซ์ที่เกี่ยวข้องเท่านั้นคุณกำลังประหยัดทรัพยากร @CodeHater ก็ค่อนข้างถูกต้องเช่นกันถ้าคุณจะลบและแสดงองค์ประกอบบ่อยๆการซ่อนมันไว้แทนที่จะลบมันจะช่วยปรับปรุงประสิทธิภาพได้

กรณีการใช้งานหลักที่ฉันค้นหาสำหรับ ng-if คือช่วยให้ฉันสามารถตรวจสอบความถูกต้องและกำจัดองค์ประกอบหากเนื้อหานั้นผิดกฎหมาย เช่นฉันสามารถอ้างอิงตัวแปรชื่อภาพ null และนั่นจะทำให้เกิดข้อผิดพลาด แต่ถ้าฉัน ng-if และตรวจสอบว่ามันว่างเปล่ามันดีทั้งหมด ถ้าฉันทำรายการ -GG ข้อผิดพลาดจะยังคงทำงานอยู่


7

สิ่งสำคัญสิ่งหนึ่งที่ควรทราบเกี่ยวกับ ng-if และ ng-show คือเมื่อใช้การควบคุมแบบฟอร์มจะเป็นการดีกว่าที่จะใช้ng-ifเพราะจะลบองค์ประกอบออกจาก dom อย่างสมบูรณ์

ความแตกต่างนี้มีความสำคัญเพราะถ้าคุณสร้างช่องป้อนข้อมูลด้วยrequired="true"แล้วตั้งค่าng-show="false"ให้ซ่อน Chrome จะโยนข้อผิดพลาดต่อไปนี้เมื่อผู้ใช้พยายามส่งแบบฟอร์ม:

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

เหตุผลที่เป็นช่องป้อนข้อมูลอยู่และเป็นrequiredเพราะมันซ่อนอยู่ Chrome ไม่สามารถมุ่งเน้นไปที่มัน สิ่งนี้สามารถทำลายรหัสของคุณได้อย่างแท้จริงเนื่องจากข้อผิดพลาดนี้หยุดการทำงานของสคริปต์ ดังนั้นระวัง!


นี่คือความจริงที่แท้จริงถ้าคุณใช้การควบคุมแบบฟอร์มสำหรับการตรวจสอบแล้วคุณจะประสบมากถ้าคุณใช้ ng-show / ng-hide และถ้าคุณมีหลายส่วนที่ซ่อนอยู่ / แสดงขึ้นอยู่กับการแสดงออก ดังนั้นหากคุณใช้ ng-show / hide องค์ประกอบจะยังคงอยู่ที่นั่นและการตรวจสอบจะล้มเหลวแม้ว่าพวกเขาจะไม่ได้อยู่บนหน้าจอ งั้นถ้าคุณช่วยชีวิตคุณ :)
NeverGiveUp161

5

@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>

สวัสดีครับ 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

ความจริง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ขอบเขตด้านนอกผ่านทาง


1
  1. ng-if ถ้า false จะลบองค์ประกอบออกจาก DOM ซึ่งหมายความว่ากิจกรรมทั้งหมดคำสั่งที่แนบกับองค์ประกอบเหล่านั้นจะหายไป ตัวอย่างเช่น ng-click เป็นหนึ่งในองค์ประกอบย่อยเมื่อ ng-if ประเมินว่าเป็นเท็จองค์ประกอบนั้นจะถูกลบออกจาก DOM และอีกครั้งเมื่อเป็นจริงจะถูกสร้างขึ้นใหม่

  2. ng-show / ng-hide ไม่ได้ลบองค์ประกอบออกจาก DOM มันใช้สไตล์ CSS (.ng-hide) เพื่อซ่อน / แสดงองค์ประกอบวิธีนี้เหตุการณ์คำสั่งที่แนบกับเด็ก ๆ ของคุณจะไม่สูญหาย

  3. ng-if สร้างขอบเขตลูกในขณะที่ ng-show / ng-hide ไม่ได้


1

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. 

0

สิ่งที่เกิดขึ้นกับฉันตอนนี้: ng-show ซ่อนเนื้อหาผ่าน css ใช่ แต่มันทำให้เกิดข้อผิดพลาดแปลก ๆ ใน div ที่ควรจะเป็นปุ่ม

ฉันมีการ์ดที่มีสองปุ่มที่ด้านล่างและขึ้นอยู่กับสถานะที่แท้จริงหนึ่งแลกเปลี่ยนกับที่สามตัวอย่างปุ่มแก้ไขกับรายการใหม่ การใช้ ng-show = false เพื่อซ่อนสิ่งที่เหลือไว้ (ปรากฏก่อนในไฟล์) มันเกิดขึ้นว่าปุ่มต่อไปนี้จบลงด้วยขอบด้านขวาด้านนอกของการ์ด ng-if แก้ไขโดยไม่ใส่รหัสเลย (เพียงตรวจสอบที่นี่หากมีความประหลาดใจที่ซ่อนอยู่โดยใช้ ng-if แทน ng-show)


0

ngIfทำการจัดการกับ DOM โดยการลบหรือสร้างองค์ประกอบใหม่

โดยที่ngShowใช้กฎ css เพื่อซ่อน / แสดงสิ่งต่าง ๆ

สำหรับกรณีส่วนใหญ่ (ไม่เสมอไป)ฉันจะสรุปสิ่งนี้หากคุณต้องการตรวจสอบหนึ่งครั้งเพื่อแสดง / ซ่อนสิ่งใช้ng-ifหากคุณต้องการแสดง / ซ่อนสิ่งต่าง ๆ ตามการกระทำของผู้ใช้บนหน้าจอ (เช่นตรวจสอบแล้ว ช่องทำเครื่องหมายนั้นแสดงกล่องข้อความไม่ถูกตรวจสอบแล้วซ่อนกล่องข้อความ ฯลฯ .. ) จากนั้นใช้ng-show


-17

ข้อแตกต่างที่น่าสนใจอย่างหนึ่งของ ng-if และ ng-show คือ:

การรักษาความปลอดภัย

องค์ประกอบ DOM มีอยู่ในบล็อก ng-if จะไม่ถูกแสดงผลในกรณีที่ค่าเป็นเท็จ

โดยที่ในกรณีของ ng-show ผู้ใช้สามารถเปิดหน้าต่างองค์ประกอบการตรวจสอบและตั้งค่าเป็น TRUE

และด้วยเสียงโห่ร้องเนื้อหาทั้งหมดที่ตั้งใจจะซ่อนจะถูกแสดงซึ่งเป็นการละเมิดความปลอดภัย :)


27
นี่เป็นรูปแบบความปลอดภัยที่อ่อนแออย่างยิ่ง หากเนื้อหานั้นมอบให้กับลูกค้าโดยเซิร์ฟเวอร์คุณต้องถือว่าผู้ใช้ / ผู้โจมตีสามารถเข้าถึงได้โดยไม่คำนึงว่ามีอยู่ใน DOM หรือไม่ ตรรกะการอนุญาตทั้งหมดต้องถูกบังคับใช้โดยเซิร์ฟเวอร์
tlrobinson

คิดเกี่ยวกับ html มากกว่า jsp ... ตอนนี้ถ้าคุณต้องการบังคับใช้ความปลอดภัยบนส่วนประกอบ html .. ถ้าคุณต้องการซ่อนส่วนประกอบจากผู้ใช้ ... คุณจะทำอย่างไรให้สำเร็จ และสิ่งที่ในกรณีที่การกำหนดค่าของคุณแบ่งออกเป็นฝั่งเซิร์ฟเวอร์สำหรับแบ็กเอนด์และฝั่งไคลเอ็นต์สำหรับส่วนหน้า ..
Ashish_B
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.