08 ส.ค. 2568·อ่าน 2 นาที

คอมโพเนนต์ Vue แบบกำหนดเองใน UI ที่สร้างโดยระบบ — ปลอดภัยและรองรับการสร้างใหม่

เรียนรู้วิธีเพิ่มคอมโพเนนต์ Vue แบบกำหนดเองใน UI ที่สร้างโดยระบบโดยไม่ทำให้การสร้างใหม่เสียหาย ด้วยรูปแบบแยกชัด ขอบเขตที่ชัดเจน และกฎการส่งมอบที่เรียบง่าย

คอมโพเนนต์ Vue แบบกำหนดเองใน UI ที่สร้างโดยระบบ — ปลอดภัยและรองรับการสร้างใหม่

อะไรที่พังเมื่อคุณแก้ UI ที่ถูกสร้างขึ้น

UI ที่ถูกสร้างออกมาออกแบบให้สามารถสร้างใหม่ได้ ในแพลตฟอร์มอย่าง AppMaster โค้ดเว็บแอป Vue3 ถูกผลิตจากตัวสร้างแบบวิชวล การสร้างใหม่ (regeneration) คือวิธีที่ทำให้การเปลี่ยนแปลงคงที่ระหว่างหน้าจอ ลอจิก และโมเดลข้อมูล

ปัญหาง่าย ๆ คือ: ถ้าคุณแก้ไฟล์ที่ถูกสร้างขึ้นโดยตรง การสร้างใหม่ครั้งถัดไปอาจเขียนทับการแก้ของคุณได้

นั่นจึงเป็นเหตุผลที่ทีมมักเพิ่มโค้ดแบบกำหนดเอง บล็อก UI ที่มีมักครอบคลุมฟอร์มและตารางมาตรฐาน แต่แอปจริงมักต้องการส่วนพิเศษไม่กี่อย่าง: ชาร์ตซับซ้อน ตัวเลือกแผนที่ ตัวแก้ข้อความขั้นสูง แผงเซ็นชื่อ หรือเครื่องมือวางแผนแบบลากแล้ววาง เหล่านี้เป็นเหตุผลที่ดีในการเพิ่มคอมโพเนนต์ Vue แบบกำหนดเอง ตราบใดที่คุณปฏิบัติต่อมันเหมือนส่วนเสริม ไม่ใช่การแก้ไฟล์ที่มีอยู่

เมื่อโค้ดแบบกำหนดเองผสมกับโค้ดที่สร้างขึ้น ความล้มเหลวจะมาช้าและสับสน คุณอาจไม่สังเกตจนกว่าการเปลี่ยน UI ครั้งถัดไปจะบังคับให้สร้างใหม่ หรือจนกว่าคนในทีมจะปรับหน้าจอในตัวแก้แบบวิชวล ปัญหาทั่วไปได้แก่:

  • มาร์กอัพแบบกำหนดเองของคุณหายไปเพราะเทมเพลตถูกสร้างใหม่
  • การ import หรือการลงทะเบียนพังเพราะชื่อไฟล์หรือโครงสร้างเปลี่ยน
  • "การแก้เล็กน้อย" กลายเป็นความขัดแย้งในการรวมโค้ดทุกครั้งที่ deploy
  • ลอจิกที่ถูกสร้างและลอจิกแบบกำหนดเองเบี่ยงกัน ทำให้กรณีขอบเกิดความผิดพลาด
  • การอัปเกรดรู้สึกเสี่ยงเพราะคุณไม่รู้ว่าจะมีอะไรถูกแทนที่บ้าง

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

กฎขอบเขตที่ทำให้การสร้างใหม่ปลอดภัย

ถ้าคุณต้องการปรับแต่งโดยไม่เสียงาน ให้ทำตามกฎเดียว: ห้ามแก้ไฟล์ที่ถูกสร้างขึ้นโดยตรง ถือพวกมันเป็นผลลัพธ์แบบอ่านอย่างเดียว เหมือนกับไฟล์ที่คอมไพล์แล้ว

