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

لقد سمع الجميع عن منهجية BEM. محددات CSS مع الشرطة السفلية. تحدث عن عنصر المكون ، مع الأخذ في الاعتبار الطريقة التي يتم بها كتابة محددات CSS CSS. ولكن لن تكون هناك كلمة عن CSS في المقال. فقط شبيبة ، المتشددين فقط!
لفهم سبب ظهور المنهجية والمشكلات التي واجهتها ياندكس في ذلك الوقت ، أوصي بأن تتعرف على تاريخ BEM.
مقدمة
ولدت BEM حقا كخلاص من الاتصال القوي والتعشيش في CSS. لكن تقسيم ورقة style.css
إلى ملفات لكل كتلة أو عنصر أو معدّل أدى حتماً إلى بنية مماثلة لرمز JavaScript.
في عام 2011 ، استحوذت Open Source على الالتزامات الأولى i-bem.js
، والتي عملت مع محرك القالب bem-xjst
. نشأت كلتا التقنيتين من XSLT وخدمت الفكرة الشائعة آنذاك لفصل منطق الأعمال والعرض التقديمي للمكونات. في العالم الخارجي ، كانت هذه الأوقات الرائعة لـ Handlebars و Underscore.
bem-xjst
هو نوع مختلف من محرك القالب. من أجل زيادة معرفتي بهيكلية أساليب التوحيد ، أوصي بشدة بتقرير سيرجي بيريزني . bem-xjst
تجربة محرك القالب bem-xjst
في صندوق الحماية عبر الإنترنت .
نظرًا لخصائص خدمات بحث Yandex ، تم تصميم واجهات المستخدم باستخدام البيانات. صفحة نتائج البحث فريدة لكل استعلام.

استعلام البحث عن طريق الرابط

استعلام البحث عن طريق الرابط

