هل لدى المصمم فكرة جديدة؟ ما يمكن أن يكون أسهل

مرحبا ، هابروفشانين! المصممون هم أشخاص أيديولوجيون وعملاء ، لا سيما مع متطلبات أعمالهم.

تخيل أنك كومة أفضل UIkit الخاص بك في العالم في أروع ٪ إدراج إطار JS ٪ الخاص بك. يبدو أن هناك كل ما يحتاجه المشروع. الآن يمكنك شرب القهوة ، وإغلاق جميع المهام الجديدة عن طريق رمي المكونات على الصفحة. والأفضل من ذلك ، إذا وجدت مثل هذه واجهة المستخدم في مكب نفايات في المساحات المفتوحة لـ NPM وهي تتوافق تمامًا مع UX / UI الحالي واحتياجاته. خيال!

وحقا ... من أنا أمزح؟ سعادتك من المرجح أن تكون قصيرة الأجل. في الواقع ، عندما يأتي المصمم قيد التشغيل مع Talmud من حلول واجهة المستخدم الجديدة للصفحة التالية أو "مشروع خاص" ، سيكون هناك خطأ ما على أي حال.

في هذه المرحلة ، يواجه المطور السؤال "DRY or not DRY" ؟ هل يجب علي تخصيص المكونات الموجودة بطريقة أو بأخرى؟ نعم ، حتى لا تؤخر الانحدار في الحالات القائمة. أو تصرف وفقًا لمبدأ "الأعمال - لا تلمس" واكتب مكونات جديدة من نقطة الصفر. في الوقت نفسه ، تضخيم UIkit وتعقيد الدعم.

إذا كنت ، مثل كثيرين ، في مثل هذا الموقف ، فابحث عن هذا الحد!



على الرغم من المقدمة الواسعة ، جاءت فكرة كتابة هذا المقال لي بعد قراءة أحد سلاسل التعليقات على حبري. هناك ، تم رش اللاعبين بجدية حول كيفية تخصيص عنصر الزر في React. حسنًا ، بعد أن شاهدت اثنين من هذه holivars في Telegram ، تم تعزيز الحاجة إلى الكتابة حول هذا الأمر أخيرًا.

بادئ ذي بدء ، دعونا نحاول تخيل "التخصيصات" التي قد نحتاج إلى تطبيقها على المكون.

الأنماط



بادئ ذي بدء ، هذا هو تخصيص أنماط المكون. مثال شائع هو زر رمادي ، ولكن هناك حاجة إلى واحدة زرقاء. أو زر دون زوايا مدورة وفجأة تكون هناك حاجة إليها. استنادا إلى holivars قرأت ، خلصت إلى أن هناك ما يقرب من 3 طرق لهذا:

1. الأساليب العالمية


استخدم القوة الكاملة لأنماط CSS العالمية ، التي تمت إعادة توجيهها إلى حد كبير ! هام ، بحيث في الخارج ، على المستوى العالمي ، حاول أن تتداخل مع أنماط المكون الأصلي. القرار ، بعبارة ملطفة ، مثير للجدل ومباشر للغاية. علاوة على ذلك ، فإن هذا الخيار ببساطة غير ممكن دائمًا وفي الوقت نفسه ينتهك بشكل يائس أي تغليف للأسلوب. ما لم يكن بالطبع يتم استخدامه في المكونات الخاصة بك.

2. اجتياز الطبقات (الأنماط) من السياق الأصلي


أيضا قرار مثير للجدل للغاية. اتضح أننا نقوم بإنشاء دعامة خاصة ، كما كان ، على سبيل المثال ، دعنا نسميها فئات ونزج فوراً الفئات اللازمة في المكون مباشرةً من الأعلى.

<Button classes="btn-red btn-rounded" /> 