คิดว่า UI ของคุณมีสองโซน:

  • โซนที่สร้างขึ้น: หน้า เลย์เอาต์ และสกรีนที่ตัวสร้างผลิต
  • โซนแบบกำหนดเอง: คอมโพเนนต์ Vue ที่คุณเขียนเองในโฟลเดอร์แยก

UI ที่ถูกสร้างควรใช้คอมโพเนนต์ของคุณ มันไม่ควรเป็นที่สร้างคอมโพเนนต์เหล่านั้น

เพื่อให้ใช้งานระยะยาวได้ ให้ขอบเขตเล็กและชัด วิดเจ็ตแบบกำหนดเองควรทำตัวเหมือนสินค้าตัวเล็กที่มีสัญญา:

  • Props เข้า: เฉพาะสิ่งที่ต้องใช้ในการเรนเดอร์เท่านั้น
  • Events ออก: เฉพาะสิ่งที่หน้าจอต้องตอบสนอง

หลีกเลี่ยงการเข้าถึงสถานะทั่วโลกหรือเรียก API ที่ไม่เกี่ยวข้องจากภายในวิดเจ็ต เว้นแต่นั่นจะเป็นส่วนหนึ่งของสัญญาอย่างชัดเจน

กับหน้าจอ Vue3 ในสไตล์ AppMaster นั่นหมายถึงการเดินสาย (wiring) ในหน้าจอที่ถูกสร้างให้น้อยที่สุดเพื่อส่ง props และจัดการ events การเดินสายนี้อาจเปลี่ยนข้ามการสร้างใหม่ แต่ก็ยังเล็กและง่ายที่จะทำซ้ำ งานจริงจะปลอดภัยอยู่ในโซนแบบกำหนดเอง

รูปแบบการแยกที่ทำงานได้ดีกับ Vue3

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

แนวทางปฏิบัติที่ได้ผลคือเก็บวิดเจ็ตเฉพาะเป็นโมดูลภายในขนาดเล็ก: คอมโพเนนต์ สไตล์ และยูทิลิตี้ช่วยเหลือไว้ในที่เดียว ในแอป Vue3 ที่ถูกสร้าง มักหมายความว่าโค้ดแบบกำหนดเองอยู่ภายนอกหน้าที่ถูกสร้างและถูก import เป็น dependency

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

รูปแบบที่ยืนได้ดีมีดังนี้:

  • ปฏิบัติต่อวิดเจ็ตเป็นกล่องดำ: props เข้า, events ออก
  • ใช้ wrapper เพื่อแมปการตอบ API, วันที่, และ ID เป็นรูปแบบที่วิดเจ็ตเข้าใจ
  • เก็บสไตล์แบบ scoped เพื่อไม่ให้หน้าที่สร้างใหม่เขียนทับวิดเจ็ตของคุณโดยไม่ได้ตั้งใจ
  • อย่าอาศัยโครงสร้าง DOM ของพาเรนท์หรือชื่อคลาสเฉพาะหน้าจอ

เรื่องสไตลิ่ง ให้เลือก CSS แบบ scoped (หรือ CSS Modules) และตั้งชื่อคลาสแชร์ด้วยชื่อที่มี namespace หากวิดเจ็ตต้องเข้ากับธีมของแอป ให้ส่ง token ธีมเป็น props (สี ระยะ ขนาดฟอนต์) แทนการนำเข้า style ของหน้า

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

ออกแบบสัญญาคอมโพเนนต์ที่เสถียร (props และ events)

วิธีที่ปลอดภัยที่สุดคือปฏิบัติวิดเจ็ตแต่ละตัวเหมือนอินเทอร์เฟซคงที่ หน้าจอที่ถูกสร้างอาจเปลี่ยน แต่คอมโพเนนต์ของคุณไม่ควรเปลี่ยน