استعلام البحث عن طريق الرابط
عندما ينتشر التقسيم إلى كتلة وعنصر ومعدل في نظام الملفات ، فإن هذا يسمح بتجميع أكبر قدر ممكن فقط من الشفرة الضرورية ، في الواقع لكل صفحة ، لكل طلب مستخدم. لكن كيف؟
src/components ├── ComponentName │ ├── _modName │ │ ├── ComponentName_modName.tsx — │ │ └── ComponentName_modName_modVal.tsx — │ ├── ElementName │ │ └── ComponentName-ElementName.tsx — ComponentName │ ├── ComponentName.i18n — │ │ ├── ru.ts — │ │ ├── en.ts — │ │ └── index.ts — │ ├── ComponentName.test — │ │ ├── ComponentName.page-object.js — Page Object │ │ ├── ComponentName.hermione.js — │ │ └── ComponentName.test.tsx — unit- │ ├── ComponentName.tsx — │ ├── ComponentName.scss — │ ├── ComponentName.examples.tsx — Storybook │ └── README.md —
هيكل دليل المكون الحديث
كما هو الحال في بعض الشركات الأخرى ، في Yandex ، يكون مطورو الواجهة مسؤولين عن الواجهة الأمامية ، التي تتكون من جزء العميل في المستعرض وجزء الخادم على Node.js
يعالج جزء الخادم بيانات البحث "الكبير" ويفرض قوالب عليها. تحول معالجة البيانات الأولية JSON إلى BEMJSON ، وهي بنية البيانات الخاصة bem-xjst
قوالب bem-xjst
. يدور محرك القالب حول كل عقدة من الشجرة ويفرض قالبًا عليها. نظرًا لأن التحويل الأساسي يتم على الخادم ، نظرًا للتقسيم إلى كيانات صغيرة ، فإن العقد تتوافق مع الملفات ، وخلال عملية إنشاء القوالب ، ندفع رمز المتصفح الذي سيتم استخدامه فقط في الصفحة الحالية.
أدناه هي مراسلة العقد BEMJSON إلى الملفات الموجودة على نظام الملفات.
module.exports = { block: 'Select', elem: 'Item', elemMods: { type: 'navigation' } };
src/components ├── Select │ ├── Item │ │ _type │ │ ├── Select-Item_type_navigation.js │ │ └── Select-Item_type_navigation.css
كان نظام وحدات YModules
مسؤولاً عن عزل مكونات شفرة JavaScript في المستعرض. يسمح لك بتوصيل الوحدات النمطية بشكل متزامن وغير متزامن إلى المستعرض. يمكن العثور على مثال لكيفية عمل المكونات مع YModules
و i-bem.js
هنا . اليوم ، بالنسبة لمعظم المطورين ، يقوم webpack
غير المفرج عن الواردات الديناميكية بذلك .
أتاحت مجموعة من منهجية BEM ومحرك القوالب التعريفي وإطار عمل JS باستخدام نظام معياري حل أي مشكلة. ولكن مع مرور الوقت ، أصبحت ديناميات واجهات المستخدم.
أمل جديد
في عام 2013 ، سحرت React المصدر المفتوح. في الواقع ، بدأ Facebook استخدامها مرة أخرى في عام 2011. يقول جيمس لونج في ملاحظاته من مؤتمر JS Conf الأمريكي :
كانت الدورتان الأخيرتان مفاجأة. أعطيت الأولى واحدة من قبل اثنين من مطوري الفيسبوك وأعلنوا الفيسبوك رد الفعل . لم أأخذ الكثير من الملاحظات لأنني شعرت بالصدمة إزاء مدى سوء فكرة أعتقد أنها كذلك. في الأساس ، أنشأوا لغة تسمى JSX والتي تتيح لك تضمين XML في JavaScript لإنشاء واجهات مستخدم تفاعلية مباشرة. XML في جافا سكريبت.
لقد غير React منهج تصميم تطبيقات الويب. لقد أصبح شائعًا لدرجة أنه لا يمكنك اليوم العثور على مطور لم يسمع بـ React. ولكن هناك شيء آخر مهم: أصبحت التطبيقات مختلفة ، لقد حان SPA في حياتنا.
من المقبول عمومًا أن مطوري ياندكس لديهم شعور خاص بالجمال فيما يتعلق بالتكنولوجيا. غريب في بعض الأحيان ، وهو أمر صعب الجدال معه ، ولكن بدون سبب. عندما كان React يكتسب نجومًا على GitHub ، أصر الكثيرون الذين كانوا على دراية بتقنيات Yandex على الويب: فاز Facebook ، وأسقط حرفك وأعد كتابة كل شيء على React قبل فوات الأوان. من المهم أن نفهم شيئين.
أولاً ، لم تكن هناك حرب. الشركات لا تتنافس في إنشاء أفضل إطار على الأرض. إذا بدأت الشركة في قضاء وقت أقل (قراءة الأموال) في مهام البنية الأساسية بنفس الإنتاجية ، فسيستفيد الجميع من ذلك. لا معنى لكتابة الأطر لكتابة الأطر. يقوم أفضل المطورين بإنشاء أدوات تعمل على حل مهام الشركة بأفضل طريقة. الشركات ، الخدمات ، الأهداف - الأمر مختلف. ومن هنا مجموعة متنوعة من الأدوات.
ثانياً ، كنا نبحث عن طريقة لاستخدام React بالطريقة التي نريدها. مع كل الميزات التي قدمتها تقنياتنا الموضحة أعلاه.
من المعتقد على نطاق واسع أن الكود الذي يستخدم React سريع بشكل افتراضي. إذا كنت تعتقد ذلك أيضًا ، فأنت مخطئ تمامًا. الشيء الوحيد الذي يفعله React هو ، في معظم الحالات ، يساعد على التفاعل الأمثل مع DOM.
حتى الإصدار 16 ، كان لدى React عيب قاتل. كان 10 مرات أبطأ من bem-xjst
على الخادم. لم نتمكن من تحمل هذه النفايات. زمن الاستجابة لـ Yandex هو أحد المقاييس الأساسية. تخيل أنك عندما تسأل عن وصفة نبيذ مدروسة ، ستحصل على إجابة أبطأ 10 مرات من المعتاد. لن تكون سعيدًا بالأعذار ، حتى لو كنت تعرف أي شيء عن تطوير الويب. ماذا يمكن أن نقول عن التفسير ، مثل "لكنه أصبح أكثر ملاءمة للمطورين للتواصل مع DOM". أضف هنا نسبة سعر التنفيذ والربح - وأنت نفسك ستتخذ القرار الصحيح الوحيد.
لحسن الحظ للأسف ، فإن المطورين أناس غريبون. إذا لم ينجح شيء ما ، فهذا ليس سببًا لإسقاط كل شيء ...
رأسا على عقب
كنا واثقين من أننا قادرون على هزيمة بطء رد الفعل. لدينا بالفعل محرك قالب سريع. كل ما تحتاجه هو إنشاء HTML على الخادم باستخدام bem-xjst
، وعلى العميل "إجبار" React على قبول هذا الترميز على أنه خاص به. كانت الفكرة بسيطة للغاية لدرجة أن لا شيء ينذر بالفشل.
في الإصدارات التي تصل إلى 15 بما في ذلك ، قام React بالتحقق من صحة العلامات باستخدام مجموع تجزئة - وهي خوارزمية تحول أي تحسين إلى قرع. لإقناع React بصلاحية العلامات ، كان من الضروري وضع معرف لكل عقدة وحساب مجموع التجزئة لكل العقد. كما يعني دعم مجموعة مزدوجة من القوالب: رد فعل للعميل و bem-xjst
للخادم. أوضحت اختبارات السرعة البسيطة مع تثبيت المعرّف أنه لا يوجد أي جدوى من المتابعة.
bem-xjst
bem bem-xjst
هو أداة الاستخفاف بها للغاية. انظر إلى تقرير المشرف الرئيسي على Glory Oliyanchuk وانظر بنفسك. يعتمد bem-xjst
على بنية تسمح لك باستخدام بناء جملة قالب واحد bem-xjst
مختلفة من شجرة المصدر. تشبه إلى حد كبير رد فعل ، أليس كذلك؟ تتيح هذه الميزة اليوم وجود أدوات مثل react-sketchapp
.
خارج النطاق bem-xjst
يحتوي bem-xjst
على نوعين من التحويلات: في HTML وفي JSON. يمكن لأي مطور مجتهد بما فيه الكفاية كتابة محركه الخاص لتحويل القوالب إلى أي شيء. علمنا bem-xjst
تحويل شجرة البيانات إلى سلسلة من المكالمات إلى وظائف HyperScript . مما يعني التوافق التام مع كل من React والتطبيقات الأخرى لخوارزمية DOM الظاهرية ، على سبيل المثال ، Preact .
مقدمة مفصلة لتوليد استدعاء وظيفة HyperScript
نظرًا لأن قوالب React تتطلب التعايش بين التخطيط ومنطق العمل ، فقد اضطررنا إلى جلب المنطق من i-bem.js
إلى i-bem.js
، والتي لم تكن مخصصة لهذا الغرض. بالنسبة لهم كان غير طبيعي. كانوا يسيرون بشكل مختلف. بالمناسبة!
فيما يلي مثال من أعماق الإلتصاق بعوالم مختلفة في وقت تشغيل واحد.
block('select').elem('menu')( def()(function() { const React = require('react'); const Menu = require('../components/menu/menu'); const MenuItem = require('../components/menu-item/menu-item'); const _select = this.ctx._select; const selectComponent = _select._select; return React.createElement.apply(React, [ Menu, { mix: { block : this.block, elem : this.elem }, ref: menu => selectComponent._menu = menu, size: _select.mods.size, disabled: _select.mods.disabled, mode: _select.mods.mode, content: _select.options, checkedItems: _select.bindings.checkedItems, style: _select.bindings.popupMenuWidth, onKeyDown: _select.bindings.onKeyDown, theme: _select.mods.theme, }].concat(_select.options.map(option => React.createElement( MenuItem, { onClick: _select.bindings.onOptionCheck, theme: _select.mods.theme, val: option.value, }, option.content) )) ); }) );
بالطبع ، كان لدينا جمعية خاصة بنا. كما تعلمون ، فإن أسرع عملية هي تسلسل السلسلة. تم بناء محرك bem-xjst
عليه ، وتم بناء التجميع عليه. توجد ملفات الكتل والعناصر والمعدلات في مجلدات ، وكان على التجميع لصق الملفات في التسلسل الصحيح فقط. باستخدام هذا النهج ، يمكنك لصق JS و CSS والقوالب بشكل متوازٍ ، وكذلك الكيانات نفسها. وهذا هو ، إذا كان لديك أربعة مكونات في المشروع ، وأربع نوى على الكمبيوتر المحمول ، وتجميع تكنولوجيا مكون واحد يستغرق ثانية واحدة ، ثم يستغرق بناء المشروع ثانيتين. هنا يجب أن يصبح أكثر وضوحًا كيف يمكننا إدارة الضغط فقط على الشفرة اللازمة في المتصفح.
كل هذا بالنسبة لنا فعل ENB . تلقينا الشجرة النهائية للتوحيد القياسي فقط في وقت التشغيل ، وبما أن التبعية بين المكونات يجب أن تنشأ في وقت مبكر قليلاً من أجل جمع الحزم ، فقد تم الاستيلاء على هذه الوظيفة بواسطة تقنية deps.js
المعروفة. لقد سمح لك بإنشاء رسم بياني للاعتماد بين المكونات ، وبعد ذلك يمكن للمجمع لصق الكود في التسلسل المطلوب ، متجاوزًا الرسم البياني.
توقف رد الفعل الإصدار 16 عن العمل في هذا الاتجاه ، وكانت سرعة تنفيذ القوالب على الخادم متساوية . في مرافق الإنتاج ، أصبح الفرق غير محسوس.
العقدة: v8.4.0
الأطفال: 5 ك
العارض | الوقت يعني | العمليات / ثانية |
---|
preact v8.2.6 | 66.235 مللي ثانية | 15 |
bem-xjst v8.8.4 | 71.326 مللي ثانية | 14 |
رد فعل v16.1.0 | 73.966 مللي ثانية | 14 |
باستخدام الروابط أدناه ، يمكنك استعادة تاريخ النهج:
هل جربنا أي شيء آخر؟

