ประโยชน์ของการใช้พร็อพเพอร์ตี้ที่กำหนดเองในระบบการออกแบบและไลบรารีคอมโพเนนต์
ผมชื่อ Dave เป็น Senior Front-End Developer ที่ Nordhealth ฉันทํางานด้านการออกแบบและพัฒนาระบบการออกแบบ Nord ซึ่งรวมถึงการสร้างคอมโพเนนต์เว็บสําหรับคลังคอมโพเนนต์ เราอยากแชร์วิธีแก้ปัญหาเกี่ยวกับการจัดสไตล์ Web Components โดยใช้พร็อพเพอร์ตี้ที่กำหนดเองของ CSS และประโยชน์อื่นๆ ของการใช้พร็อพเพอร์ตี้ที่กำหนดเองในระบบการออกแบบและไลบรารีคอมโพเนนต์
วิธีสร้างคอมโพเนนต์เว็บ
เราใช้ Lit ซึ่งเป็นไลบรารีที่มีโค้ดทั่วไปจำนวนมาก เช่น สถานะ สไตล์ที่มีขอบเขต เทมเพลต และอื่นๆ เพื่อสร้างคอมโพเนนต์เว็บ Lit ไม่เพียงใช้งานง่าย แต่ยังสร้างขึ้นบน JavaScript API แบบเนทีฟอีกด้วย ซึ่งหมายความว่าเราสามารถนำส่งชุดโค้ดขนาดเล็กที่ใช้ประโยชน์จากฟีเจอร์ที่เบราว์เซอร์มีอยู่แล้ว
แต่สิ่งที่ดึงดูดใจที่สุดเกี่ยวกับ Web Components คือ Web Components ใช้งานได้กับเฟรมเวิร์ก JavaScript ที่มีอยู่เกือบทุกเฟรมเวิร์ก หรือแม้แต่ไม่มีเฟรมเวิร์กเลย เมื่อมีการอ้างอิงแพ็กเกจ JavaScript หลักในหน้า การใช้ Web Component จะคล้ายกับการใช้องค์ประกอบ HTML เดิมเป็นอย่างมาก สัญญาณที่บอกได้จริงๆ เพียงอย่างเดียวที่บอกว่าไม่ได้เป็นองค์ประกอบ HTML แต่เดิม คือเครื่องหมายขีดกลางที่สอดคล้องกันภายในแท็ก ซึ่งเป็นมาตรฐานในการบอกเบราว์เซอร์ว่านี่คือคอมโพเนนต์เว็บ
การห่อหุ้มสไตล์ Shadow DOM
ในทำนองเดียวกัน องค์ประกอบ HTML ที่มีอยู่แต่เดิมก็มี Shadow DOM เช่นเดียวกับคอมโพเนนต์ของเว็บ Shadow DOM เป็นต้นไม้ที่ซ่อนอยู่ของโหนดภายในองค์ประกอบ วิธีที่ดีที่สุดในการแสดงภาพข้อมูลนี้คือการเปิดเครื่องมือตรวจสอบเว็บและเปิดตัวเลือก "แสดงแผนผัง Shadow DOM" เมื่อเสร็จแล้ว ให้ลองดูองค์ประกอบอินพุตเดิมในเครื่องมือตรวจสอบ คุณจะเห็นตัวเลือกให้เปิดอินพุตดังกล่าวและดูองค์ประกอบทั้งหมดที่อยู่ในนั้น คุณยังลองใช้กับ Web Component ของเราได้ด้วย ลองตรวจสอบคอมโพเนนต์อินพุตที่กําหนดเองเพื่อดู Shadow DOM
ข้อดีอย่างหนึ่ง (หรือข้อเสีย ทั้งนี้ขึ้นอยู่กับมุมมองของคุณ) ของ Shadow DOM คือการห่อหุ้มสไตล์ หากคุณเขียน CSS ภายในคอมโพเนนต์เว็บ รูปแบบเหล่านั้นจะเปิดเผยออกมาไม่ได้และส่งผลต่อหน้าหลักหรือองค์ประกอบอื่นๆ ทั้งหมดอยู่ภายในคอมโพเนนต์เดียว นอกจากนี้ CSS ที่เขียนขึ้นสําหรับหน้าหลักหรือคอมโพเนนต์เว็บหลักจะไม่สามารถแทรกซึมเข้าไปในคอมโพเนนต์เว็บได้
การสรุปรูปแบบนี้มีประโยชน์ในไลบรารีคอมโพเนนต์ของเรา ทำให้เรารับประกันได้มากขึ้นว่าเมื่อมีคนใช้คอมโพเนนต์รายการใดรายการหนึ่งของเรา องค์ประกอบดังกล่าวจะมีลักษณะตามที่ตั้งใจไว้ ไม่ว่าจะมีการใช้สไตล์ใดก็ตามกับหน้าหลัก และเพื่อเป็นการตรวจสอบเพิ่มเติม เรายังเพิ่ม all: unset;
ลงในรูทหรือ "โฮสต์" ของคอมโพเนนต์เว็บทั้งหมดด้วย
แต่จะเกิดอะไรขึ้นหากผู้ใช้คอมโพเนนต์เว็บของคุณมีเหตุผลอันสมควรในการเปลี่ยนรูปแบบบางอย่าง อาจเป็นเพราะข้อความบางบรรทัดมีความคมชัดไม่เพียงพอตามบริบท หรือเส้นขอบต้องหนาขึ้น หากไม่มีสไตล์ใดเข้าสู่คอมโพเนนต์ได้ คุณจะทำอย่างไรเพื่อปลดล็อกตัวเลือกการจัดสไตล์เหล่านั้น
คุณสมบัติที่กำหนดเอง CSS จะช่วยแก้ปัญหานี้ได้
พร็อพเพอร์ตี้ CSS ที่กำหนดเอง
พร็อพเพอร์ตี้ที่กำหนดเองมีชื่อที่เหมาะเจาะมาก เนื่องจากเป็นพร็อพเพอร์ตี้ CSS ที่คุณตั้งชื่อเองได้ทั้งหมดและใช้ค่าใดก็ได้ที่ต้องการ ข้อกำหนดเพียงอย่างเดียวคือคุณต้องใส่ขีดกลาง 2 ตัวนำหน้า เมื่อประกาศพร็อพเพอร์ตี้ที่กำหนดเองแล้ว คุณจะใช้ค่าใน CSS ได้โดยใช้ฟังก์ชัน var()
เมื่อพูดถึงการรับค่า พร็อพเพอร์ตี้ที่กำหนดเองทั้งหมดจะรับค่ามา ซึ่งเป็นไปตามลักษณะการทำงานทั่วไปของพร็อพเพอร์ตี้และค่า CSS ปกติ พร็อพเพอร์ตี้ที่กำหนดเองใดๆ ที่ใช้กับองค์ประกอบระดับบนหรือตัวองค์ประกอบเองสามารถใช้เป็นค่าในพร็อพเพอร์ตี้อื่นได้ เราใช้ประโยชน์จากพร็อพเพอร์ตี้ที่กำหนดเองสำหรับโทเค็นการออกแบบของเราอย่างมากโดยการนำไปใช้กับองค์ประกอบรูทผ่านเฟรมเวิร์ก CSS ซึ่งหมายความว่าองค์ประกอบทั้งหมดในหน้าเว็บสามารถใช้ค่าโทเค็นเหล่านี้ได้ ไม่ว่าจะเป็นคอมโพเนนต์เว็บ คลาสตัวช่วย CSS หรือนักพัฒนาซอฟต์แวร์ที่ต้องการดึงค่าจากรายการโทเค็นของเรา
ความสามารถในการรับค่าพร็อพเพอร์ตี้ที่กำหนดเองด้วยการใช้ฟังก์ชัน var()
นี้เป็นวิธีที่เราเจาะผ่าน Shadow DOM ของคอมโพเนนต์เว็บ และช่วยให้นักพัฒนาซอฟต์แวร์ควบคุมรูปแบบคอมโพเนนต์ได้ละเอียดยิ่งขึ้น
คุณสมบัติที่กำหนดเองในคอมโพเนนต์เว็บ Nord
เมื่อใดก็ตามที่เรากำลังพัฒนาองค์ประกอบสำหรับระบบการออกแบบของเรา เราจะใช้แนวทางที่ไตร่ตรองใน CSS ของระบบ กล่าวคือเราจะเน้นการใช้โค้ดขนาดเล็กแต่ดูแลรักษาได้ง่าย โทเค็นการออกแบบที่เรามีจะกำหนดเป็นพร็อพเพอร์ตี้ที่กำหนดเองภายในเฟรมเวิร์ก CSS หลักของเราในองค์ประกอบรูท
จากนั้นระบบจะอ้างอิงค่าโทเค็นเหล่านี้ภายในคอมโพเนนต์ ในบางกรณี เราจะใช้มูลค่าในพร็อพเพอร์ตี้ CSS โดยตรง แต่สำหรับกรณีอื่นๆ เราจะกำหนดพร็อพเพอร์ตี้ที่กำหนดเองตามบริบทใหม่ และใช้ค่ากับพร็อพเพอร์ตี้นั้น
นอกจากนี้ เราจะแยกค่าบางอย่างที่เจาะจงสำหรับคอมโพเนนต์แต่ไม่ได้อยู่ในโทเค็นของเรา และเปลี่ยนให้เป็นพร็อพเพอร์ตี้ที่กำหนดเองตามบริบท คุณสมบัติที่กำหนดเองซึ่งบริบทของคอมโพเนนต์ให้ประโยชน์หลักๆ 2 ประการดังนี้ ประการแรกหมายความว่า CSS ของเราอาจ "ซับซ้อน" มากยิ่งขึ้น เนื่องจากค่าดังกล่าวสามารถนำไปใช้กับพร็อพเพอร์ตี้หลายรายการภายในคอมโพเนนต์
ประการที่ 2 การเปลี่ยนแปลงสถานะคอมโพเนนต์และรูปแบบนั้นชัดเจนมาก กล่าวคือ ต้องเปลี่ยนแปลงพร็อพเพอร์ตี้ที่กำหนดเองทั้งหมดเพื่ออัปเดตพร็อพเพอร์ตี้เหล่านั้นทั้งหมดเมื่อคุณจัดรูปแบบสถานะโฮเวอร์หรือสถานะแอ็กทีฟ หรือในกรณีนี้คืออีกรูปแบบหนึ่ง
แต่ประโยชน์ที่มีประสิทธิภาพมากที่สุดคือเมื่อเรากําหนดพร็อพเพอร์ตี้ที่กําหนดเองตามบริบทเหล่านี้ในคอมโพเนนต์ เราจะสร้าง CSS API ที่กําหนดเองสําหรับคอมโพเนนต์แต่ละรายการ ซึ่งผู้ใช้คอมโพเนนต์นั้นสามารถเข้าถึงได้
ตัวอย่างก่อนหน้านี้แสดงหนึ่งในคอมโพเนนต์ของเว็บที่มีพร็อพเพอร์ตี้ที่กำหนดเองตามบริบทที่เปลี่ยนแปลงผ่านตัวเลือก ผลลัพธ์ของแนวทางทั้งหมดนี้คือคอมโพเนนต์ที่ให้ความยืดหยุ่นในการจัดสไตล์แก่ผู้ใช้มากพอ ในขณะที่ยังคงควบคุมสไตล์จริงส่วนใหญ่ไว้ นอกจากนี้ เราในฐานะนักพัฒนาคอมโพเนนต์ยังมีความสามารถพิเศษในการขัดจังหวะสไตล์เหล่านั้นที่ผู้ใช้นำมาใช้ หากเราต้องการปรับหรือขยายหนึ่งในพร็อพเพอร์ตี้เหล่านั้น เราก็สามารถทำได้โดยที่ผู้ใช้ไม่จำเป็นต้องเปลี่ยนแปลงโค้ดใดๆ ของพวกเขา
เราพบว่าวิธีการนี้มีประสิทธิภาพอย่างยิ่ง ไม่เพียงแต่สำหรับเราในฐานะผู้สร้างองค์ประกอบระบบการออกแบบของเราเท่านั้น แต่ยังรวมถึงทีมพัฒนาเมื่อใช้องค์ประกอบเหล่านี้ในผลิตภัณฑ์ของเราด้วย
พัฒนาพร็อพเพอร์ตี้ที่กำหนดเองให้ก้าวไปอีกขั้น
ขณะเขียนบทความนี้ เรายังไม่ได้เปิดเผยพร็อพเพอร์ตี้ที่กำหนดเองตามบริบทเหล่านี้ในเอกสารประกอบ แต่เรามีแผนที่จะเปิดเผยเพื่อให้ทีมพัฒนาซอฟต์แวร์ส่วนกลางเข้าใจและใช้ประโยชน์จากพร็อพเพอร์ตี้เหล่านี้ได้ คอมโพเนนต์ของเราเป็นแพ็กเกจใน npm ด้วยไฟล์ Manifest ซึ่งมีข้อมูลทุกอย่างที่ควรทราบ จากนั้นเราจะใช้ไฟล์ Manifest เป็นข้อมูลเมื่อมีการทำให้เว็บไซต์เอกสารประกอบของเราใช้งานได้ ซึ่งดำเนินการโดยใช้ Eleventy และฟีเจอร์ข้อมูลทั่วโลก เราวางแผนที่จะรวมพร็อพเพอร์ตี้ที่กำหนดเองตามบริบทเหล่านี้ไว้ในไฟล์ข้อมูลไฟล์ Manifest นี้
อีกเรื่องหนึ่งที่เราต้องการปรับปรุงคือวิธีที่คุณสมบัติที่กำหนดเองตามบริบทเหล่านี้จะรับค่าค่าต่างๆ ตัวอย่างเช่น ในปัจจุบัน หากคุณต้องการปรับสีของคอมโพเนนต์เส้นแบ่ง 2 ส่วน คุณจะต้องกำหนดเป้าหมายคอมโพเนนต์ทั้ง 2 ส่วนนี้ด้วยตัวเลือกโดยเฉพาะ หรือใช้คุณสมบัติที่กำหนดเองในองค์ประกอบโดยตรงด้วยแอตทริบิวต์รูปแบบ การดำเนินการนี้อาจดูไม่มีปัญหา แต่นักพัฒนาซอฟต์แวร์จะกำหนดสไตล์เหล่านั้นในองค์ประกอบที่บรรจุหรือแม้แต่ที่ระดับรูทได้จะมีประโยชน์มากกว่า
สาเหตุที่คุณต้องตั้งค่าพร็อพเพอร์ตี้ที่กำหนดเองในคอมโพเนนต์โดยตรงเนื่องจากเรากําหนดค่าในองค์ประกอบเดียวกันผ่านตัวเลือกโฮสต์คอมโพเนนต์ โทเค็นการออกแบบส่วนกลางที่เราใช้ในคอมโพเนนต์โดยตรงจะผ่านเข้ามาโดยไม่ได้รับผลกระทบจากปัญหานี้ และอาจถูกดักจับบนองค์ประกอบหลักได้ เราจะทำอย่างไรให้ได้ผลลัพธ์ที่ดีที่สุด
พร็อพเพอร์ตี้ที่กำหนดเองและแบบสาธารณะ
พร็อพเพอร์ตี้ที่กำหนดเองแบบส่วนตัวคือสิ่งที่ Lea Verou รวมเข้าด้วยกัน ซึ่งเป็นพร็อพเพอร์ตี้ที่กำหนดเอง "ส่วนตัว" ตามบริบทในคอมโพเนนต์นั้นๆ แต่ตั้งค่าเป็นพร็อพเพอร์ตี้ที่กำหนดเอง "สาธารณะ" โดยมีการสำรอง
การกําหนดพร็อพเพอร์ตี้ที่กําหนดเองตามบริบทในลักษณะนี้หมายความว่าเรายังคงทําสิ่งต่างๆ ทั้งหมดที่เคยทําได้ เช่น รับค่าโทเค็นส่วนกลางและนําค่ามาใช้ซ้ำในโค้ดคอมโพเนนต์ แต่คอมโพเนนต์จะรับค่าคําจํากัดความใหม่ของพร็อพเพอร์ตี้นั้นในตัวเองหรือองค์ประกอบหลักอย่างราบรื่นด้วย
แม้อาจมีการโต้แย้งว่าวิธีการนี้ไม่ใช่ "ความเป็นส่วนตัว" อย่างแท้จริง แต่เรายังคงคิดว่าวิธีนี้เป็นวิธีแก้ปัญหาที่ค่อนข้างสวยงามและเป็นวิธีแก้ปัญหาที่เรากังวล เมื่อมีโอกาส เราจะจัดการเรื่องนี้ในคอมโพเนนต์เพื่อให้ทีมพัฒนาของเราควบคุมการใช้งานคอมโพเนนต์ได้มากขึ้นโดยที่ยังได้ประโยชน์จากแนวทางป้องกันที่เรามีอยู่
เราหวังว่าข้อมูลเชิงลึกนี้เกี่ยวกับวิธีใช้คอมโพเนนต์เว็บที่มีพร็อพเพอร์ตี้ที่กำหนดเองของ CSS ให้เป็นประโยชน์ โปรดบอกให้เราทราบว่าคุณคิดเห็นอย่างไร และหากตัดสินใจที่จะใช้วิธีการเหล่านี้ในงานของคุณเอง โปรดติดต่อฉันทาง Twitter ที่ @DavidDarnes นอกจากนี้ คุณยังติดตาม Nordhealth ได้ที่ @NordhealthHQ ใน Twitter รวมถึงติดตามทีมที่เหลือของเราที่ทุ่มเททำงานเพื่อพัฒนาระบบการออกแบบนี้และทำให้ฟีเจอร์ที่กล่าวถึงในบทความนี้ใช้งานได้จริงได้ที่ @Viljamis, @WickyNilliams และ @eric_habich
รูปภาพหลักโดย Dan Cristian Pădureț