เริ่มจากอินพุต (props) ให้เล็ก คาดเดาได้ และตรวจสอบง่าย ชอบค่าพื้นฐานแบบ primitive และวัตถุเรียบที่คุณควบคุม เพิ่มค่าเริ่มต้นเพื่อให้วิดเจ็ตทำงานได้แม้หน้าส่งค่าไม่ครบ หากบางค่าอาจผิดรูป (ID, สตริงวันที่, ค่าที่คล้าย enum) ให้ validate และล้มเหลวอย่างสุภาพ: แสดงสถานะว่างแทนการค้าง

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

  • update:modelValue สำหรับ v-model
  • change สำหรับการเปลี่ยนที่ผู้ใช้ยืนยัน (ไม่ใช่ทุกครั้งที่พิมพ์)
  • error เมื่อคอมโพเนนต์ไม่สามารถทำงานให้เสร็จ
  • ready เมื่องานแบบอะซิงก์เสร็จและวิดเจ็ตพร้อมใช้งาน

ถ้ามีงานอะซิงก์ ให้ทำให้เป็นส่วนหนึ่งของสัญญา เปิดเผย loading และ disabled เป็น props และพิจารณา errorMessage สำหรับความล้มเหลวจากฝั่งเซิร์ฟเวอร์ หากคอมโพเนนต์ดึงข้อมูลเอง ให้ยังคง emit error และ ready เพื่อให้พาเรนท์ตอบโต้ได้ (เช่น toast, logging, UI สำรอง)

ความคาดหวังด้านการเข้าถึง (Accessibility)

ฝังการเข้าถึงไว้ในสัญญา ยอมรับ label (หรือ ariaLabel) prop อธิบายพฤติกรรมคีย์บอร์ด และทำให้โฟกัสคาดเดาได้หลังการกระทำ

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

ขั้นตอนทีละข้อ: เพิ่มวิดเจ็ตเฉพาะโดยไม่แตะไฟล์ที่สร้าง

ปรับแต่ง UI โดยไม่เกิดความเสียหาย
สร้างหน้าจอ Vue3 แล้วเพิ่มวิดเจ็ตแบบกำหนดเองโดยไม่แก้ไฟล์ที่ถูกสร้างขึ้น
ลอง AppMaster

เริ่มจากเล็ก: หน้าจอเดียวที่ผู้ใช้สนใจ วิดเจ็ตชิ้นเดียวที่ทำให้ประสบการณ์แตกต่าง การเปลี่ยนครั้งแรกที่แคบทำให้เห็นว่าการสร้างใหม่มีผลอย่างไร

  1. สร้างคอมโพเนนต์นอกพื้นที่ที่ถูกสร้าง วางในโฟลเดอร์ที่คุณเป็นเจ้าของและเก็บใน source control (มักเป็นโฟลเดอร์ custom หรือ extensions)

  2. เก็บผิวสาธารณะให้เล็ก props ไม่กี่ตัวเข้า, events ไม่กี่ตัวออก อย่าส่ง state ทั้งหน้าลงไป

  3. เพิ่ม wrapper บางๆ ที่คุณเป็นเจ้าของ งานของมันคือแปลง "ข้อมูลหน้าที่ถูกสร้าง" ให้เข้ากับสัญญาของวิดเจ็ต

  4. ผสานผ่านจุดขยายที่รองรับ อ้างอิง wrapper โดยไม่ต้องแก้ไฟล์ที่ถูกสร้าง

  5. สร้างใหม่และยืนยัน โฟลเดอร์ custom, wrapper และคอมโพเนนต์ของคุณควรไม่เปลี่ยนและคอมไพล์ได้

รักษาขอบให้คม วิดเจ็ตโฟกัสที่การแสดงผลและการโต้ตอบ Wrapper แปลงข้อมูลและส่งต่อการกระทำ กฎทางธุรกิจเก็บไว้ที่เลเยอร์ตรรกะของแอป (backend หรือ process ที่แชร์) ไม่ใช่ฝังในวิดเจ็ต

การเช็คสุขภาพง่าย ๆ: ถ้าสร้างใหม่ตอนนี้ เพื่อนร่วมทีมสามารถสร้างแอปขึ้นมาใหม่และได้ผลลัพธ์เดียวกันโดยไม่ต้องทำการแก้ด้วยมือไหม? ถ้าได้ แพทเทิร์นของคุณแข็งแรง

จะวางลอจิกไว้ตรงไหนเพื่อให้ UI ดูแลรักษาง่าย

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

