เราสร้างส่วนประกอบ UI ใน Rails ได้อย่างไร

เผยแพร่แล้ว: 2024-06-28

การรักษาความสอดคล้องของภาพในเว็บแอปพลิเคชันขนาดใหญ่เป็นปัญหาร่วมกันในหลายๆ องค์กร เว็บแอปพลิเคชันหลักที่อยู่เบื้องหลังผลิตภัณฑ์ Flywheel ของเราสร้างขึ้นด้วย Ruby on Rails และเรามีนักพัฒนา Rails หลายคนและนักพัฒนาส่วนหน้าสามคนที่เขียนโค้ดในแต่ละวัน เราให้ความสำคัญกับการออกแบบเช่นกัน (ซึ่งเป็นหนึ่งในค่านิยมหลักของเราในฐานะบริษัท) และมีนักออกแบบสามคนที่ทำงานอย่างใกล้ชิดกับนักพัฒนาในทีม Scrum ของเรา

คนสองคนร่วมมือกันในการออกแบบเว็บไซต์

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

เราได้ผ่านการทำซ้ำคำแนะนำสไตล์และวิธีการสร้าง/บำรุงรักษารูปแบบ UI และส่วนประกอบต่างๆ และการวนซ้ำแต่ละครั้งช่วยแก้ปัญหาที่เราเผชิญอยู่ในขณะนั้น เรามั่นใจว่าแนวทางใหม่ของเราจะเตรียมเราให้พร้อมไปอีกนาน หากคุณประสบปัญหาที่คล้ายกันในแอปพลิเคชัน Rails ของคุณและต้องการเข้าถึงส่วนประกอบต่างๆ จากฝั่งเซิร์ฟเวอร์ ฉันหวังว่าบทความนี้จะให้แนวคิดแก่คุณได้

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

ในบทความนี้ ฉันจะเจาะลึกเกี่ยวกับ:

  • เรากำลังแก้ไขเพื่ออะไร
  • การจำกัดส่วนประกอบ
  • การแสดงผลส่วนประกอบทางฝั่งเซิร์ฟเวอร์
  • โดยที่เราไม่สามารถใช้ส่วนประกอบฝั่งเซิร์ฟเวอร์ได้

เรากำลังแก้ไขเพื่ออะไร

เราต้องการจำกัดองค์ประกอบ UI ของเราอย่างสมบูรณ์ และลดความเป็นไปได้ที่ UI เดียวกันจะถูกสร้างขึ้นมากกว่าหนึ่งวิธี แม้ว่าลูกค้าอาจไม่สามารถบอกได้ (ในตอนแรก) การไม่มีข้อจำกัดในส่วนประกอบทำให้เกิดประสบการณ์ที่สับสนของนักพัฒนา ทำให้สิ่งต่าง ๆ ยากมากที่จะรักษา และทำให้ยากต่อการเปลี่ยนแปลงการออกแบบทั่วโลก

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

หน้าคำแนะนำสไตล์สำหรับส่วนประกอบไม้ระแนง

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

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

ตัวอย่างส่วนประกอบที่ไม่มีข้อจำกัด

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

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

 .card__ส่วนหัว
  .card__header-ซ้าย
    %h2 การสำรองข้อมูล
  .card__header-ขวา
    = link_to "#" ทำ
      = ไอคอน ("plus_small")

หลังจากที่เขียนโค้ดแล้ว ลองจินตนาการถึงนักออกแบบที่ต้องการเพิ่มไอคอนทางด้านซ้ายของชื่อ เมื่อแกะกล่องแล้ว จะไม่มีระยะขอบระหว่างไอคอนและชื่อเรื่อง

 -
  .card__header-ซ้าย
    = ไอคอน ("arrow_backup", สี: "gray25")
    %h2 การสำรองข้อมูล
-

ตามหลักการแล้ว เราจะแก้ปัญหานั้นใน CSS สำหรับส่วนหัวของการ์ด แต่สำหรับตัวอย่างนี้ สมมติว่านักพัฒนาคนอื่นคิดว่า "โอ้ ฉันรู้! เรามีตัวช่วยมาร์จิ้น ฉันจะตบคลาสผู้ช่วยตามชื่อ”

 -
  .card__header-ซ้าย
    = ไอคอน ("arrow_backup", สี: "gray25")
    %h2.--ml-10 การสำรองข้อมูล
