การสร้างส่วนประกอบ React แบบใช้ซ้ำได้โดยใช้ Tailwind

เผยแพร่แล้ว: 2022-03-10
สรุปอย่างย่อ ↬ Tailwind คือเฟรมเวิร์ก CSS ที่เน้นยูทิลิตี้เป็นหลักซึ่งให้ชื่อคลาสระดับต่ำแก่นักพัฒนาเว็บ ไม่มี JavaScript และทำงานได้ดีกับเฟรมเวิร์กที่มีอยู่เช่น React, Vue, Angular, Ember และอื่น ๆ แม้ว่าจะเป็นเรื่องดี แต่ก็อาจทำให้นักพัฒนารายใหม่เกิดความสับสนในการทำความเข้าใจวิธีผสานรวม Tailwind ในแอปพลิเคชันของตนได้ ในบทความนี้ เราจะสำรวจวิธีสร้างส่วนประกอบ React ที่นำกลับมาใช้ใหม่ได้โดยใช้ Tailwind

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

คุณจะต้องทำงานกับ React เพื่อทำความเข้าใจโพสต์นี้ให้ดี

Tailwind คือเฟรมเวิร์ก CSS ยอดนิยมที่มีคลาสยูทิลิตี้ระดับต่ำ เพื่อช่วยนักพัฒนาสร้างการออกแบบที่กำหนดเอง ได้รับความนิยมเพิ่มขึ้นในช่วงไม่กี่ปีที่ผ่านมา เนื่องจากสามารถแก้ปัญหาสองประการได้ดีมาก:

  1. Tailwind ช่วยให้ทำการเปลี่ยนแปลงซ้ำๆ กับ HTML ได้อย่างง่ายดายโดยไม่ต้องค้นหาสไตล์ชีตเพื่อค้นหาตัวเลือก CSS ที่ตรงกัน
  2. Tailwind มีหลักการและค่าเริ่มต้นที่สมเหตุสมผล ทำให้ง่ายต่อการเริ่มต้นโดยไม่ต้องเขียน CSS ตั้งแต่เริ่มต้น

เพิ่มเอกสารประกอบที่ครอบคลุม และไม่แปลกใจเลยว่าทำไม Tailwind ถึงได้รับความนิยม

วิธีการเหล่านี้จะช่วยคุณแปลงโค้ดที่มีลักษณะดังนี้:

 <button className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"> Enable </button>

หากต้องการรหัสที่มีลักษณะดังนี้:

 <Button size="sm" textColor="white" bgColor="blue-500"> Enable </Button>

ความแตกต่างระหว่างข้อมูลโค้ดทั้งสองคือในตอนแรกเราใช้แท็กปุ่ม HTML มาตรฐาน ในขณะที่ส่วนที่สองใช้คอมโพเนนต์ <Button> คอมโพเนนต์ <Button> สร้างขึ้นเพื่อให้นำกลับมาใช้ใหม่ได้และอ่านง่ายกว่าเนื่องจากมีความหมายที่ดีกว่า แทนที่จะใช้รายการชื่อคลาสแบบยาว มันใช้คุณสมบัติเพื่อตั้งค่าแอตทริบิวต์ต่างๆ เช่น size , textColor และ bgColor

มาเริ่มกันเลย.

เพิ่มเติมหลังกระโดด! อ่านต่อด้านล่าง↓

วิธีที่ 1: การควบคุมคลาสด้วยโมดูลชื่อคลาส

วิธีง่ายๆ ในการปรับ Tailwind ให้เป็นแอปพลิเคชัน React คือการยอมรับชื่อคลาสและสลับชื่อคลาสโดยทางโปรแกรม

โมดูลชื่อคลาส npm ทำให้ง่ายต่อการสลับคลาสใน React เพื่อสาธิตวิธีการใช้สิ่งนี้ ลองใช้กรณีที่คุณมีส่วนประกอบ <Button> ในแอปพลิเคชัน React ของคุณ

 // This could be hard to read. <button className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">Enable</button> // This is more conventional React. <Button size="sm" textColor="white" bgColor="blue-500">Enable</Button>

