اذهب إلى المحتوى

المرشحات Filters والـمخاليط Mixins في Vue.js


حسام برهان

سنتعلّم في هذا الدرس:

  • المرشّح (Filter).
  • المخلوط (Mixin).

سنتابع عملنا في هذه السلسلة مع ميزتين مفيدتين في Vue.js وهما: المرشّحات (Filters) والمخاليط (Mixins). تُعتبر هاتين الميزتين على بساطتهما من المزايا المتقدّمة نسبيًا في Vue.js. سنوضّح المقصود بكل منهما في هذا الدرس، وذلك بكتابة مثالين تطبيقيين بسيطين، لتوضيح الغاية من استخدام هاتين التقنيتين بشكل جيّد.

المرشّح (Filter)

المرشّح (Filter) هو ميزة مفيدة في Vue.js يمكن من خلالها تطبيق إجراء معيّن على قيمة حقل ما، بحيث يطرأ تعديل على شكله النهائي عند عرضه للمستخدم.

يمكن تعريف المرشّحات التي نرغب بكتابتها ضمن قسم خاص ضمن كائن Vue.js اسمه filters. فالمرشح في الحقيقة عبارة عن مجرّد تابع يقبل وسيطًا واحدًا، ويرجع قيمة بعد التعديل.

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

لنتناول الآن مثالًا برمجيًا يوضّح كيفية كتابة المرشحات. أنشئ مشروعًا جديدًا باستخدام الأمر vue من موجّه الأوامر وسمّه vue-filters كما يلي:

vue create vue-filters

ثم افتح المشروع باستخدام Visual Studio Code. احذف الملف HelloWorld.vue ثم استبدال بما يلي محتويات الملف App.vue:

<template>
  <div id="app">
    <h1>Filters</h1>
    {{text | toUpper}}
  </div>
</template>

