Vue mixins ، الطريقة الصريحة (على سبيل المثال من البرنامج المساعد لمعدلات BEM)


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


الهدف


نود الحصول على مزيج عالمي يمنح أي مكون دعماً يسمى types ويقوم بإخراج مجموعة من فئات CSS تسمى mods baseClass من baseClass .


بالنظر إلى هذه العلامة:


 <SampleComponent :types="['active', 'block']"></SampleComponent> 

نتوقع أن يكون هذا (بافتراض أن baseClass بنا هو sample-component ):


 <div class="sample-component sample-component--active sample-component--block"></div> 

نهج ساذج


من قراءة وثائق Vue فقط ، قد يكون تفكيرك الأول هو مجرد استخدام دمج خاصية مضمن وتوفير mods كخاصية محسوبة في مكون مطلوب.


 // bemMods.js export default (baseClass) => ({ props: { types: { type: Array, default: () => [] } }, computed: { mods() { return this.types.map(type => `${baseClass}--${type}`); } } }) 

 // SampleComponent.vue <template> <div class="sample-component" :class="mods"><slot /></div> </template> 

 import bemMods from 'bemMods.js'; export default { name: 'SampleComponent', mixins: [ bemMods('sample-component') ] } 

هذا النهج يعاني من العديد من المشاكل:


  1. رمز Boilerplate في كل مكون. (على الأقل في نهج Vue)
  2. التبعية على وسيطة baseClass .
  3. لا توجد إشارة واضحة إلى أين أتت خاصية mods .
  4. تضارب الأسماء ممكن بسهولة.

سنحاول حل جميع هذه المشكلات في الخطوة التالية.


Mixin مع تصدير واضح


تتمتع Vue بآلية حقن التبعية ، تسمى Inject \ Prov . يمكن أن يحل مشكلتنا مع السياق الملوث.


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


ثانياً ، يمكننا أيضًا إعادة استخدام اسم المكون الخاص بنا كقاعدة baseClass وعدم تضمين ذلك كخيار مخصص في كل مكون.


وأخيرًا ، سنترك خيارًا لتمرير baseClass كوسيطة دالة في حالة عدم تطابق baseClass الخاص baseClass باسمه.


 // bemMods.js // Converts ComponentName to component-name const transformName = string => string.replace(/\s+/g, '-').toLowerCase(); const install = (Vue, { propName = 'types', modsName = 'mods' } = {}) => { Vue.mixin({ props: { // Prop name is now dynamic and allows to avoid conflits [propName]: { type: Array, default: () => [], } }, // Dependency injection forces us to explicitly require that function provide: { [modsName](baseClass) { baseClass = baseClass || transformName(this.$options.name); return (this[propName] || []).map(type => `${baseClass}--${type}`); } } }); }; export default { install }; 

نحن الآن على استعداد لتسجيل البرنامج المساعد لدينا على مستوى العالم.


 import Vue from 'vue'; import bemMods from 'bemMods.js'; Vue.use(bemMods); 

يمكننا أيضًا تخصيص كيفية استدعاء الدعائم لدينا ، من خلال توفير كائن خيارات.


 import Vue from 'vue'; import bemMods from 'bemMods.js'; Vue.use(bemMods, { propName: 'modifiers', modsName: 'classes' }); 

وإليك كيف يبدو المكون الخاص بنا بعد إعادة هيكلة الخلط:


 <template> <div class="sample-component" :class="mods"><slot /></div> </template> 

 export default { name: 'SampleComponent', // Explicit property inject: ['mods'] } 

دعنا نتخيل أن المكون الخاص بنا ليس له name أو أنه يحتوي على قاعدة مختلفة عن اسمه:


 <template> <div class="special-component" :class="mods('snowflake')"><slot /></div> </template> 

 export default { name: 'SpecialComponent', inject: ['mods'] } 

أو إذا كنا نريد أن نكون مستعدين لعملية إعادة بناء أو إزالة مكون إضافي:


 export default { name: 'SomeComponent', inject: { // If mixin export property changes name it's now possible to replace it in every single component instance withouth any additional rework 'mods': { // In this case 'mods' becomes 'classes' from: 'classes', } } } 

يمكنك أيضًا استخدام Symbol كاسم mods لإزالة تعارضات الأسماء تمامًا ، ولكن هذا يتطلب منك تضمين هذا الرمز في كل مكون ترغب في استخدام bemMods .


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


آمل أن يكون هذا مفيدًا لك وقد وجدت طريقة أفضل لكتابة خلطات Vue.

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


All Articles