بطبيعة الحال ، لن يعمل مثل هذا النهج إلا إذا كان المكون يدعم تطبيق الأنماط على محتواه بهذه الطريقة. بالإضافة إلى ذلك ، إذا كان المكون أكثر تعقيدًا ويتكون من بنية متداخلة من عناصر HTML ، فمن الواضح أن تطبيق الأنماط على الكل سيكون مشكلة. لذلك ، سيتم تطبيقها على العنصر الجذر للمكون ، وبعد ذلك ، باستخدام قواعد CSS ، سوف تنتشر بطريقة أو بأخرى. بحزن.

3. تحديد المكون باستخدام الدعائم


يبدو أنه الأكثر منطقية ، ولكن في نفس الوقت هو الحل الأقل مرونة. ببساطة ، نتوقع أن يكون مؤلف العنصر نوعًا من العبقرية ويفكر في جميع الخيارات مقدمًا. وهذا هو ، كل ما قد نحتاجه وتحديد جميع الدعائم اللازمة لجميع النتائج المرجوة:

 <Button bgColor="red" rounded={true} /> 

هذا لا يبدو مرجحًا جدًا ، هاه؟ ربما.

السلوك




هنا لا يزال أكثر غموضا. بادئ ذي بدء ، لأن الصعوبات في تخصيص سلوك عنصر تأتي من المهمة. وكلما زاد تعقيد المكون والمنطق فيه ، وكذلك كلما زاد التغيير الذي نريد إجراءه تعقيدًا ، زاد صعوبة إجراء هذا التغيير. تحولت نوعا من tautology ... باختصار ، أنت تفهم! ؛-)

ومع ذلك ، حتى هنا ، هناك مجموعة من الأدوات التي إما أن تساعدنا في تخصيص المكون أم لا. نظرًا لأننا نتحدث بشكل خاص عن نهج المكون ، أود أن أبرز الأدوات المفيدة التالية:

1. عمل مريحة مع الدعائم


بادئ ذي بدء ، يجب أن تكون قادرًا على محاكاة مجموعة الدعائم المكونة دون الحاجة إلى إعادة وصف هذه المجموعة والتعبير عنها بسهولة.

علاوة على ذلك ، إذا حاولنا إضافة بعض السلوك إلى المكون ، فعلى الأرجح ، سنحتاج إلى استخدام مجموعة إضافية من الدعائم التي لا يحتاج إليها المكون الأصلي. لذلك ، من الجيد أن تكون قادرًا على قطع جزء من الدعائم ونقل فقط الضروري إلى المكون الأصلي. في الوقت نفسه ، الحفاظ على جميع الخصائص متزامنة.

الجانب الآخر هو عندما نريد تنفيذ حالة خاصة من سلوك المكون. بطريقة ما لإصلاح جزء من ولايته في مهمة محددة.

2. تتبع دورة حياة المكون والأحداث


بمعنى آخر ، يجب ألا يكون كل ما يحدث داخل أحد المكونات كتابًا مغلقًا تمامًا. خلاف ذلك ، فإنه يعقد حقا تخصيص سلوكه.

لا أقصد انتهاك التغليف والتدخل غير المنضبط في الداخل. يجب إدارة المكون من خلال واجهة برمجة تطبيقاته العامة (عادةً ما تكون أدوات و / أو طرق). ولكن لكي تكون قادرًا على "معرفة" ما يحدث في الداخل وتتبع التغيير في حالته ، لا يزال ضروريًا.

3. إدارة حتمية


سوف نفترض أنني لم أخبرك بهذا. ومع ذلك ، في بعض الأحيان ، من الجيد أن تكون قادرًا على الحصول على مثيل لأحد المكونات و "سحب الأوتار" بشكل حتمي. من الأفضل تجنب ذلك ، ولكن في الحالات المعقدة بشكل خاص ، لا يمكنك الاستغناء عنه.

حسنا ، نوعا من تسويتها النظرية. إلى حد كبير ، كل شيء واضح ، ولكن ليس كل شيء واضح. لذلك ، يجدر النظر في بعض الحالات الحقيقية على الأقل.