الدافع
في منتصف القصة ، سيكون من المفيد التحدث عن ما حفزنا. كان الأمر يستحق القيام بذلك في البداية ، ولكن - من يتذكر القديم ، هذه العين كهدية. لماذا نحتاج كل هذا؟ ما الذي يمكن لـ BEM أن يجلبه React؟ أسئلة يطرحها الجميع تقريبًا.
التحلل
تصبح وظيفة المكونات أكثر تعقيدًا من سنة إلى أخرى ، ويزيد عدد الاختلافات. يتم التعبير عن ذلك من خلال إنشاء رمز switch
أو switch
، كنتيجة لذلك ، تزداد قاعدة التعليمات البرمجية حتمًا ، ونتيجة لذلك ، يزداد وزن المكون والمشروع باستخدام هذا المكون. الجزء الرئيسي من منطق مكون React موجود في طريقة render()
. لتغيير وظيفة أحد المكونات ، من الضروري إعادة كتابة معظم هذه الطريقة ، مما يؤدي حتماً إلى زيادة هائلة في عدد المكونات عالية التخصص.
يعلم الجميع مكتبات المواد ، واجهة المستخدم ، ومكتبات رد فعل التمهيد . بشكل عام ، جميع المكتبات المعروفة التي تحتوي على مكونات لها نفس العيب. تخيل أن لديك عدة مشاريع وكلها تستخدم نفس المكتبة. أنت تأخذ نفس المكونات ، ولكن في أشكال مختلفة: هنا توجد اختيارات مع خانات اختيار ، لا توجد ، هناك أزرار زرقاء مع أيقونة ، وهناك أزرار حمراء بدونها. سيكون وزن CSS و JS الذي تجلبه المكتبة لك هو نفسه في جميع المشاريع. لكن لماذا؟ يتم تضمين أشكال مختلفة داخل المكون نفسه وتأتي معها ، سواء كنت تريد ذلك أم لا. بالنسبة لنا هذا غير مقبول.
Yandex لديها أيضا مكتبتها الخاصة مع المكونات - ليغو. يتم تطبيقه في ~ 200 الخدمات. هل نريد استخدام Lego في Search لتكلف نفسه لـ Yandex.Health؟ أنت تعرف الجواب.
لدعم منصات متعددة ، غالبًا ما يقومون بإنشاء إصدار منفصل لكل نظام أساسي ، أو إصدار واحد قابل للتكيف.
يتطلب تطوير الإصدارات الفردية موارد إضافية: كلما زاد عدد المنصات ، زاد الجهد. سيؤدي الحفاظ على الحالة المتزامنة لخصائص المنتج في إصدارات مختلفة إلى صعوبات جديدة.
يعمل تطوير نسخة قابلة للتكيف على تعقيد الكود ، وزيادة الوزن ، ويقلل من سرعة المنتج مع الاختلاف المناسب بين المنصات.
هل نريد من الآباء / الأصدقاء / الزملاء / الأطفال استخدام إصدارات سطح المكتب على الهاتف المحمول مع انخفاض سرعة الإنترنت وانخفاض الإنتاجية؟ أنت تعرف الجواب.
التجارب
إذا كنت تقوم بتطوير مشاريع لجمهور كبير ، فعليك التأكد من كل تغيير. تجارب A / B هي إحدى الطرق لاكتساب هذه الثقة.
طرق تنظيم التعليمات البرمجية للتجارب:
- شوكة المشروع وإنشاء مثيلات الخدمة في الإنتاج ؛
- شروط نقطة داخل قاعدة الرمز.
إذا كان المشروع يحتوي على الكثير من التجارب المطولة ، فإن تشفير قاعدة الكود يسبب تكاليف كبيرة. من الضروري مواكبة كل فرع بالتجربة: أخطاء تصحيح المنفذ ووظائف المنتج. Codebase المتفرعة يعقد تجارب متقاطعة عدة مرات.
تعمل شروط النقطة بشكل أكثر مرونة ، ولكنها تعقد قاعدة الشفرة: يمكن أن تؤثر ظروف التجربة على أجزاء مختلفة من المشروع. هناك عدد كبير من الشروط تؤدي إلى انخفاض الأداء عن طريق زيادة مقدار التعليمات البرمجية للمستعرض. من الضروري إزالة الشروط أو جعل الشفرة أساسية أو حذف التجربة الفاشلة تمامًا.
في Search ~ 100 تجربة عبر الإنترنت في مجموعات مختلفة للجماهير المختلفة. يمكنك أن ترى ذلك بنفسك. تذكر ، ربما لاحظت الوظيفة ، وبعد أسبوع اختفت بطريقة سحرية. هل نريد اختبار نظريات المنتج على حساب الحفاظ على مئات فروع قاعدة الشفرة النشطة التي تبلغ 500000 سطر ، والتي يتم تغييرها بواسطة حوالي 60 مطور يوميًا؟ أنت تعرف الجواب.
التغيير العالمي
على سبيل المثال ، يمكنك إنشاء مكون CustomButton
موروثة من Button
من مكتبة. ولكن لن يتم تطبيق CustomButton
الموروثة على جميع المكونات من المكتبة التي تحتوي على Button
. قد تحتوي المكتبة على مكون " Search
إنشاؤه من " Input
Button
. في هذه الحالة ، لا يظهر CustomButton
الموروث داخل مكون Search
. هل نريد أن ندور حول قاعدة الشفرة بأكملها حيث Button
استخدام Button
؟