มาดูวิธีแยกคลาส Tailwind เพื่อให้ผู้ใช้คอมโพเนนต์ <Button> สามารถใช้ React props เช่น size , textColor และ bgColor

  1. ส่งอุปกรณ์ประกอบฉาก เช่น bgColor และ textColor ไปยังเทมเพลตสตริงชื่อคลาสโดยตรง
  2. ใช้อ็อบเจ็กต์เพื่อเปลี่ยนชื่อคลาสโดยทางโปรแกรม (ตามที่เราทำกับเสา size )

ในโค้ดตัวอย่างด้านล่าง เราจะพิจารณาทั้งสองวิธี

 // Button.jsx import classnames from 'classnames'; function Button ({size, bgColor, textColor, children}) { return ( <button className={classnames("bg-${bgColor} text-${textColor} font-bold py-2 px-4 rounded", { "text-xs": size === 'sm' "text-xl": size === 'lg', })}> {children} </button> ) }; export default Button;

ในโค้ดด้านบนนี้ เรากำหนดองค์ประกอบ Button ที่ใช้อุปกรณ์ประกอบฉากต่อไปนี้:

  • size
    กำหนดขนาดของปุ่มและใช้คลาส Tailwind text-xs หรือ text-xl
  • bgColor
    กำหนดสีพื้นหลังของปุ่มและใช้คลาส Tailwind bg-*
  • textColor
    กำหนดสีข้อความของปุ่มและใช้ text-* classes
  • children
    ส่วนประกอบย่อยใดๆ จะถูกส่งผ่านที่นี่ โดยปกติจะมีข้อความอยู่ภายใน <Button>

ด้วยการกำหนด Button.jsx ตอนนี้เราสามารถนำเข้าและใช้ React props แทนชื่อคลาสได้ ทำให้โค้ดของเราอ่านและนำกลับมาใช้ใหม่ได้ง่ายขึ้น

 import Button from './Button'; <Button size="sm" textColor="white" bgColor="blue-500">Enable</Button>

การใช้ชื่อคลาสสำหรับส่วนประกอบแบบโต้ตอบ

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

ตัวอย่างเช่น มาดูดรอปดาวน์ที่สร้างโดยใช้ Tailwind


ดรอปดาวน์แบบอินเทอร์แอกทีฟที่สร้างขึ้นโดยใช้ Tailwind และการสลับชื่อคลาส

สำหรับตัวอย่างนี้ เราสร้างองค์ประกอบ HTML โดยใช้ชื่อคลาส Tailwind CSS แต่เราเปิดเผยองค์ประกอบ React ที่มีลักษณะดังนี้:

 <Dropdown options={\["Edit", "Duplicate", "Archive", "Move", "Delete"\]} onOptionSelect={(option) => { console.log("Selected Option", option)} } />

เมื่อดูโค้ดด้านบน คุณจะสังเกตเห็นว่าเราไม่มีคลาส Tailwind ทั้งหมดถูกซ่อนอยู่ภายในโค้ดการใช้งานของ <Dropdown/> ผู้ใช้องค์ประกอบ Dropdown ต้องระบุรายการ options และตัวจัดการการคลิก onOptionSelect เมื่อ option

เรามาดูกันว่าจะสร้างคอมโพเนนต์นี้โดยใช้ Tailwind ได้อย่างไร