القضية




ذكرت أعلاه أن فكرة كتابة مقال نشأت بسبب holivar حول تخصيص زر. لذلك ، اعتقدت أنه سيكون من الرمزية حل مثل هذه الحالة. سيكون تغيير اللون أو زوايا التقريب بغباء أمرًا بالغ السهولة ، لذلك حاولت أن أتوصل إلى حالة أكثر تعقيدًا بقليل.

تخيل أن لدينا مكونًا معينًا من الزر الأساسي ، والذي يتم استخدامه في سجن مواقع التطبيقات. بالإضافة إلى ذلك ، تطبق بعض السلوكيات الأساسية لجميع أزرار التطبيق ، بالإضافة إلى مجموعة من الأنماط الأساسية والمغلفة ، والتي يتم مزامنتها من وقت لآخر مع أدلة واجهة المستخدم وكل ذلك.

علاوة على ذلك ، يصبح من الضروري وجود عنصر إضافي لزر الإرسال إلى الخادم (زر الإرسال) ، والذي يتطلب ، بالإضافة إلى تغييرات النمط ، سلوكًا إضافيًا. على سبيل المثال ، يمكن أن يكون رسمًا للتقدم المحرز في الإرسال ، بالإضافة إلى تمثيل مرئي لنتائج هذا الإجراء - بنجاح أم لا.

قد يبدو مثل هذا:



ليس من الصعب تخمين أن الزر الأساسي يقع على اليسار ، وأن زر الإرسال على اليمين في حالة الانتهاء بنجاح من الطلب. حسنًا ، إذا كانت الحالة واضحة - فلنبدأ!

الحل


ما زلت لا أستطيع أن أعرف بالضبط ما تسبب في holivar في قرار React. على ما يبدو ليس هناك بهذه البساطة. لذلك ، لن أجرب حظي وأستخدم الأداة الأكثر دراية - SvelteJS - إطار جديد من الجيل المختفي مثالي لحل مثل هذه المشكلات .

سنتفق على الفور ، لن نتدخل بأي شكل من الأشكال مع رمز الزر الأساسي. نحن نفترض أنه لم يكتب من قبلنا على الإطلاق ، وأن كوده مغلق للتصحيح. في هذه الحالة ، سيبدو مكون الزر الأساسي كما يلي:

Button.html

 <button {type} {name} {value} {disabled} {autofocus} on:click > <slot></slot> </button> <script> export default { data() { return { type: 'button', disabled: false, autofocus: false, value: '', name: '' }; } }; </script> <style> /* scoped styles */ </style> 

واستخدمت بهذه الطريقة:

 <Button on:click="cancel()">Cancel</Button> 

يرجى ملاحظة أن عنصر الزر هو حقا الأساسية للغاية. لا يحتوي على أي عناصر أو دعائم إضافية يمكن أن تساعد في تنفيذ الإصدار الموسع للمكون. لا يدعم هذا المكون حتى نقل الأنماط عن طريق الدعائم أو على الأقل نوعا من التخصيص المدمج ، وجميع الأنماط معزولة بشكل صارم ولا تتسرب.

قد يكون إنشاء عنصر آخر على أساس هذا المكون ، مع وظائف محسّنة ، وحتى بدون إجراء تغييرات ، مهمة سهلة. ولكن ليس عند استخدام Svelte .