ค่าเริ่มต้นที่ดี: เก็บกฎธุรกิจไว้ที่เลเยอร์หน้า (page) หรือ feature และทำให้วิดเจ็ตเป็น "dumb" หน้าเป็นคนตัดสินว่าควรส่งข้อมูลอะไรให้วิดเจ็ตและจะทำอะไรเมื่อวิดเจ็ต emit event วิดเจ็ตแค่เรนเดอร์และรายงานเจตนา

เมื่อจำเป็นต้องมีลอจิกใกล้วิดเจ็ต (การฟอร์แมต สเตทเล็ก การตรวจสอบฝั่งไคลเอนต์) ซ่อนมันหลังเลเยอร์บริการเล็กๆ ใน Vue3 นั่นอาจเป็นโมดูล, composable, หรือ store ที่มี API ชัดเจน วิดเจ็ตนำเข้า API นั้น ไม่ใช่ internals แบบสุ่มของแอป

การแยกที่เป็นประโยชน์:

  • Widget (component): สถานะ UI การจัดการอินพุต รูปลักษณ์ และ emit events เช่น select, change, retry
  • Service/composable: การปั้นข้อมูล, caching, แมปข้อผิดพลาด API เป็นข้อความที่อ่านได้
  • Page/container: กฎทางธุรกิจ, สิทธิ์, ข้อมูลที่จะโหลด, เวลาในการบันทึก
  • ส่วนที่ถูกสร้างของแอป: ไม่แตะ ให้ส่งข้อมูลเข้าและฟัง events

หลีกเลี่ยงการเรียก API โดยตรงจากวิดเจ็ต เว้นแต่นั่นคือสัญญาของวิดเจ็ตจริงๆ หากมันเป็นผู้รับผิดชอบการดึงข้อมูล ให้ทำให้ชัดในชื่อ (เช่น CustomerSearchWidget) และเก็บโค้ดเรียกใน service เดียว มิฉะนั้น ให้ส่ง items, loading, และ error ลงเป็น props

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

ตัวอย่าง: วิดเจ็ต ApprovalBadge แบบกำหนดเองไม่ควรตัดสินว่า invoice สามารถอนุมัติได้หรือไม่ ให้หน้าคำนวณ status และ canApprove แล้ว badge emit approve หน้าเป็นคนเรียก backend (เช่น API ที่คุณโมเดลใน AppMaster) แล้วส่งสถานะสำเร็จหรือข้อผิดพลาดกลับเข้า UI อย่างชัดเจน

ความผิดพลาดทั่วไปที่ทำให้เกิดปัญหาหลังการสร้างใหม่ครั้งถัดไป

ส่งมอบวิดเจ็ตแบบเฉพาะตัวหนึ่งชิ้น
เพิ่มวิดเจ็ตเช่น timeline หรือ chart ให้หน้าจอจริงโดยไม่ต้องแก้ไฟล์ด้วยมือ
สร้างแดชบอร์ด

ปัญหาส่วนใหญ่ไม่ใช่เรื่อง Vue แต่เกิดจากการผสมงานแบบกำหนดเองเข้าไปในที่ที่ตัวสร้างเป็นเจ้าของ หรือพึ่งพารายละเอียดที่อาจเปลี่ยนได้

ความผิดพลาดที่มักจะเปลี่ยนวิดเจ็ตเล็กๆ ให้กลายเป็นงานล้างซ้ำ ๆ:

  • แก้ไฟล์ Vue ที่ถูกสร้างโดยตรงแล้วลืมว่าทำอะไรไป
  • ใช้ global CSS หรือตัวเลือกที่กว้างซึ่งมีผลกับหน้าจออื่นเมื่อมาร์กอัพเปลี่ยน
  • อ่านหรือแก้รูปแบบสถานะที่สร้างโดยตรง ทำให้การเปลี่ยนชื่อทลายวิดเจ็ต
  • ยัดสมมติฐานเฉพาะหน้าลงในคอมโพเนนต์เดียว
  • เปลี่ยน API ของคอมโพเนนต์ (props/events) โดยไม่มีแผนย้ายรุ่น