طريق طويل إلى التكوين
قررنا تغيير الإستراتيجية. في النهج السابق ، أخذوا تقنية Yandex كأساس وحاولوا جعل React تعمل على هذا الأساس. اقترح تكتيكات جديدة عكس ذلك. هذه هي الطريقة التي جاء بها مشروع bem-react-core .
توقف عن ذلك! لماذا تتفاعل على الإطلاق؟
لقد رأينا فيها فرصة للتخلص من العرض الأولي الصريح في HTML ومن الدعم اليدوي لحالة مكون JS لاحقًا في وقت التشغيل - في الواقع ، أصبح من الممكن دمج قوالب BEMHMTL ومكونات JS في تقنية واحدة.
في البداية ، خططنا لنقل جميع أفضل الممارسات والخصائص bem-xjst
إلى المكتبة في أعلى React. أول ما يلفت انتباهك هو التوقيع ، أو إذا كنت تفضل بناء الجملة لوصف المكونات.
ماذا فعلت ، هناك JSX!
تم بناء الإصدار الأول على أساس الوراثة - مكتبة تساعد على تنفيذ الفصول والوراثة. كما يتذكر البعض منكم ، في تلك الأيام ، لم يكن لدى النماذج الأولية في جافا سكريبت دروس ، لم يكن هناك super
. بشكل عام ، لا يزالون غائبين ، وبشكل أكثر دقة ، هذه ليست الطبقات التي تتبادر إلى الذهن أولاً. inherit
كل ما تستطيع الطبقات في ES2015 فعله الآن ، وما يعتبر سحراً أسود: دمج الوراثة والنموذج الأولي بدلًا من إعادة بناء السلسلة ، مما يؤثر إيجابًا على الأداء. لن تكون مخطئًا إذا كنت تعتقد أن الأمر يبدو منطقيًا مثل الوراثة في Node.js ، لكنها تعمل بشكل مختلف.
يوجد أدناه مثال على بناء جملة القوالب bem-react-core@v1.0.0
.
App-Header.js
import { decl } from 'bem-react-core'; export default decl({ block: 'App', elem: 'Header', attrs: { role: 'heading' }, content() { return ' '; } });
App-Header@desktop.js
import { decl } from 'bem-react-core'; export default decl({ block: 'App', elem: 'Header', tag: 'h1', attrs() { return { ...this.__base(...arguments), 'aria-level': 1 }, }, content() { return ` ${this.__base(...arguments)} h1`; } });
App-Header@touch.js
import { decl } from 'bem-react-core'; export default decl({ block: 'App', elem: 'Header', tag: 'h2', content() { return ` ${this.__base(...arguments)} `; } });
index.js
import ReactDomServer from 'react-dom/server'; import AppHeader from 'b:App e:Header'; ReactDomServer.renderToStaticMarkup(<AppHeader />);
output@desktop.html
<h1 class="App-Header" role="heading" aria-level="1">A h1</h2>
output@touch.html
<h2 class="App-Header" role="heading"> </h2>
يمكن العثور على قوالب الجهاز للمكونات الأكثر تعقيدًا هنا .
نظرًا لأن الفصل عبارة عن كائن ، والعمل مع كائنات في JavaScript أكثر ملاءمة ، فإن بناء الجملة مناسب. تم نقل بناء الجملة لاحقًا إلى العقل المدبر bem-xjst
.
كانت المكتبة مستودعًا عالميًا لتعريفات الكائنات - نتائج تنفيذ دالة decl
أو أجزاء من الكيانات: كتلة أو عنصر أو معدِّل. يوفر BEM آلية تسمية فريدة وبالتالي فهو مناسب لإنشاء مفاتيح في قبو. تم لصق مكون التفاعل الناتج في مكان استخدامه. الحيلة هي أن decl
عملية الحل عند استيراد الوحدة. جعل ذلك من الممكن الإشارة إلى أجزاء المكون المطلوبة في كل مكان معين باستخدام قائمة بسيطة من الواردات. ولكن تذكر: المكونات معقدة ، وهناك العديد من الأجزاء ، وقائمة الواردات طويلة ، والمطورين كسول.
استيراد السحر
كما ترون ، في أمثلة التعليمات البرمجية هناك خطوط import AppHeader from 'b:App e:Header'
.
لقد كسرت المعيار! هذا مستحيل! لن ينجح!
أولاً ، لا يعمل معيار الاستيراد بشروط في الروح "يجب أن يكون هناك مسار إلى وحدة نمطية حقيقية في خط الاستيراد". ثانياً ، إنه السكر النحوي الذي تم تحويله باستخدام بابل. ثالثًا ، إنشاء علامات ترقيم import txt from 'raw-loader!./file.txt';
غريبة لـ import txt from 'raw-loader!./file.txt';
webpack import txt from 'raw-loader!./file.txt';
لسبب ما لم يزعج أحدا.
لذلك ، يتم تقديم كتلة لدينا في منصتين: desktop
، touch
.
import Hello from 'b:Hello';
Hello
, applyDecls
, inherit
, React-.
Babel, , . webpack, , .
, :
:
- TypeScript/Flow;
- React- ;
- - ;
- .
bem-react-core@v1.0.0
, .
import { Elem } from 'bem-react-core'; import { Button } from '../Button'; export class AppHeader extends Elem { block = 'App'; elem = 'Header'; tag() { return 'h2'; } content() { return ( <Button> </Button> ); } }
, . , , TypeScript/Flow. , inherit
«» , , .
:
— webpack Babel;
— ;
— , .
HOC , .
import * as React from 'react'; import * as ReactDOM from 'react-dom'; import { Block, Elem, withMods } from 'bem-react-core'; interface IButtonProps { children: string; } interface IModsProps extends IButtonProps { type: 'link' | 'button'; }
, .
withMods
, (), . , , withMods , . . , , , ( ) . . , , — , .
, :
- . , . , TS. , . ES5 TS super , . , TS , .
- . TS ES6 Babel ES5. , npm- . , Babel.
:
- , . , . : DOM-. HOC, . withMods .
- (, , ) . SFC .
- CSS-. CSS- JS- . , , .
v2.
, . . , , 1 2. .
— . CSS- HOC, — dependency injection .
React:
. . React.ComponentType
-. HOC compose .
.
dependency injection, React.ContextAPI
. , , . , . DI — HOC, . . , , .
, , . , , 4 , 1.5Kb
.
. شكرا لأولئك الذين قرأوا حتى النهاية. , React . .