เมื่อใดควรใช้ <ui: include> ไฟล์แท็กคอมโพสิตคอมโพสิตและ / หรือคอมโพเนนต์แบบกำหนดเอง


102

ฉันเริ่มใช้ JSF 2.0 กับ Facelets เมื่อเร็ว ๆ นี้และรู้สึกงงงวยกับส่วนประกอบคอมโพสิตใหม่ที่รู้<ui:include>เทคนิคที่มีอยู่และเทคนิคอื่น ๆ ที่ Facelets 1.x นำเสนอ

อะไรคือความแตกต่างระหว่างแนวทางเหล่านี้? ดูเหมือนว่าพวกเขาจะนำเสนอสิ่งเดียวกัน: <ui:param>vs <cc:attribute>, <ui:insert>+ <ui:define>vs tag files, การนำเทมเพลตที่มีอยู่มาใช้ซ้ำ มีอะไรนอกเหนือจากไวยากรณ์และข้อกำหนดของอินเทอร์เฟซที่ชัดเจนในกรณีของคอมโพสิตหรือไม่? ประสิทธิภาพอาจแตกต่างกันหรือไม่?

คำตอบ:


176

อะไรคือความแตกต่างระหว่างแนวทางเหล่านี้?

เทมเพลต Facelet

ใช้ Facelet แม่ (ในขณะที่<ui:composition>, <ui:include>และ<ui:decorate>) ถ้าคุณต้องการที่จะแยกชิ้นส่วนหลักเค้าโครงหน้าเป็นแม่แบบ Reuseable เช่นส่วนหัวเมนูเนื้อหาส่วนท้าย ฯลฯ

ตัวอย่าง:

ไฟล์แท็ก Facelet

ใช้ไฟล์แท็ก Facelet หากคุณต้องการมีกลุ่มส่วนประกอบที่ใช้ซ้ำได้เพื่อป้องกัน / ลดการทำซ้ำรหัส เช่นกลุ่มของป้ายกำกับ + อินพุต + คอมโพเนนต์ข้อความ ความแตกต่างที่สำคัญกับส่วนประกอบคอมโพสิตคือผลลัพธ์ของไฟล์แท็ก Facelet ไม่ได้แสดงถึงไฟล์เดียวUIComponentและในบางสถานการณ์อาจเป็นทางออกเดียวเมื่อส่วนประกอบคอมโพสิตไม่เพียงพอ โดยทั่วไปการ<ui:include>มีอย่างน้อยหนึ่งรายการ<ui:param>ซึ่งส่งผ่านคุณสมบัติ bean ที่มีการจัดการ (และไม่ใช่ค่าฮาร์ดโค้ด) เป็นสัญญาณว่าไฟล์รวมสามารถเป็นไฟล์แท็กได้ดีกว่า

ตัวอย่าง:

ส่วนประกอบคอมโพสิต

ใช้คอมโพสิตคอมโพเนนต์หากคุณต้องการสร้างแบบกำหนดเองUIComponentเดียวและใช้ซ้ำได้ด้วยความรับผิดชอบเดียวโดยใช้ XML ที่บริสุทธิ์ ส่วนประกอบคอมโพสิตดังกล่าวมักประกอบด้วยส่วนประกอบและ / หรือ HTML ที่มีอยู่จำนวนมากและได้รับการแสดงผลทางกายภาพเป็นองค์ประกอบเดียวและควรถูกผูกไว้กับคุณสมบัติ bean เดียว เช่นคอมโพเนนต์ที่แสดงjava.util.Dateคุณสมบัติเดียวโดย 3 <h:selectOneMenu>องค์ประกอบที่ขึ้นต่อกันหรือส่วนประกอบที่รวม<p:fileUpload>และ<p:imageCropper>เป็นองค์ประกอบเดียวที่<my:uploadAndCropImage>อ้างอิงcom.example.Imageเอนทิตีแบบกำหนดเองเดียวเป็นคุณสมบัติ

ตัวอย่าง:

ส่วนประกอบที่กำหนดเอง