สถานการณ์ทั่วไป: คุณเพิ่มวิดเจ็ตตารางแบบกำหนดเองแล้วมันใช้ได้ เดือนต่อมา การเปลี่ยนเลย์เอาต์ที่สร้างทำให้กฎ .btn ทั่วไปของคุณส่งผลกับหน้า login หรือ admin หรือวัตถุข้อมูลเปลี่ยนจาก user.name เป็น user.profile.name และวิดเจ็ตล้มเหลวโดยไม่มีเสียง วิดเจ็ตไม่ใช่ปัญหา แต่นิสัยพึ่งพารายละเอียดที่ไม่เสถียรคือปัญหา

สองนิสัยช่วยป้องกันสิ่งนี้:

อันดับแรก ปฏิบัติโค้ดที่สร้างเป็น read-only และเก็บไฟล์แบบกำหนดเองแยกต่างหาก พร้อมขอบเขต import ที่ชัดเจน

อันดับสอง เก็บสัญญาคอมโพเนนต์ให้เล็กและชัด หากต้องวิวัฒนาการ ให้เพิ่ม prop เวอร์ชันง่าย ๆ (เช่น apiVersion) หรือรองรับทั้งรูปแบบ props เก่าและใหม่ในหนึ่งการปล่อย

เช็คลิสต์ด่วนก่อนส่งวิดเจ็ตแบบกำหนดเอง

ออกแบบ API วิดเจ็ตที่มั่นคง
กำหนดสัญญา props และ events ให้ชัดเจน เพื่อให้วิดเจ็ตคงตัวข้ามการสร้างใหม่
สร้างคอมโพเนนต์

ก่อน merge วิดเจ็ตเฉพาะเข้ากับแอป Vue3 ที่ถูกสร้าง ให้เช็คสภาพจริงด่วน มันควรรอดการสร้างใหม่ครั้งถัดไปโดยไม่ต้องฮีโร่ และคนอื่นควรนำกลับมาใช้ได้

  • ทดสอบการสร้างใหม่: รันการสร้างใหม่และสร้างซ้ำ หากคุณต้องแก้ไฟล์ที่ถูกสร้าง boundary ผิด
  • อินพุตและเอาต์พุตชัดเจน: props เข้า, emits ออก หลีกเลี่ยงการพึ่งพาวัตถุลับเช่น DOM ภายนอกหรือสตอร์หน้าจอเฉพาะ
  • ควบคุมสไตล์: scope สไตล์และใช้คำนำคลาสชัดเจน (เช่น timeline-)
  • สถานะทั้งหมดดูดี: loading, error, และ empty states ควรมีและสมเหตุสมผล
  • นำกลับมาใช้โดยไม่ต้องคลอน: ยืนยันว่าคุณสามารถวางบนหน้าที่สองได้ด้วยการเปลี่ยน props และ handler ไม่ใช่การก็อปภายใน

วิธีเช็คง่าย: ลองวางวิดเจ็ตบนหน้าผู้ดูแลระบบแล้วบนพอร์ทัลลูกค้า ถ้าทั้งคู่ทำงานด้วยการเปลี่ยน props และการจัดการ events เท่านั้น คุณอยู่ในพื้นที่ปลอดภัย

ตัวอย่างที่เป็นจริง: เพิ่มวิดเจ็ตไทม์ไลน์ลงแดชบอร์ด

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

แนวทางปลอดภัยคือเก็บวิดเจ็ตไว้แยกจาก UI ที่สร้างและวางลงในหน้าผ่าน wrapper บาง ๆ

สัญญาของวิดเจ็ต

ทำให้เรียบและคาดเดาได้ เช่น wrapper ส่ง:

  • ticketId (string)
  • range (7 วันล่าสุด, 30 วันล่าสุด, แบบกำหนดเอง)
  • mode (compact vs detailed)

วิดเจ็ต emit:

  • select เมื่อผู้ใช้คลิกเหตุการณ์
  • changeFilters เมื่อผู้ใช้ปรับ range หรือ mode

ตอนนี้วิดเจ็ตไม่รู้เรื่อง dashboard, โมเดลข้อมูล หรือการร้องขออย่างละเอียด มันเรนเดอร์ไทม์ไลน์และรายงานการกระทำผู้ใช้