-

ในทางเทคนิค แล้วดูเหมือนว่าการเยาะเย้ยทำใช่ไหม! แน่นอน แต่สมมุติว่าหนึ่งเดือนต่อมา นักพัฒนา รายอื่น ต้องการส่วนหัวของการ์ด แต่ไม่มีไอคอน พวกเขาค้นหาตัวอย่างสุดท้าย คัดลอก/วาง และลบไอคอนออก

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

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

นักพัฒนารายอื่นอาจพยายามใช้โค้ดนั้นซ้ำ แต่ในกรณีนี้ พวกเขาจำเป็นต้องมีเส้นขอบจริงๆ สมมติว่าพวกเขาเพิกเฉยต่อการใช้งานที่เหมาะสมที่บันทึกไว้ในคู่มือสไตล์ และไม่ทราบว่าการลบคลาสไร้ขอบจะทำให้พวกเขามีขอบเขต แต่จะเพิ่มกฎแนวนอนแทน ในที่สุดก็มีช่องว่างภายในเพิ่มเติมระหว่างชื่อเรื่องและเส้นขอบ ดังนั้นพวกเขาจึงใช้คลาสตัวช่วยกับ hr และ voila!

ด้วยการปรับเปลี่ยนส่วนหัวของการ์ดแบบเดิมทั้งหมด ตอนนี้เรามีปัญหาเรื่องโค้ด

 .card__header.--ไร้ขอบ
  .card__header-ซ้าย
    %h2.--ml-10 การสำรองข้อมูล
  .card__header-ขวา
    = link_to "#" ทำ
      = ไอคอน ("plus_small")
  %ชม.--mt-0.--mb-0

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


ส่วนประกอบที่จำกัด

คุณอาจคิดว่าปัญหาที่ระบุไว้ข้างต้นได้รับการแก้ไขแล้วด้วยส่วนประกอบต่างๆ อย่างชัดเจน นั่นเป็นสมมติฐานที่ถูกต้อง! เฟรมเวิร์กส่วนหน้าเช่น React และ Vue ได้รับความนิยมอย่างมากสำหรับจุดประสงค์นี้ มันเป็นเครื่องมือที่น่าทึ่งสำหรับการห่อหุ้ม UI อย่างไรก็ตาม มีปัญหาอย่างหนึ่งที่เราไม่ชอบเสมอไป เนื่องจากพวกเขาต้องการให้ JavaScript แสดงผล UI ของคุณ

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

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

  • ไม่มีวิธีที่ผิดในการรวบรวมส่วนประกอบเข้าด้วยกัน
  • ส่วนประกอบจะเป็นผู้คิดการออกแบบทั้งหมดให้กับคุณ (คุณเพียงแค่ผ่านตัวเลือก!)
  • ไวยากรณ์สำหรับการสร้างส่วนประกอบมีความสอดคล้องและง่ายต่อการให้เหตุผล
  • หากจำเป็นต้องเปลี่ยนแปลงการออกแบบในส่วนประกอบ เราสามารถเปลี่ยนได้ครั้งเดียวในส่วนประกอบและมั่นใจได้ว่าได้รับการอัปเดตทุกที่

การแสดงผลส่วนประกอบทางฝั่งเซิร์ฟเวอร์

แล้วเรากำลังพูดถึงอะไรโดยการจำกัดส่วนประกอบ? มาเจาะลึกกันดีกว่า!

ตามที่กล่าวไว้ข้างต้น เราต้องการให้นักพัฒนาที่ทำงานในแอปพลิเคชันสามารถดูการจำลองการออกแบบของหน้าและสามารถสร้างหน้านั้นได้ทันทีโดยไม่มีอุปสรรค นั่นหมายความว่าวิธีการสร้าง UI จะต้อง A) ได้รับการจัดทำเป็นเอกสารไว้เป็นอย่างดี และ B) มีความชัดเจนและไม่มีการคาดเดา

บางส่วนเพื่อช่วยเหลือ (หรืออย่างที่เราคิด)

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

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

ความรู้เบื้องต้นเกี่ยวกับเซลล์