<script>
export default {
  data(){
    return {
        text:"We will apply a filter on this field."
    }
  },
  filters:{
    toUpper(value){
      return value.toUpperCase();
    }
  }
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

انظر إلى القسم الجديد filters كيف عرفت المرشّح toUpper ضمنه على شكل تابع يقبل قيمة وحيدة value. لاحظ كيف يُرجع هذا المرشّح حالة الأحرف الكبيرة لهذه القيمة عن طريق تابع جافاسكريبت وهو toUpperCase.

لاحظ معي الآن طريقة تطبيق المرشّح كما هو ظاهر من الشيفرة السابقة. نضع المحرف | بعد اسم الحقل المراد تطبيق المرشّح عليه، ثم نكتب اسم المرشّح. أي كما في التالي:

text | toUpper

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

الأسلوب السابق في تعريف المرشّحات كقسم ضمن كائن Vue.js يُعتبر تعريفًا محليًا (Local). يمكن تعريف المرشّحات بشكل عام (Global) وذلك عن طريق استخدام التابع Vue.filter ضمن الملف main.js على الشكل التالي:

import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false

Vue.filter('toLower', function(value){
  return value.toLowerCase();
})

new Vue({
  render: h => h(App),
}).$mount('#app')

كما هو واضح، يٌمرّر وسيطان إلى التابع filter الأوّل هو اسم المرشّح العام، أمّا الثاني فهو التابع الذي يحتوي على الشيفرة البرمجيّة الخاصة بالمرشّح. المرشّح هنا هو toLower وسنجعله مسؤول عن تحويل الأحرف إلى الحالة الطباعية الصغيرة.

سنعمل الآن على تطبيق المرشّح العام الجديد ضمن الملف App.vue وذلك على المرشّح المحلي القديم على النحو التالي:

{{text | toUpper | toLower}}

لاحظ كيف طبقنا المرشّح الجديد بشكل متسلسل على المرشّح القديم. الذي سيحدث الآن، أنّ محتويات الحقل text سيطبّق عليها المرشّح toUpper أولًا، مما سيعطينا حالة أحرف طباعية كبيرة، ثم سيتم تطبيق المرشّح toLower على النتيجة الأخيرة، مما سيؤدي إلى تحويل حالة الأحرف إلى الحالة الطباعية الصغيرة.

كان يمكن بالطبع تطبيق المرشح toLower فقط دون المرشّح toUpper ولكنني فضلت استخدامها بالشكل المتسلسل السابق لتوضيح إمكانية تطبيق أكثر من مرشّح بنفس الوقت بشكل متسلسل كما فعلنا قبل قليل.

المخلوط (Mixin)

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

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

سنحتاج بالتأكيد إلى مثال عملي يوضّح هذه الفكرة. أنشئ مشروعًا جديدًا وسمّه vue-mixins، ثم افتح المشروع باستخدام Visual Studio Code. احذف الملف HelloWorld.vue، ثم أضف ملفين ضمن المجلّد components، سمّهما على النحو التالي: BMI.vue و ImperialConverter.vue. وأضف أيضًا ملف اسمه ConverterMixin.js إلى المجلّد src.

فكرة هذا التطبيق هي إنشاء مكوّنين الأول هو ImperialConverter يوفر إمكانية التحويل من الكيلوغرام والسنتيمتر إلى الباوند والبوصة على الترتيب. أمّا المكوّن الثاني فهو BMI ووظيفته إعطاء تقرير عن حالة مؤشّر كتلة الجسم (Body Mass Index). يشترك كل من المكونين السابقين بجزء من الشيفرة البرمجية موضوع ضمن المخلوط ConverterMixin. مع العلم أنّ كل من المكونين السابقين مستقلين تمامًا فيما يتعلّق بالبيانات.

يحتوي المخلوط ConverterMixin على الشيفرة البرمجية المسؤولة عن التحويل من الكيلوغرام إلى الباوند، ومن السنتيمتر إلى البوصة. انظر محتويات الملف ConverterMixin.js:

export const ConverterMixin = {
    data() {
        return {
            kg_value: 0,
            cm_value: 0
        };
    },
    computed: {
        to_pounds: function () {
            return this.kg_value * 2.20462;
        },
        to_inches: function () {
            return this.cm_value * 0.393701;
        }
    }
}

الشيفرة البرمجية الموجودة في المخلوط بسيطة جدًا، حيث تحتوي على حقلي بيانات kg_value و cm_value بالإضافة إلى خاصيتين محسوبتين: to_pounds و to_inches.

بالنسبة للمكون ImperialConverter فهو بسيط أيضًا، انظر للشيفرة البرمجية الموجودة ضمنه:

<template>
  <div>
    <h2>Kilograms to Pounds Converter</h2>
    <div>
      <input type="text" style="width:50px;text-align:center;" v-model="kg_value" />
      <span style="margin-left:8px;">Kg = {{to_pounds}} pounds.</span>
    </div>
    <br />
    <div>
      <input type="text" style="width:50px;text-align:center;" v-model="cm_value" />
      <span style="margin-left:8px;">CM = {{to_inches}} Inches.</span>
    </div>
  </div>
</template>

<script>
import { ConverterMixin } from "../ConverterMixin";

export default {
  name: "ImperialConverter",
  mixins: [ConverterMixin],
};
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>

يوفر هذا المكوّن عناصر HTML مناسبة لإدخال البيانات المراد تحويلها وذلك ضمن القسم <template>، أمّا بالنسبة للقسم <script> فنعمل على استيراد المخلوط باستخدام التعليمة import ثم نُخبر Vue.js أنّنا نريد استخدام هذا المخلوط عن طريق القسم mixins. لاحظ أنّه لا توجد شيفرة برمجية فعلية ضمن المكون لأنّه أغلب المنطق الحسابي يحدث ضمن المخلوط في مثالنا البسيط هذا.

أمّا بالنسبة للمكوّن BMI فهو المكوّن المسؤول (كما أشرنا) على حساب مؤشّر كتلة الجسم بالإضافة إلى عرض تقرير بسيط للمستخدم حول القيمة المحسوبة. انظر إلى الشيفرة البرمجية لهذا المكون:

<template>
  <div>
    <h2>Body Mass Index (BMI)</h2>
    <div>
      <div>
        <span>Weight (Kg):</span>
        <input type="text" style="width:50px;text-align:center;" v-model="kg_value" />
      </div>
      <br />
      <div>
        <span>Height (Cm):</span>
        <input type="text" style="width:50px;text-align:center;" v-model="cm_value" />
      </div>
      <br />
      <div>
        <span>BMI value: {{bmi_value}}</span> -
        <span>{{result}}</span>
      </div>
    </div>
  </div>
</template>

<script>
import { ConverterMixin } from "../ConverterMixin";

export default {
  name: "BMI",
  mixins: [ConverterMixin],
  computed: {
    bmi_value: function () {
      return (703 * this.to_pounds) / (this.to_inches * this.to_inches);
    },
    result: function () {
      if (this.bmi_value < 16) {
        return "Severe Thinness";
      } else if (this.bmi_value < 17) {
        return "Moderate Thinness";
      } else if (this.bmi_value < 18.5) {
        return "Mild Thinness";
      } else if (this.bmi_value < 25) {
        return "Normal";
      } else if (this.bmi_value < 30) {
        return "Overweight";
      } else if (this.bmi_value < 35) {
        return "Obese Class I";
      } else if (this.bmi_value < 40) {
        return "Obese Class II";
      } else if (this.bmi_value >= 40) {
        return "Obese Class III";
      } else {
        return "Not defined!";
      }
    },
  },
};
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>

مرة أخرى، يوفّر القسم <template> واجهة المستخدم، أمّا القسم <script> فنستورد عن طريقه المخلوط ConverterMixin ونصرح عن استخدامه كما فعلنا تمامًا مع المكون ImperialConverter قبل قليل. بقي أخيرًا الملف App.vue الذي سنستخدم من خلاله المكونين السابقين. انظر إلى الشيفرة البرمجية لهذا الملف:

<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png">
    <imperial-converter/>
    <BMI/>
  </div>
</template>

<script>
import ImperialConverter from './components/ImperialConverter.vue'
import BMI from './components/BMI.vue'

export default {
  name: 'App',
  components: {
    ImperialConverter,
    BMI
  }
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

بعد تشغيل التطبيق ستحصل على واجهة شبيهة بما يلي:

1.png

ختامًا

تحدثنا في هذا الدرس عن ميزتين جديدتين من مزايا Vue.js، وهما: المرشّحات (Filters) والمخاليط (Mixins)، حيث قد وجدنا أنّ المرشحات هي عبارة عن شيفرات برمجية بسيطة تعمل على إجراء منطق برمجي بسيط وسريع دون الحاجة لاستخدام التوابع أو الخاصيات المحسوبة. أمّا المخاليط فوجدنا أنّها تقنية مفيدة للتخلص من تكرار الشيفرة البرمجية بين المكوّنات المختلفة، حيث يُوضع القسم البرمجي المشترك بين مكوّنين أو أكثر ضمن ملف منفصل دعوناه بالمخلوط، وتعمل المكوّنات المختلفة بعد ذلك على استخدام هذا المخلوط وتتجنّب تكرار الشيفرة البرمجية.

اقرأ أيضًا


تفاعل الأعضاء

أفضل التعليقات

لا توجد أية تعليقات بعد



انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أضف تعليق

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • أضف...