الآن دعونا نحدد ما يجب أن يكون زر الإرسال قادرًا على القيام به:

  1. بادئ ذي بدء ، يجب أن يكون النص والإطار الزر الأخضر. عند التحويم ، يجب أن تكون الخلفية أيضًا خضراء بدلاً من الرمادي الداكن.
  2. علاوة على ذلك ، عند الضغط على زر ، يجب أن "ينتقد" في مؤشر التقدم الدائري.
  3. عند الانتهاء من العملية (التي يتم التحكم فيها خارجيًا) ، من الضروري تغيير حالة الزر إلى نجاح (نجاح) أو عدم نجاح (خطأ). في الوقت نفسه ، يجب أن يتحول الزر من المؤشر إما إلى شارة خضراء ذات مؤشر داو أو شارة حمراء عليها صليب.
  4. من الضروري أيضًا أن تكون قادرًا على ضبط الوقت الذي ستتحول بعده الشارة المقابلة مرة أخرى إلى زر في حالته الأصلية (الخمول).
  5. وبالطبع ، تحتاج إلى القيام بكل ذلك أعلى زر القاعدة مع حفظ وتطبيق جميع الأنماط والدعائم من هناك.

فوه ، ليست مهمة سهلة. لنقم أولاً بإنشاء مكون جديد ولفه بالزر الأساسي:

SubmitButton.html

 <Button> <slot></slot> </Button> <script> import Button from './Button.html'; export default { components: { Button } }; </script> 

على الرغم من أن هذا هو نفس الزر تمامًا ، إلا أنه أسوأ من ذلك - حتى أنه لا يعرف كيفية عمل الدعائم بالوكالة. هذا لا يهم ، سنعود إلى هذا في وقت لاحق.

أسلب


في غضون ذلك ، دعونا نفكر في الطريقة التي يمكننا بها تصميم زر جديد ، أي تغيير الألوان ، حسب المهمة. لسوء الحظ ، يبدو أننا لا نستطيع استخدام أي من الطرق الموضحة أعلاه.

نظرًا لأن الأنماط يتم عزلها داخل أحد الأزرار ، فقد تحدث مشكلات في الأنماط العامة. من المستحيل أيضًا إدخال الأنماط - الزر الأساسي لا يدعم هذه الميزة. وكذلك تخصيص المظهر بمساعدة الدعائم. بالإضافة إلى ذلك ، نود أيضًا تغليف جميع الأنماط المكتوبة للزر الجديد داخل هذا الزر وعدم التسرب منها.