โชคดีที่มีทางเลือกอื่นที่ดีกว่าสำหรับ Partials ซึ่งช่วยให้เราใช้โค้ดซ้ำ และ เก็บตรรกะไว้ไม่ให้มองข้าม มันถูกเรียกว่า Cells ซึ่งเป็นอัญมณี Ruby ที่พัฒนาโดย Trailblazer เซลล์มีมานานแล้วก่อนที่เฟรมเวิร์กส่วนหน้าเช่น React และ Vue จะได้รับความนิยมเพิ่มขึ้น และเซลล์เหล่านี้ช่วยให้คุณสามารถเขียนโมเดลมุมมองแบบห่อหุ้มที่จัดการทั้งตรรกะ และ เทมเพลตได้ พวกเขาให้มุมมองที่เป็นนามธรรมซึ่ง Rails ไม่ได้มีไว้นอกกรอบจริงๆ จริงๆ แล้ว เราใช้ Cells ในแอป Flywheel มาระยะหนึ่งแล้ว เพียงแต่ไม่ใช่ในระดับสากลที่สามารถนำกลับมาใช้ใหม่ได้เป็นพิเศษ

ในระดับที่ง่ายที่สุด Cells ช่วยให้เราสามารถสรุปมาร์กอัปบางส่วนได้เช่นนี้ (เราใช้ Haml สำหรับภาษาเทมเพลตของเรา):

 %div
  %h1 สวัสดีชาวโลก!

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

 = เซลล์("hello_world")

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

การสร้างเซลล์

เราใส่ UI Cells ทั้งหมดของเราไว้ในไดเร็กทอรี app/cells/ui แต่ละเซลล์จะต้องมีไฟล์ Ruby เพียงไฟล์เดียว ซึ่งต่อท้ายด้วย _cell.rb ในทางเทคนิคแล้ว คุณสามารถเขียนเทมเพลตใน Ruby ด้วยตัวช่วย content_tag ได้ แต่เซลล์ส่วนใหญ่ของเรายังมีเทมเพลต Haml ที่เกี่ยวข้องซึ่งอยู่ในโฟลเดอร์ที่ตั้งชื่อตามส่วนประกอบ

เซลล์พื้นฐานขั้นสูงที่ไม่มีตรรกะจะมีลักษณะดังนี้:

 // เซลล์/ui/slat_cell.rb
UI ของโมดูล
  คลาส SlatCell < ViewModel
    แน่นอนแสดง
    จบ
  จบ
จบ

วิธีการแสดงคือสิ่งที่แสดงผลเมื่อคุณสร้างอินสแตนซ์ของเซลล์ และจะค้นหาไฟล์ show.haml ที่เกี่ยวข้องในโฟลเดอร์ที่มีชื่อเดียวกันกับเซลล์โดยอัตโนมัติ ในกรณีนี้คือ app/cells/ui/slat (เรากำหนดขอบเขต UI Cells ทั้งหมดของเราเป็นโมดูล UI)

ในเทมเพลต คุณสามารถเข้าถึงตัวเลือกที่ส่งผ่านไปยังเซลล์ได้ ตัวอย่างเช่น หากเซลล์ถูกสร้างอินสแตนซ์ในมุมมอง = cell("ui/slat", title: "Title", subtitle: "Subtitle", label: "Label") เราสามารถเข้าถึงตัวเลือกเหล่านั้นผ่านออบเจ็กต์ตัวเลือก

 // เซลล์/ui/slat/show.haml
.ไม้ระแนง
  .slat__inner
    .slat__เนื้อหา
      %h4= ตัวเลือก[:หัวข้อ]
      %p= ตัวเลือก[:คำบรรยาย]
      = ไอคอน(ตัวเลือก[:ไอคอน], สี: "สีน้ำเงิน")

หลายครั้งเราจะย้ายองค์ประกอบแบบง่ายและค่าขององค์ประกอบเหล่านั้นไปไว้ในวิธีการในเซลล์ เพื่อป้องกันไม่ให้องค์ประกอบว่างถูกเรนเดอร์หากไม่มีตัวเลือก

 // เซลล์/ui/slat_cell.rb
ชื่อแน่นอน
  กลับยกเว้นตัวเลือก [:title]
  content_tag :h4, ตัวเลือก[:ชื่อ]
จบ
คำบรรยายแน่นอน
  กลับยกเว้นตัวเลือก [: คำบรรยาย]
  content_tag :p, ตัวเลือก[:คำบรรยาย]
จบ
 // เซลล์/ui/slat/show.haml