ใช้ส่วนประกอบที่กำหนดเองเมื่อใดก็ตามที่ไม่สามารถใช้งานได้กับไฟล์แท็ก Facelet หรือส่วนประกอบคอมโพสิตเนื่องจากไม่มีการสนับสนุนในชุดส่วนประกอบมาตรฐาน / ที่มีอยู่ ตัวอย่างสามารถพบได้ทั่วสถานที่ทั้งหมดในรหัสที่มาของห้องสมุดองค์ประกอบที่มาเปิดเช่นPrimeFacesและOmniFaces

เครื่องจัดการแท็ก

เมื่อคุณต้องการควบคุมการสร้างโครงสร้างคอมโพเนนต์ JSF แทนการแสดงผลเอาต์พุต HTML คุณควรใช้เครื่องจัดการแท็กแทนส่วนประกอบ

ตัวอย่าง:

ตัวอย่างโครงการ

ต่อไปนี้เป็นโครงการตัวอย่างที่ใช้เทคนิคที่กล่าวมาทั้งหมด


ประสิทธิภาพอาจแตกต่างกันหรือไม่?

ในทางเทคนิคแล้วความกังวลเกี่ยวกับประสิทธิภาพนั้นมีน้อยมาก ทางเลือกควรขึ้นอยู่กับข้อกำหนดการทำงานที่เป็นรูปธรรมและระดับสุดท้ายของนามธรรมการนำกลับมาใช้ใหม่และการบำรุงรักษาของการนำไปใช้งาน แต่ละแนวทางมีวัตถุประสงค์และข้อ จำกัด ที่ชัดเจนของตัวเอง

อย่างไรก็ตามส่วนประกอบคอมโพสิตมีค่าใช้จ่ายที่สำคัญในระหว่างการสร้าง / กู้คืนมุมมอง (โดยเฉพาะ: ระหว่างการบันทึก / กู้คืนสถานะมุมมอง) และใน Mojarra เวอร์ชันเก่าส่วนประกอบคอมโพสิตมีปัญหาด้านประสิทธิภาพในการกำหนดค่าเริ่มต้นซึ่งได้รับการแก้ไขแล้วตั้งแต่ 2.1.13 นอกจากนี้ Mojarra ยังมีหน่วยความจำรั่วเมื่อใช้ a <cc:attribute method-signature>สำหรับนิพจน์เมธอดโดยทั่วไปโครงสร้างส่วนประกอบทั้งหมดจะถูกอ้างอิงอีกครั้งในเซสชัน HTTP ซึ่งได้รับการแก้ไขตั้งแต่ 2.1.29 / 2.2.8 การรั่วไหลของหน่วยความจำสามารถข้ามได้ในเวอร์ชัน 2.1 ที่เก่ากว่าดังนี้:

<context-param>
    <param-name>com.sun.faces.serializeServerState</param-name>
    <param-value>true</param-value>
</context-param>

หรือในเวอร์ชัน 2.2 ที่เก่ากว่าดังต่อไปนี้:

<context-param>
    <param-name>javax.faces.SERIALIZE_SERVER_STATE</param-name>
    <param-value>true</param-value>
</context-param>

ถึงกระนั้นเมื่อคุณมีคอมโพสิตที่ค่อนข้าง "เยอะ" และคุณjavax.faces.STATE_SAVING_METHODตั้งค่าเป็นclientแล้วประสิทธิภาพจะเป็นความเจ็บปวด อย่าใช้ส่วนประกอบคอมโพสิตในทางที่ผิดหากคุณเพียงแค่ต้องการฟังก์ชันพื้นฐานที่เป็นไปได้ด้วยไฟล์รวมไฟล์หรือแท็กง่ายๆ อย่าใช้ความง่ายในการกำหนดค่า (อ่าน: ไม่*.taglib.xmlจำเป็นต้องใช้ไฟล์) เป็นข้ออ้างในการเลือกใช้คอมโพสิตมากกว่าไฟล์แท็ก

เมื่อใช้ Mojarra 2.2.10 ขึ้นไปอย่าลืมปิดใช้งานระยะเวลารีเฟรช Facelets ที่ค่อนข้างสั้นสำหรับโหมดการผลิต:

<context-param>
    <param-name>javax.faces.FACELETS_REFRESH_PERIOD</param-name>
    <param-value>-1</param-value>
</context-param>