Wrapper เชื่อมต่อกับหน้าอย่างไร

Wrapper นั่งข้าง ๆ dashboard และแปลงข้อมูลหน้ามาเป็นสัญญา มันอ่าน ticket ID ปัจจุบันจาก state ของหน้า แปลงฟิลเตอร์ UI เป็น range และแมประเบียน backend เป็นรูปเหตุการณ์ที่วิดเจ็ตต้องการ

เมื่อวิดเจ็ต emit select wrapper อาจเปิดพาแนลรายละเอียดหรือเรียกการกระทำของหน้า เมื่อตัวมัน emit changeFilters wrapper จะอัปเดตฟิลเตอร์ของหน้าและรีเฟรชข้อมูล

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

วิธีทดสอบและแนวปฏิบัติการปล่อยที่ป้องกันความประหลาดใจ

เก็บกฎไว้ในกระบวนการ
ใช้กระบวนการธุรกิจแบบวิชวลสำหรับกฎ แล้วเก็บคอมโพเนนต์ให้เป็น dumb และนำกลับมาใช้ใหม่ได้
อัตโนมัติกระบวนการ

คอมโพเนนต์แบบกำหนดเองมักพังด้วยสาเหตุที่น่าเบื่อ: รูป prop เปลี่ยน, event หยุดยิง, หรือหน้าที่สร้างเรียกเรนเดอร์บ่อยกว่าที่วิดเจ็ตคาด เล็กน้อยของนิสัยจับปัญหาได้เร็ว

การทดสอบท้องถิ่น: หาเบรกของขอบเขตแต่เนิ่นๆ

ปฏิบัติต่อขอบระหว่าง UI ที่ถูกสร้างกับวิดเจ็ตเหมือน API ทดสอบวิดเจ็ตโดยไม่มีแอปเต็มรูปแบบก่อน ใช้ props กำหนดค่าที่ตรงตามสัญญา

เรนเดอร์ด้วย props แบบ "เส้นทางสุขสบาย" และกับค่าส่งไม่ครบ จำลองเหตุการณ์สำคัญ (save, cancel, select) และยืนยันว่าพาเรนท์รับมือได้ ทดสอบข้อมูลช้าและหน้าจอเล็ก ยืนยันว่ามันไม่เขียนสถานะทั่วโลกเว้นแต่นั่นเป็นส่วนของสัญญา

ถ้าคุณสร้างบนแอป Vue3 ของ AppMaster ให้รันเช็กเหล่านี้ก่อนจะสร้างอะไรใหม่ มันง่ายกว่าที่จะแยกปัญหาเมื่อคุณยังไม่ได้เปลี่ยนสองอย่างพร้อมกัน

การถอยหลังหลังการสร้างใหม่: ตรวจอะไรเป็นอันดับแรก

หลังการสร้างใหม่ ให้เช็คจุดสัมผัส: props เดิมยังถูกส่งหรือไม่ และ events เดิมยังถูกจับหรือไม่ นั่นคือที่ที่ความเสียหายมักแสดงก่อน

เก็บการรวมแบบคงที่ หลีกเลี่ยงการ import เปราะบางที่พึ่งพาเส้นทางไฟล์ที่อาจย้าย ใช้ entry point ที่เสถียรสำหรับคอมโพเนนต์แบบกำหนดเอง

สำหรับ production เพิ่ม logging เบาๆ และจับข้อผิดพลาดภายในวิดเจ็ต:

  • ขณะ mounted พร้อม props หลัก (sanitize)
  • การละเมิดสัญญา (prop required หายหรือชนิดผิด)
  • การเรียก API ล้มเหลวพร้อมรหัสข้อผิดพลาดสั้นๆ
  • สถานะว่างที่ไม่คาดคิด

เมื่อบางอย่างพัง คุณจะตอบได้เร็วว่าการสร้างใหม่เปลี่ยนอินพุต หรือว่าวิดเจ็ตเปลี่ยน

ขั้นตอนถัดไป: ทำให้รูปแบบนี้ใช้ซ้ำได้ทั่วแอปของคุณ