.ไม้ระแนง
  .slat__inner
    .slat__เนื้อหา
      = ชื่อเรื่อง
      = คำบรรยาย

การรวมเซลล์ด้วยยูทิลิตี้ UI

หลังจากพิสูจน์แนวคิดที่ว่าสิ่งนี้สามารถทำงานได้ในวงกว้าง ฉันต้องการจัดการกับมาร์กอัปภายนอกที่จำเป็นในการเรียกเซลล์ มันไม่ค่อยลื่นไหลนักและยากที่จะจดจำ เราเลยจัดตัวช่วยเล็กๆ น้อยๆ มาให้! ตอนนี้เราสามารถโทร = ui “name_of_component” และส่งผ่านตัวเลือกแบบอินไลน์ได้

 = ui "slat", ชื่อเรื่อง: "ชื่อเรื่อง", คำบรรยาย: "คำบรรยาย", ป้ายกำกับ: "ป้ายกำกับ"

การส่งผ่านตัวเลือกเป็นบล็อกแทนที่จะเป็นแบบอินไลน์

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

 = ui “slat”, หัวเรื่อง: “หัวเรื่อง”, คำบรรยาย: “คำบรรยาย”, ป้ายกำกับ: “ป้ายกำกับ”, ลิงก์: “#”, tertiary_title: “ตติยภูมิ”, ปิดการใช้งาน: จริง, รายการตรวจสอบ: [“รายการที่ 1”, “รายการ 2”, “รายการ 3”]

มันยุ่งยากมาก ซึ่งทำให้เราสร้างคลาสที่เรียกว่า OptionProxy ซึ่งจะดักจับเมธอด Cells setter และแปลเป็นค่าแฮช ซึ่งจากนั้นจะรวมเข้ากับตัวเลือกต่างๆ ถ้ามันฟังดูซับซ้อน ไม่ต้องกังวล มันก็ซับซ้อนสำหรับฉันเหมือนกัน นี่คือส่วนสำคัญของคลาส OptionProxy ที่ Adam หนึ่งในวิศวกรซอฟต์แวร์อาวุโสของเราเขียนไว้

นี่คือตัวอย่างการใช้คลาส OptionProxy ภายในเซลล์ของเรา:

 UI ของโมดูล
  คลาส SlatCell < ViewModel
    แน่นอนแสดง
      OptionProxy.new(self).yield!(ตัวเลือก, &บล็อก)
      ซุปเปอร์()
    จบ
  จบ
จบ

ในตอนนี้ เราสามารถเปลี่ยนตัวเลือกอินไลน์ที่ยุ่งยากของเราให้กลายเป็นบล็อกที่น่าพึงพอใจยิ่งขึ้นได้!

 = ui "slat" ทำ |slat|
  - slat.title = "ชื่อเรื่อง"
  - slat.subtitle = "คำบรรยาย"
  - slat.label = "ป้ายกำกับ"
  - slat.link = "#"
  - slat.tertiary_title = "ตติยภูมิ"
  - slat.disabled = จริง
  - slat.checklist = ["รายการที่ 1", "รายการที่ 2", "รายการที่ 3"]

ขอแนะนำลอจิก

จนถึงจุดนี้ ตัวอย่างยังไม่ได้รวมตรรกะใดๆ เกี่ยวกับสิ่งที่มุมมองแสดง นั่นเป็นหนึ่งในสิ่งที่ดีที่สุดที่ Cells นำเสนอ ดังนั้นเรามาพูดถึงมันกันดีกว่า!

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

วิธีการด้านล่างนี้จะเรียกตัวช่วย link_to หรือ content_tag ขึ้นอยู่กับตัวเลือก [:link]

 def คอนเทนเนอร์ (&บล็อก)
  แท็ก =
    ถ้าตัวเลือก[:ลิงค์]
      [:link_to, ตัวเลือก[:ลิงก์]]
    อื่น
      [:content_tag, :div]
    จบ
  send(*แท็ก, คลาส: “slat__inner”, &บล็อก)
สิ้นสุด