การลบโค้ดที่ไม่เกี่ยวข้องบางส่วน นี่คือปมของตรรกะ คุณสามารถดู Codepen นี้สำหรับตัวอย่างที่สมบูรณ์

 import classNames from 'classnames'; function Dropdown({ options, onOptionSelect }) { // Keep track of whether the dropdown is open or not. const [isActive, setActive] = useState(false); const buttonClasses = `inline-flex justify-center w-full rounded-md border border-gray-300 px-4 py-2 bg-white text-sm leading-5 font-medium text-gray-700 hover:text-gray-500 focus:outline-none focus:border-blue-300 focus:shadow-outline-blue active:bg-blue-500 active:text-gray-200 transition ease-in-out duration-150`; return ( // Toggle the dropdown if the button is clicked <button onClick={() => setActive(!isActive)} className={buttonClasses}> Options </button> // Use the classnames module to toggle the Tailwind .block and .hidden classes <div class={classNames("origin-top-right absolute right-0 mt-2 w-56 rounded-md shadow-lg", { block: isActive, hidden: !isActive })}> // List items are rendered here. {options.map((option) => <div key={option} onClick={(e) => onOptionSelect(option)}>{option}</div>)} </div> ) } export default Dropdown;

ดรอปดาวน์เป็นแบบโต้ตอบโดยเลือกแสดงหรือซ่อนโดยใช้คลาส . .hidden และ . .block เมื่อใดก็ตามที่ <button> เราจะเริ่มตัวจัดการ onClick ที่สลับสถานะ isActive หากปุ่มทำงานอยู่ ( isActive === true ) เราจะตั้งค่าคลาส block มิฉะนั้นเราจะตั้งค่าคลาสที่ hidden ซึ่งเป็นทั้งคลาสของ Tailwind สำหรับการสลับลักษณะการแสดงผล

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

วิธีที่ 2: การใช้ค่าคงที่เพื่อกำหนดระบบการออกแบบ

อีกวิธีหนึ่งในการใช้ Tailwind และ React ร่วมกันคือการใช้ค่าคงที่และอุปกรณ์ประกอบการแมปกับค่าคงที่เฉพาะ สิ่งนี้มีประสิทธิภาพสำหรับระบบการออกแบบอาคาร มาสาธิตด้วยตัวอย่าง

เริ่มต้นด้วยไฟล์ theme.js ที่คุณแสดงรายการระบบการออกแบบของคุณ

 // theme.js (you can call it whatever you want) export const ButtonType = { primary: "bg-blue-500 hover:bg-blue-700 text-white font-bold rounded", secondary: "bg-blue-500 hover:bg-blue-700 text-white font-bold rounded", basic: "bg-white hover:bg-gray-700 text-gray-700 font-bold rounded", delete: "bg-red-300 hover:bg-red-500 text-white font-bold rounded" }; export const ButtonSize = { sm: "py-2 px-4 text-xs", lg: "py-3 px-6 text-lg" }

ในกรณีนี้ เรามีค่าคงที่สองชุด:

  • ButtonType กำหนดรูปแบบปุ่มต่างๆ ในแอปของเรา
  • ButtonSizes กำหนดขนาดของปุ่มในแอปของเรา

ตอนนี้ มาเขียนองค์ประกอบ <Button> ของเรา:

 import {ButtonType, ButtonSize} from './theme'; function Button({size, type, children}) { // This can be improved. I'm keeping it simple here by joining two strings. const classNames = ButtonType[type] + " " + ButtonSize[size]; return ( <button className={classNames}>{children}</button> ) } export default Button;

เราใช้ค่าคงที่ ButtonType และ ButtonSize เพื่อสร้างรายชื่อคลาส สิ่งนี้ทำให้อินเทอร์เฟซของ <Button> ของเราดีขึ้นมาก ช่วยให้เราใช้ size และ type อุปกรณ์ประกอบฉากแทนการใส่ทุกอย่างในสตริงชื่อคลาส

 // Cleaner and well defined props. <Button size="xs" type="primary">Enable</Button>

เทียบกับแนวทางก่อนหน้า:

 // Exposing class names <button className="py-2 px-4 text-xs bg-blue-500 hover:bg-blue-700 text-white font-bold rounded">Enable</button>

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

วิธีที่ 3: การเขียนยูทิลิตี้ด้วย @apply

วิธีที่สามในการปรับปรุงความชัดเจนของส่วนประกอบ React ของคุณคือการใช้ CSS และรูปแบบ @apply ที่มีอยู่ใน PostCSS เพื่อแยกคลาสที่ซ้ำกัน รูปแบบนี้เกี่ยวข้องกับการใช้สไตล์ชีตและตัวประมวลผลภายหลัง

มาสาธิตวิธีการทำงานผ่านตัวอย่างกัน สมมติว่าคุณมีกลุ่มปุ่มที่มีปุ่มหลักและปุ่มรอง

กลุ่มปุ่มประกอบด้วยปุ่มหลักและปุ่มรอง
กลุ่มปุ่มประกอบด้วยปุ่มหลักและปุ่มรอง (ตัวอย่างขนาดใหญ่)
 <button className="py-2 px-4 mr-4 text-xs bg-blue-500 hover:bg-blue-700 text-white font-bold rounded">Update Now</button> <button className="py-2 px-4 text-xs mr-4 hover:bg-gray-100 text-gray-700 border-gray-300 border font-bold rounded">Later</button>

การใช้รูปแบบ @apply คุณสามารถเขียน HTML นี้เป็น:

 <button className="btn btn-primary btn-xs">Update Now</button> <button className="btn btn-secondary btn-xs">Later</button>

ซึ่งสามารถนำไปปรับใช้กับ React ให้เป็น:

 import classnames from "classnames"; function Button ({size, type, children}) { const bSize = "btn-" + size; const bType = "btn-" + type; return ( <button className={classnames("btn", bSize, bType)}>{children}</button> ) } Button.propTypes = { size: PropTypes.oneOf(['xs, xl']), type: PropTypes.oneOf(['primary', 'secondary']) }; // Using the Button component. <Button type="primary" size="xs">Update Now</Button> <Button type="secondary" size="xs">Later</Button>

ต่อไปนี้คือวิธีสร้างชื่อคลาสสไตล์ BEM เช่น .btn , .btn-primary และอื่นๆ เริ่มต้นด้วยการสร้างไฟล์ button.css :

 /\* button.css \*/ @tailwind base; @tailwind components; .btn { @apply py-2 px-4 mr-4 font-bold rounded; } .btn-primary { @apply bg-blue-500 hover:bg-blue-700 text-white; } .btn-secondary { @apply hover:bg-gray-700 text-gray-700 border-gray-300 border; } .btn-xs { @apply text-xs; } .btn-xl { @apply text-xl; } @tailwind utilities;

โค้ดด้านบนไม่ใช่ CSS จริง แต่จะรวบรวมโดย PostCSS มีที่เก็บ GitHub ที่นี่ ซึ่งจะแสดงวิธีตั้งค่า PostCSS และ Tailwind สำหรับโปรเจ็กต์ JavaScript

นอกจากนี้ยังมีวิดีโอสั้น ๆ ที่แสดงวิธีตั้งค่าที่นี่

ข้อเสียของการใช้ @apply

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

อันดับแรก การแยกชื่อคลาสเหล่านี้ออก เราจะสูญเสียข้อมูลบางส่วน ตัวอย่างเช่น เราต้องระวังว่าจะต้องเพิ่ม .btn-primary ลงในส่วนประกอบที่มี .btn นำไปใช้กับมันอยู่แล้ว นอกจากนี้ .btn-primary และ .btn-secondary ยังใช้ร่วมกันไม่ได้ ข้อมูลนี้ไม่ปรากฏชัดเมื่อดูจากชั้นเรียน

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

นี่คือวิดีโอที่ Adam Wathan ผู้สร้าง Tailwind เจาะลึกข้อดีข้อเสียของการใช้ @apply

สรุป

ในบทความนี้ เราได้พิจารณาสามวิธีในการผสานรวม Tailwind เข้ากับแอปพลิเคชัน React เพื่อสร้างส่วนประกอบที่ใช้ซ้ำได้ วิธีการเหล่านี้ช่วยให้คุณสร้างส่วนประกอบ React ที่มีอินเทอร์เฟซที่สะอาดขึ้นโดยใช้ props

  1. ใช้โมดูลชื่อคลาสเพื่อสลับคลาสโดยทางโปรแกรม
  2. กำหนดไฟล์ค่าคงที่ที่คุณกำหนดรายการของคลาสต่อสถานะคอมโพเนนต์
  3. ใช้ @apply เพื่อแยกคลาส CSS ระดับสูง

หากคุณมีคำถามใด ๆ ส่งข้อความบน Twitter ที่ @tilomitra

การอ่านที่แนะนำ บน SmashingMag:

  • การตั้งค่า Tailwind CSS ในโครงการตอบสนอง
  • การสร้างตารางที่จัดเรียงได้ด้วย React
  • คำแนะนำเกี่ยวกับ CSS DevTools ใหม่และทดลองใน Firefox
  • สร้างแผงเนื้อหาที่ขยายและทำสัญญาของคุณเอง