เมื่อวิดเจ็ตแรกใช้งานได้ ผลประโยชน์จริงคือทำให้มันทำซ้ำได้ เพื่อวิดเจ็ตถัดไปจะไม่ใช่แฮ็กชั่วคราว

สร้างมาตรฐานภายในเล็ก ๆ สำหรับสัญญาวิดเจ็ตและจดไว้ที่ที่ทีมเก็บบันทึกแอป ทำให้เรียบ: การตั้งชื่อ props ที่จำเป็น vs ตัวเลือก ชุด event เล็ก ๆ พฤติกรรมข้อผิดพลาด และความเป็นเจ้าของชัดเจน (อะไรอยู่ใน UI ที่สร้าง vs โฟลเดอร์ custom ของคุณ)

ยังเขียนกฎขอบเขตด้วยภาษาง่าย ๆ: อย่าแก้ไฟล์ที่ถูกสร้าง เก็บโค้ดแบบกำหนดเองแยก และส่งข้อมูลผ่าน props และ events เท่านั้น มันป้องกัน "แก้ด่วน" ที่กลายเป็นภาษีการดูแลระยะยาว

ก่อนสร้างวิดเจ็ตที่สอง ให้รันการทดลองสร้างใหม่เล็ก ๆ ส่งวิดเจ็ตแรก แล้วสร้างใหม่อย่างน้อยสองครั้งในช่วงการเปลี่ยนปกติ (เช่นเปลี่ยนฉลาก เปลี่ยนเลย์เอาต์ เพิ่มฟิลด์) และยืนยันว่าไม่มีอะไรพัง

ถ้าคุณใช้ AppMaster มักจะทำงานได้ดีที่สุดเมื่อเก็บ UI และลอจิกส่วนใหญ่ไว้ในตัวแก้แบบวิชวล (UI builders, Business Process Editor, Data Designer) ให้คอมโพเนนต์ Vue แบบกำหนดเองสำหรับวิดเจ็ตที่ visual editors ไม่สามารถแสดงผลได้ เช่นไทม์ไลน์เฉพาะ ชาร์ตปฏิสัมพันธ์ หรือคอนโทรลอินพุตที่ไม่ธรรมดา หากต้องการจุดเริ่มต้นที่สะอาด AppMaster บน appmaster.io ถูกออกแบบรอบการสร้างใหม่ ดังนั้นการแยกวิดเจ็ตแบบกำหนดเองจะกลายเป็นส่วนหนึ่งของเวิร์กโฟลว์โดยธรรมชาติ

คำถามที่พบบ่อย

ทำไมการเปลี่ยนแปลง UI ของฉันถึงหายไปหลังจากสร้างแอปใหม่?

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

ฉันจะปรับแต่ง UI ที่ถูกสร้างโดยไม่เสียงานเมื่อมีการสร้างใหม่ได้อย่างไร?

เก็บโค้ด Vue ที่เขียนด้วยมือทั้งหมดไว้ในโฟลเดอร์ที่คุณเป็นเจ้าของ (เช่น custom หรือ extensions) แล้วนำเข้าเป็น dependency ปฏิบัติต่อหน้าจอที่ถูกสร้างเป็นผลลัพธ์แบบอ่านอย่างเดียว และเชื่อมต่อกับคอมโพเนนต์ของคุณผ่านอินเทอร์เฟซขนาดเล็กและมั่นคง

Wrapper component คืออะไรและช่วยกับหน้าที่ถูกสร้างอย่างไร?

Wrapper คือคอมโพเนนต์บางๆ ที่คุณเป็นเจ้าของ วางอยู่ระหว่างหน้าที่สร้างกับวิดเจ็ตของคุณ มันแปลงรูปข้อมูลของหน้าเป็น props ที่สะอาดและแปลง events ของวิดเจ็ตให้เป็นการกระทำของหน้า ดังนั้นหากข้อมูลที่สร้างเปลี่ยนในภายหลัง คุณมักจะอัปเดตเฉพาะ wrapper เท่านั้น

วิธีที่ปลอดภัยที่สุดในการออกแบบ props และ events สำหรับวิดเจ็ตที่นำกลับมาใช้ได้คืออะไร?