ซึ่งช่วยให้เราสามารถแทนที่องค์ประกอบ .slat__inner ในเทมเพลตด้วยบล็อกคอนเทนเนอร์:

 .ไม้ระแนง
  = คอนเทนเนอร์ทำ
  -

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

 = ui "slat" ทำ |slat|
  -
  - slat.disabled = จริง

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

 .slat { class: possible_classes("--disabled": options[:disabled]) }
  .slat__inner
    .slat__เนื้อหา
      %h4{ class: possible_classes("--alt": options[:disabled]) }= ตัวเลือก[:ชื่อ]
      %p{ คลาส: possible_classes("--alt": options[:disabled]) }=
      ตัวเลือก[:คำบรรยาย]
      = ไอคอน (ตัวเลือก [: ไอคอน], สี: "สีเทา")

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

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


โดยที่เราไม่สามารถใช้ส่วนประกอบฝั่งเซิร์ฟเวอร์ได้

แม้ว่าแนวทางเซลล์จะมีประโยชน์อย่างมากสำหรับการใช้งานเฉพาะของเราและวิธีการทำงานของเรา แต่ฉันก็ไม่กล้าที่จะบอกว่าวิธีนี้สามารถแก้ไขปัญหาของเราได้ 100% เรายังคงเขียน JavaScript (จำนวนมาก) และสร้างประสบการณ์บางอย่างใน Vue ทั่วทั้งแอปของเรา 75% ของเวลาทั้งหมด เทมเพลต Vue ของเรายังคงอยู่ใน Haml และเราเชื่อมโยงอินสแตนซ์ Vue ของเรากับองค์ประกอบที่มีอยู่ ซึ่งช่วยให้เรายังคงใช้ประโยชน์จากแนวทางเซลล์ได้

อย่างไรก็ตาม ในสถานที่ที่เหมาะสมกว่าที่จะจำกัดส่วนประกอบอย่างสมบูรณ์ให้เป็นอินสแตนซ์ Vue ไฟล์เดียว เราจะไม่สามารถใช้ Cells ได้ ตัวอย่างเช่น รายการที่เราเลือกคือ Vue ทั้งหมด แต่ฉันคิดว่าไม่เป็นไร! เราไม่พบความจำเป็นที่จะต้องมีส่วนประกอบเวอร์ชันที่ซ้ำกันทั้งในส่วนประกอบ Cells และ Vue ดังนั้นจึงเป็นเรื่องปกติที่ส่วนประกอบบางส่วนสร้างขึ้นด้วย Vue 100% และบางส่วนก็สร้างด้วย Cells

หากส่วนประกอบถูกสร้างขึ้นด้วย Vue หมายความว่า JavaScript จำเป็นต้องสร้างส่วนประกอบนั้นใน DOM และเราใช้ประโยชน์จากเฟรมเวิร์ก Vue เพื่อดำเนินการดังกล่าว สำหรับส่วนประกอบอื่นๆ ส่วนใหญ่ของเรา พวกมันไม่จำเป็นต้องใช้ JavaScript และหากจำเป็นต้องใช้ พวกมันต้องการให้สร้าง DOM ไว้แล้ว และเราเพียงแค่เชื่อมต่อและเพิ่ม Listener เหตุการณ์

ในขณะที่เราพัฒนาแนวทางเซลล์ไปเรื่อย ๆ เราจะทดลองการผสมผสานระหว่างส่วนประกอบของเซลล์และส่วนประกอบ Vue เพื่อให้เรามีวิธีเดียวในการสร้างและใช้ส่วนประกอบต่างๆ ฉันยังไม่รู้ว่ามันเป็นยังไง พอไปถึงแล้วเราจะข้ามสะพานนั้น!


บทสรุปของเรา

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

ทีมออกแบบของเรามั่นใจมากขึ้นกว่าที่เคยว่าส่วนประกอบและประสบการณ์ในแอปของเราเป็นแบบ 1:1 เมื่อเทียบกับสิ่งที่พวกเขาออกแบบใน Adobe XD ขณะนี้การเปลี่ยนแปลงหรือการเพิ่มเติมส่วนประกอบได้รับการจัดการผ่านการโต้ตอบกับนักออกแบบและนักพัฒนาส่วนหน้าเท่านั้น ซึ่งช่วยให้ทีมที่เหลือมีสมาธิและไม่ต้องกังวลในการรู้วิธีปรับแต่งส่วนประกอบให้ตรงกับการจำลองการออกแบบ

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


มาร่วมงานกับเรา!

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

พร้อมที่จะเข้าร่วมทีมของเราแล้วหรือยัง? เรากำลังจ้าง! สมัครที่นี่