อย่าใช้การตั้งค่านี้ในการพัฒนามิฉะนั้นคุณต้องรีสตาร์ทเซิร์ฟเวอร์ทั้งหมดเพื่อรับการเปลี่ยนแปลงในไฟล์ Facelets เพื่อให้แสดงผล! Mojarra 2.2.11 และใหม่กว่าและ MyFaces มีค่าเริ่มต้นอยู่แล้ว-1เมื่อjavax.faces.PROJECT_STAGEไม่ได้ตั้งค่าเป็นDevelopment.


ทำไมคุณถึงต้องการเรนเดอร์ 1 องค์ประกอบ (องค์ประกอบคอมโพสิต) แทนที่จะเป็น 3 (ไฟล์แท็ก facelet) ฉันหมายความว่าในวันที่มีแดดคุณอาจจะรู้สึกว่าเป็น 1 แทนที่จะเป็น 3 ... แต่ฉันเดาว่ามีอย่างอื่นอยู่เบื้องหลัง ในตัวอย่างของคุณคุณกำลังขยาย UINamingContainer ... นั่นอาจเป็นสาเหตุหนึ่งที่ต้องใช้ cc (เพื่อให้สามารถเขียนทับฟังก์ชันเฉพาะการใช้งาน jsf บางอย่างได้)?
ทศกัณฐ์

2
ไฟล์แท็กควรถูกมองว่าเป็นประเภทรวม ส่วนประกอบคอมโพสิตควรถูกมองว่าเป็นส่วนประกอบจริง ส่วนประกอบคอมโพสิตจำเป็นต้องนำไปใช้NamingContainerมิฉะนั้นคุณจะพบปัญหารหัสซ้ำกันเมื่อส่วนประกอบเดียวกันถูกนำมาใช้ซ้ำหลายครั้ง
BalusC

@BalusC สมมติว่าฉันมี HTML และ JSF จำนวนมากที่สร้าง 'บล็อก' ที่ช่วยให้ฉันสามารถเพิ่มหรือลบที่อยู่ (และแอตทริบิวต์ทั้งหมดนี้ ได้แก่ ถนนหมายเลขเมือง ฯลฯ ) ฉันจำเป็นต้องใช้บล็อกเดียวกันนั้นใน 2 หรือ 3 หน้า สิ่งนี้อยู่ภายใต้คำอธิบายของคอมโพสิตคอมโพเนนต์ของคุณหรือไม่?
RinaldoPJr

1
@Rinaldo: ฉันคิดว่าฉันต้องการใช้ไฟล์แท็กที่มีรหัสองค์ประกอบแบบไดนามิกเหมือนแสดงให้เห็นในstackoverflow.com/questions/5713718/... IMO ถ้าสามารถทำได้ด้วยไฟล์แท็กให้ใช้ หากไม่สามารถทำได้กับไฟล์แท็กให้ใช้คอมโพสิต หากคุณต้องการส่วนประกอบหลายอย่างเพื่อจัดการกับคุณสมบัติเดียว (ไม่ใช่ที่อยู่ แต่เช่นชื่อถนน + หมายเลขบ้านซึ่งควรอยู่ในคุณสมบัติเดียว) ส่วนประกอบแบบผสมจะเป็นทางออกเดียว
BalusC

2
@Tarik: คอมโพสิตมีค่าใช้จ่ายจำนวนมากเมื่อเทียบกับแท็กไฟล์ กล่าวอีกนัยหนึ่ง: ประสิทธิภาพต่ำ ใช้เฉพาะเมื่อคุณต้องการสร้างคอมโพเนนต์ UI ที่กำหนดเองเดียวโดยอิงตามชุดของส่วนประกอบที่มีอยู่ที่เกี่ยวข้องอย่างใกล้ชิด ไม่สามารถทำได้ด้วย tagfile ตัวอย่างเช่น ZEEF.com มีองค์ประกอบเดียวเท่านั้น: สิ่งที่อัพโหลด / ดาวน์โหลด / ครอบตัดภาพแบบ all-in-one ซึ่งใช้ในรูปภาพหน้า ao รูปโปรไฟล์ส่วนหัวบล็อกลิงก์บล็อกรูปภาพเป็นต้นซึ่งจะผูกไว้กับImageคุณสมบัติเท่านั้น ในถั่ว
BalusC
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.