รักษาสัญญาให้เล็ก: props ไม่กี่ตัวสำหรับข้อมูลที่วิดเจ็ตต้องการ และ events ไม่กี่แบบเพื่อรายงานเจตนาผู้ใช้ เลือกค่าที่เรียบง่ายและวัตถุทั่วไปที่คุณควบคุม เพิ่มค่าเริ่มต้น ตรวจสอบค่าเข้า และล้มเหลวอย่างนุ่มนวลด้วยสถานะว่างแทนการขว้างข้อผิดพลาด

เมื่อใดควรปล่อย `update:modelValue` แทน `change` จากคอมโพเนนต์แบบกำหนดเอง?

update:modelValue เหมาะเมื่อวิดเจ็ตทำหน้าที่เหมือนคอนโทรลฟอร์มและควรสนับสนุน v-model ส่วน change เหมาะกับการเปลี่ยนแปลงที่ผู้ใช้ยืนยันแล้ว เช่นเมื่อคลิกบันทึกหรือเสร็จการเลือก เพื่อที่พาเรนท์จะไม่ต้องประมวลผลทุกการพิมพ์

ฉันจะป้องกันไม่ให้ CSS ของวิดเจ็ตทำให้หน้าที่สร้างอื่นพังได้อย่างไร?

แยกสไตล์ของวิดเจ็ตให้ชัดและใช้คำนำคลาสที่ชัดเจนเพื่อไม่ให้หน้าที่สร้างใหม่ไปเขียนทับ CSS ของคุณ หากต้องการให้วิดเจ็ตเข้ากับธีมแอป ให้ส่งโทเค็นธีมเป็น props (สี ระยะห่าง ขนาดตัวอักษร) แทนการนำเข้า style ของหน้า

ถ้าฉันเพิ่ม UI แบบกำหนดเอง กฎทางธุรกิจควรอยู่ที่ไหน?

โดยทั่วไปให้เก็บกฎทางธุรกิจนอกวิดเจ็ต ปล่อยให้หน้า (page) หรือ backend ตัดสินสิทธิ์ กฎการตรวจสอบ และพฤติกรรมการบันทึก ในขณะที่วิดเจ็ตโฟกัสที่การเรนเดอร์และการโต้ตอบ แล้วปล่อย events เช่น select, retry, หรือ approve

สาเหตุที่พบบ่อยที่สุดที่คอมโพเนนต์แบบกำหนดเองพังหลังการสร้างใหม่คืออะไร?

อย่าพึ่งพารายละเอียดที่ไม่เสถียรอย่างเส้นทางไฟล์ที่ถูกสร้าง โครงสร้าง DOM ของพาเรนท์ หรือรูปแบบวัตถุสถานะภายใน หากต้องการใช้อะไรที่เสี่ยง ให้ซ่อนมันไว้ใน wrapper ดังนั้นการเปลี่ยนชื่อเช่น user.name เป็น user.profile.name จะไม่บังคับให้คุณเขียนวิดเจ็ตใหม่ทั้งหมด

ฉันควรทดสอบอะไรบ้างก่อนและหลังการสร้างใหม่เพื่อจับปัญหาเร็ว?

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

เมื่อไหร่จึงคุ้มค่าที่จะสร้างวิดเจ็ต Vue เฉพาะ แทนการใช้บล็อก UI ที่มีอยู่?

ไม่ใช่ทุก UI ต้องมีโค้ดแบบกำหนดเอง ให้ใช้คอมโพเนนต์แบบกำหนดเองเมื่อ visual builders ทำไม่ได้ เช่นชาร์ตซับซ้อน ตัวเลือกแผนที่ แผงลายเซ็น หรือตัวจัดแผนแบบลากแล้ววาง หากความต้องการสามารถตรงกับการปรับ UI ที่สร้างได้ จะดูแลรักษาง่ายกว่าในระยะยาว

ง่ายต่อการเริ่มต้น
สร้างบางสิ่งที่ น่าทึ่ง

ทดลองกับ AppMaster ด้วยแผนฟรี
เมื่อคุณพร้อม คุณสามารถเลือกการสมัครที่เหมาะสมได้

เริ่ม