بناء مكونات تفاعل قابلة لإعادة الاستخدام باستخدام Tailwind
نشرت: 2022-03-10في هذا المنشور ، سنلقي نظرة على عدة طرق مختلفة يمكنك من خلالها بناء مكونات React قابلة لإعادة الاستخدام تعمل على الاستفادة من Tailwind تحت غطاء المحرك بينما تعرض واجهة لطيفة لمكونات أخرى. سيؤدي ذلك إلى تحسين الكود الخاص بك عن طريق الانتقال من القوائم الطويلة لأسماء الفئات إلى الدعامات الدلالية التي يسهل قراءتها والحفاظ عليها.
ستحتاج إلى العمل مع React من أجل الحصول على فهم جيد لهذا المنشور.
Tailwind هو إطار عمل CSS شائع جدًا يوفر فئات أدوات مساعدة منخفضة المستوى لمساعدة المطورين على إنشاء تصميمات مخصصة. نمت شعبيتها على مدار السنوات القليلة الماضية لأنها تحل مشكلتين جيدًا:
- تسهل أداة Tailwind إجراء تغييرات تكرارية على HTML دون البحث في أوراق الأنماط للعثور على محددات CSS المتطابقة.
- تتمتع 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 في تبني أسماء الفئات وتبديلها برمجيًا.
تُسهِّل الوحدة النمطية classnames 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 مثل size
و textColor
و bgColor
.
- قم بتمرير الدعائم مثل
bgColor
وtextColor
مباشرة إلى قالب سلسلة اسم الفئة. - استخدم الكائنات للتبديل بين أسماء الفئات برمجيًا (كما فعلنا مع خاصية
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
يحدد حجم الزر ويطبق فئات Tailwindtext-xs
أوtext-xl
-
bgColor
يحدد لون خلفية الزر ويطبق فئات Tailwindbg-*
. -
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 لتبديل سلوك العرض.
باختصار ، تعد وحدة classnames طريقة بسيطة وفعالة للتحكم برمجيًا في أسماء الفئات لـ Tailwind. يسهل فصل المنطق في دعامات React ، مما يسهل إعادة استخدام مكوناتك. إنه يعمل مع المكونات البسيطة والتفاعلية.
الطريقة الثانية: استخدام الثوابت لتحديد نظام التصميم
هناك طريقة أخرى لاستخدام 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
وسيتم تحديث جميع الأزرار في تطبيقك تلقائيًا. قد يكون هذا أسهل من البحث عن أسماء الفئات في مكونات مختلفة.
الطريقة الثالثة: إنشاء الأدوات باستخدام @apply
هناك طريقة ثالثة لتحسين وضوح مكونات @apply
وهي استخدام 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
-basic و .btn-secondary
معًا. لا تتضح هذه المعلومات بمجرد النظر إلى الفصول الدراسية.
إذا كان هذا المكون شيئًا أكثر تعقيدًا ، فستحتاج أيضًا إلى فهم العلاقة بين الوالدين والطفل. بطريقة ما ، هذه هي المشكلة التي تم تصميم Tailwind لحلها ، وباستخدام @apply
، فإننا نعيد المشكلات بطريقة مختلفة.
إليك مقطع فيديو يتعمق فيه آدم ووثان - مبتكر Tailwind - في إيجابيات وسلبيات استخدام @apply
.
ملخص
في هذه المقالة ، نظرنا في ثلاث طرق يمكنك من خلالها دمج Tailwind في تطبيق React لبناء مكونات قابلة لإعادة الاستخدام. تساعدك هذه الطرق على بناء مكونات React التي لها واجهة أنظف باستخدام props
.
- استخدم وحدة classnames لتبديل الفئات برمجيًا.
- حدد ملف ثوابت حيث يمكنك تحديد قائمة بالفئات لكل حالة مكون.
- استخدم
@apply
لاستخراج فئات CSS عالية المستوى.
إذا كان لديك أي أسئلة ، فأرسل لي رسالة على Twitter علىtilomitra.
موصى بقراءة على SmashingMag:
- إعداد Tailwind CSS في مشروع React
- إنشاء جداول قابلة للفرز باستخدام React
- دليل لأدوات تطوير CSS الجديدة والتجريبية في Firefox
- اصنع لوحات المحتوى الموسعة والمتعاقد عليها