الحل بسيط للغاية ، لكن فقط إذا كنت تستخدم Svelte بالفعل. لذلك ، فقط اكتب الأنماط للزر الجديد:

 <div class="submit"> <Button> <slot></slot> </Button> </div> ... <style> .submit :global(button) { border: 2px solid #1ECD97; color: #1ECD97; } .submit :global(button:hover) { background-color: #1ECD97; color: #fff; } </style> 

واحدة من أساسيات Svelte - يجب حل الأشياء البسيطة ببساطة. سيقوم المُعدِّل الخاص : Global في هذا الإصدار بإنشاء CSS بحيث لا تتلقى الأنماط المحددة إلا الأزرار الموجودة داخل الكتلة مع فئة الإرسال الموجودة في هذا المكون.

حتى إذا ظهرت العلامات من نفس النوع فجأة في أي مكان آخر في التطبيق:

 <div class="submit"> <button>Button</button> </div> 

أنماط من مكون SubmitButton بأي شكل من الأشكال "تسرب" هناك.

باستخدام هذه الطريقة ، يجعل Svelte من السهل تخصيص أنماط المكونات المتداخلة ، مع الحفاظ على تغليف أنماط كلا المكونين.

نحن رمي الدعائم وإصلاح السلوك


حسنًا ، تعاملنا مع التصميم على الفور تقريبًا ودون أي دعائم إضافية واجتياز فصول CSS مباشرةً. الآن تحتاج إلى وكيل جميع الدعائم من مكون زر من خلال المكون الجديد. ومع ذلك ، لا أريد أن أصفها مرة أخرى. ومع ذلك ، بالنسبة للمبتدئين ، لنقرر الخصائص التي سيحتوي عليها المكون الجديد.

اذا حكمنا من خلال المهمة ، يجب أن يقوم SubmitButton بمراقبة الحالة ، وكذلك توفير فرصة لتحديد التأخير الزمني بين التغيير التلقائي لحالة النجاح / الخطأ إلى الحالة الأولية:

 <script> ... export default { ... data() { return { delay: 1500, status: 'idle' // loading, success, error }; } }; </script> 

لذلك ، سيكون لدينا زر جديد 4 حالات: الراحة ، التنزيل ، النجاح أو الخطأ. بالإضافة إلى ذلك ، بشكل افتراضي ، سيتم تغيير حالتين الأخيرتين تلقائيًا إلى حالة الخمول بعد 1.5 ثانية.

من أجل رمي جميع الدعائم المرسلة في مكون Button ، ولكن في نفس الوقت قطع الحالة والتأخير غير الواضحين لذلك ، سنكتب خاصية محسوبة خاصة. وبعد ذلك نستخدم عامل الانتشار ببساطة "لتشويه" الدعائم المتبقية على المكون المضمن. بالإضافة إلى ذلك ، نظرًا لأننا نفعل زر التقديم تمامًا ، فنحن بحاجة إلى إصلاح نوع الزر بحيث لا يمكن تغييره من الخارج:

 <div class="submit"> <Button {...attrs} type="submit"> <slot></slot> </Button> </div> <script> ... export default { ... computed: { attrs: data => { const { delay, status, ...attrs } = data; return attrs; } }, }; </script> 

بسيطة جدا وأنيقة.

نتيجةً لذلك ، حصلنا على نسخة كاملة من الزر الأساسي مع أنماط معدلة. لقد حان الوقت لتنفيذ سلوك الزر الجديد.

نحن نغير ونتتبع الحالة


لذلك ، عند النقر فوق الزر SubmitButton ، يجب ألا نطرد الحدث فقط بحيث يمكن لرمز المستخدم معالجته (كما هو الحال في Button ) ، ولكن أيضًا تنفيذ منطق عمل إضافي - قم بتعيين حالة التنزيل. للقيام بذلك ، ما عليك سوى التقاط الحدث من الزر الأساسي إلى معالجك الخاص ، وقم بما تحتاجه وأرسله إلى أبعد من ذلك:

 <div class="submit"> <Button {...attrs} type="submit" on:click="click(event)"> <slot></slot> </Button> </div> <script> ... export default { ... methods: { click(e) { this.set({ status: 'loading' }); this.fire('click', e); } }, }; </script> 

علاوة على ذلك ، يمكن للمكون الأصل لهذا الزر ، الذي يتحكم في عملية إرسال البيانات نفسها ، تعيين حالة الإرسال المقابلة ( النجاح / الخطأ ) من خلال الدعائم. في الوقت نفسه ، يجب أن يتتبع الزر مثل هذا التغيير في الحالة ، وبعد وقت محدد يغير الحالة تلقائيًا إلى الخمول . للقيام بذلك ، استخدم ربط onupdate دورة الحياة :

 <script> ... export default { ... onupdate({ current: { status, delay }, changed }) { if (changed.status && ['success', 'error'].includes(status)) { setTimeout(() => this.set({ status: 'idle' }), delay); } }, }; </script> 

اللمسات الأخيرة


هناك نقطتان أخريان غير واضحتين من المهمة وتنشأان أثناء التنفيذ. أولاً ، من أجل أن تكون الرسوم المتحركة الخاصة بتحولات الأزرار سلسة ، يجب عليك تغيير الزر نفسه باستخدام الأنماط وليس بعض العناصر الأخرى. للقيام بذلك ، يمكننا استخدام نفس الشيء : عالمي ، لذلك لا توجد مشاكل. لكن بالإضافة إلى ذلك ، من الضروري إخفاء العلامات الموجودة داخل الزر في جميع الحالات ، باستثناء الخمول .

تجدر الإشارة بشكل منفصل إلى أن العلامات الموجودة داخل الزر يمكن أن تكون موجودة ويتم طرحها في المكون الأصلي للزر الأساسي من خلال فتحات متداخلة. ومع ذلك ، على الرغم من أن هذا يبدو مهددًا ، إلا أن الحل أكثر من بدائي - تحتاج فقط إلى التفاف الفتحة داخل المكون الجديد في عنصر إضافي وتطبيق الأنماط اللازمة عليه:

 <div class="submit"> <Button {...attrs} type="submit" on:click="click(event)"> <span><slot></slot></span> </Button> </div> ... <style> ... .submit span { transition: opacity 0.3s 0.1s; } .submit.loading span, .submit.success span, .submit.error span { opacity: 0; } ... </style> 

بالإضافة إلى ذلك ، نظرًا لأن الزر لا يختفي من الصفحة ، ولكن يتحول إلى جانب الحالات ، سيكون من الجيد تعطيله في وقت الإرسال. بمعنى آخر ، إذا تم تعيين زر الإرسال على تعطيل باستخدام الدعائم ، أو إذا لم تكن الحالة خاملاً ، فيجب عليك تعطيل الزر. لحل هذه المشكلة ، نكتب خاصية أخرى محسوبة صغيرة isDisabled ونطبقها على المكون المتداخل:

 <div class="submit"> <Button {...attrs} type="submit" disabled={isDisabled}> <span><slot></slot></span> </Button> </div> <script> ... export default { ... computed: { ... isDisabled: ({ status, disabled }) => disabled || status !== 'idle' }, }; </script> 

سيكون كل شيء على ما يرام ، لكن الزر الأساسي له نمط يجعله شفافًا في حالة المعوقين ، لكننا لسنا بحاجة إليه إذا تم تعطيل الزر مؤقتًا فقط بسبب تغيير الحالة. كل هذا يأتي لإنقاذ : عالمي :

  .submit.loading :global(button[disabled]), .submit.success :global(button[disabled]), .submit.error :global(button[disabled]) { opacity: 1; } 

هذا كل شئ! الزر الجديد جميل وجاهز للذهاب!



سأحذف عمدا تفاصيل تنفيذ الرسوم المتحركة وكل هذا. ليس فقط لأنه لا يرتبط ارتباطًا مباشرًا بموضوع المقال ، ولكن أيضًا لأنه في هذا الجزء لم يتحول العرض التوضيحي كما نود. لم أقم بتعقيد مهمتي ونفذ حلاً جاهزًا تمامًا لمثل هذا الزر وبدلاً من ذلك ، قمنا بتحويل مثال موجود على الإنترنت.

لذلك ، لا أنصح باستخدام هذا التطبيق في العمل. تذكر ، هذا مجرد عرض لهذا المقال.

عرض تجريبي ومثال كامل رمز

إذا أعجبك المقال وأردت معرفة المزيد عن Svelte ، فاقرأ مقالات أخرى. على سبيل المثال ، "كيفية البحث عن مستخدم على GitHub دون React + RxJS 6 + Recompose . " استمع إلى إذاعة RadioJS # 54 الصوتية للعام الجديد ، حيث تحدثت بشيء من التفصيل حول ماهية Svelte وكيف "تختفي" ولماذا لا تكون "إطار عمل آخر لـ js".

تحقق من قناة برقية باللغة الروسية SvelteJS . يوجد بالفعل أكثر من مائتي منا وسنكون سعداء برؤيتك!

P / s

فجأة ، تغيرت إرشادات واجهة المستخدم. الآن يجب أن تكون التسميات في جميع أزرار التطبيق في الحالة العليا. ومع ذلك ، نحن لسنا خائفين من مثل هذا التحول في الأحداث. إضافة تحويل النص: الأحرف الكبيرة؛ في أنماط زر القاعدة والاستمرار في شرب القهوة.

أتمنى لك يوم عمل لطيف!

Source: https://habr.com/ru/post/ar438834/


All Articles