ทำไมแฟรกเมนต์ใน React 16 จึงดีกว่า container divs?


165

ใน React 16.2 Fragmentsมีการเพิ่มการสนับสนุนที่ปรับปรุงแล้ว ข้อมูลเพิ่มเติมสามารถดูได้ที่โพสต์บล็อกของ React ที่นี่

เราทุกคนคุ้นเคยกับรหัสต่อไปนี้:

render() {
  return (
    // Extraneous div element :(
    <div>
      Some text.
      <h2>A heading</h2>
      More text.
      <h2>Another heading</h2>
      Even more text.
    </div>
  );
}

ใช่เราต้องการ div container แต่ก็ไม่ใช่เรื่องใหญ่

ใน React 16.2 เราสามารถทำได้เพื่อหลีกเลี่ยง div container ที่อยู่โดยรอบ:

render() {
  return (
    <Fragment>
      Some text.
      <h2>A heading</h2>
      More text.
      <h2>Another heading</h2>
      Even more text.
    </Fragment>
  );
}

ไม่ว่าในกรณีใดเรายังจำเป็นต้องมีองค์ประกอบคอนเทนเนอร์ล้อมรอบองค์ประกอบภายใน

คำถามของฉันคือทำไมใช้Fragmentดีกว่า มันช่วยในเรื่องประสิทธิภาพหรือไม่? ถ้าเป็นเช่นนั้นทำไม จะรักวิปัสสนาบ้าง


2
ฉันคิดว่ามันมีประโยชน์จริงๆสำหรับการจัดแต่งทรงผมแบบ flexbox เมื่อสร้างเด็กระดับแรกสำหรับผู้ปกครอง
willwoo

32
ปัญหากับdivคือคุณไม่ต้องการองค์ประกอบ wrapper องค์ประกอบของ Wrapper มีความหมายและโดยปกติคุณต้องมีสไตล์เพิ่มเติมเพื่อลบความหมายนั้นออก <Fragment>เป็นเพียงน้ำตาลทรายที่ไม่ได้ให้ผล มีบางสถานการณ์ที่การสร้าง wrapper นั้นยากมากตัวอย่างเช่นใน SVG ที่<div>ไม่สามารถใช้งานได้และ<group>ไม่ได้เป็นอย่างที่คุณต้องการเสมอไป
Sulthan

คำตอบ:


305
  1. มันเร็วขึ้นเล็กน้อยและมีการใช้หน่วยความจำน้อยกว่า (ไม่จำเป็นต้องสร้างโหนด DOM เพิ่มเติม) นี่เป็นเพียงผลประโยชน์ที่แท้จริงบนต้นไม้ที่มีขนาดใหญ่และ / หรือลึก แต่ประสิทธิภาพของแอปพลิเคชันมักจะทนทุกข์ทรมานจากการตายโดยการตัดหนึ่งพันครั้ง นี่คือหนึ่งตัดน้อย
  2. กลไก CSS บางอย่างเช่น Flexbox และ CSS Grid มีความสัมพันธ์พิเศษกับผู้ปกครองเด็กและการเพิ่มdivs ที่อยู่ตรงกลางทำให้ยากที่จะรักษาเค้าโครงที่ต้องการในขณะที่แยกส่วนประกอบตรรกะ
  3. ตัวตรวจสอบ DOM มีความยุ่งเหยิงน้อยลง :-)

คุณสามารถค้นหาคำอธิบายของกรณีการใช้งานอื่น ๆ ในปัญหาการตอบสนองนี้: เพิ่ม Fragment API เพื่อให้สามารถส่งคืนองค์ประกอบหลายรายการจากการแสดงผล


24
4. การเขียนรายการคำจำกัดความ<dt><dd>ทำให้ง่ายขึ้นมาก กลับองค์ประกอบจับคู่Fragmentsเป็นที่น่าอึดอัดใจก่อน
Sonson123

เศษเล็กเศษน้อยทำงานเป็นปฏิกิริยาพื้นเมืองหรือไม่ import Fragment from 'react'ผมพยายามที่จะ แต่มันไม่ได้กำหนดไว้ใน RN
binchik

3
สำหรับnumber 2ตารางจริง ๆ แล้วเป็นปัญหาที่ใหญ่ที่สุดสำหรับเรา โครงสร้างที่ต้องการของtable>tr>td(อาจมีtheadและคล้ายกัน) ทำขึ้นสำหรับโค้ด React ที่น่าอึดอัดใจบางอย่าง
Matsemann

2
@binchik ลองimport {Fragment} from 'react'? เป็นการส่งออกที่มีชื่อ
Soska

1
หมายเลข 3 เป็นสิ่งสำคัญที่สุด!
Zach Smith

28

การเพิ่มคำตอบทั้งหมดข้างต้นมีข้อได้เปรียบมากขึ้น: การอ่านรหัส , สนับสนุนองค์ประกอบรูปแบบน้ำตาลประโยค,Fragment <>ดังนั้นรหัสในคำถามของคุณสามารถเขียนได้ง่ายขึ้นเป็น:

render() {
  return (
    <>
      Some text.
      <h2>A heading</h2>
      More text.
      <h2>Another heading</h2>
      Even more text.
    </>
  );
}

ตามเอกสาร ,

ใน React desugars นี้ไปยัง<React.Fragment/>องค์ประกอบดังในตัวอย่างจากส่วนก่อนหน้า (เฟรมเวิร์ก Non-React ที่ใช้ JSX อาจคอมไพล์กับบางอย่างที่แตกต่างกัน)

ไม่เกะกะใช่มั้ย

โปรดทราบว่าคุณยังคงต้องใช้<Fragment>ไวยากรณ์หากคุณจำเป็นต้องระบุให้keyกับส่วน


ปัจจุบันไวยากรณ์ที่สั้นกว่านี้ยังไม่ได้รับการสนับสนุนใน create-react-app อ้างอิง: reactjs.org/docs/fragments.html#short-syntax
codingsplash

2
@codingsplash CRA 2.0 ได้แล้วตอนนี้
พบกับ Zaveri

1
ไม่สามารถยืนน้ำตาล syntactic ชิ้นนี้ได้มันดูไม่ตั้งใจและสื่อถึงความหมายโดยธรรมชาติเพียงเล็กน้อย ชอบมาก<Fragment>
ESR

3
@ESR ส่วนตัวฉันชอบมัน คิดแบบนี้ เด็ก ๆ ไม่มีอะไรห่อหุ้มเหมือนกับไม่มีอะไรใน <> มองไม่เห็น
user3614030

6
  • คุณสมบัติที่เพิ่มเป็นไปไม่ได้มาก่อนด้วย JSX
  • มาร์กอัป jsx semantic ที่ดีขึ้น องค์ประกอบห่อหุ้มถูกนำมาใช้เมื่อไม่จำเป็นเพราะพวกเขาถูกบังคับให้
  • มาร์กอัป dom โดยรวมน้อยลง (เพิ่มประสิทธิภาพการเรนเดอร์และลดโอเวอร์เฮดของหน่วยความจำ)

มันง่ายเหมือนเมื่อคุณไม่ต้องการองค์ประกอบ wrapper คุณไม่ได้ถูกบังคับให้ใช้ การมีองค์ประกอบน้อยลงเป็นสิ่งที่ดี แต่ฉันคิดว่าประโยชน์ที่ใหญ่ที่สุดคือสามารถแสดงองค์ประกอบใน jsx ที่ไม่สามารถทำได้ก่อนหน้านี้และเพิ่มความหมายเชิงความหมายที่ดีขึ้นให้กับองค์ประกอบห่อหุ้ม

สิ่งนี้เป็นไปไม่ได้มาก่อน:

 <select>
    {this.renderOptions()}
 </select>

การดูต่อไปนี้ใน React 15 คุณไม่สามารถบอกได้ว่าจำเป็นต้องใช้องค์ประกอบของ wrapper หรือไม่:

<span>
  <h1>Hello</h1>
  {this.getContent()}
</span>

2

ตาม reactjs.org docsความต้องการที่สำคัญที่สุด<Fragment> </Fragment>แทน div ของคือการหลีกเลี่ยงการแยกความหมาย HTML เมื่อเราใช้ div แทนการ<Fragment> </Fragment>แบ่ง semantics ของ HTML

หากต้องการทราบข้อมูลเพิ่มเติมเกี่ยวกับความหมาย html โปรดคลิก และมีบางกรณีที่หากคุณใช้ div แทนการใช้ Fragments มันจะเป็น html ที่ไม่ถูกต้องเช่นดูที่รหัสนี้:

class Columns extends React.Component {
  render() {
    return (
      <div>
        <td>Hello</td>
        <td>World</td>
      </div>
    );
  }
}

<table>
      <tr>
        <div>
          <td>Hello</td>
          <td>World</td>
        </div>
      </tr>
 </table>

ส่วนย่อยแก้ปัญหานี้ได้


1
  1. ใช้<React.Fragment>...</React.Fragment>เราสามารถเพิ่มแท็กพาเรนต์ไปยังองค์ประกอบ JSX ของเราโดยไม่ต้องเพิ่มโหนดพิเศษให้กับ DOM
  2. คุณสามารถแทนที่แท็ก div พิเศษด้วย React.Fragment
  3. การเขียน React.Fragment ทุกครั้งยาวเกินไปสำหรับคุณ React.Fragment มีไวยากรณ์ชวเลขที่คุณสามารถใช้ได้ มันคือ<>...</>.
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.