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

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

  • فهم قوالب Vue.js
  • الوصول إلى البيانات والتوابع من كائنات Vue.js
  • الربط مع السمات Attributes
  • كتابة شيفرة HTML خام
  • التعامل مع الأحداث Events
  • استخدام الربط ثنائي الاتجاه

نتابع عملنا في هذا الدرس وهو الدرس الثاني من سلسلة دروس تعلّم Vue.js. سنتعلم هذه المرّة كيفية الوصول والتعامل مع DOM، حيث سنتعلّم كيف نستخدم موجّهات Vue.js مختلفة للوصول إلى بيانات كائن Vue.js والتفاعل معها، وسنتوسّع في التعامل مع الأحداث events بالإضافة إلى كيفية استخدام الربط ثنائي الاتجاه مع العناصر.

فهم قوالب Vue.js

تعاملنا في الدرس السابق مع تطبيقات استخدمت مزايا بسيطة من Vue.js، وإذا كنت تذكر أنّنا قد كتبنا شيفرة HTML بسيطة ومن ثمّ استخدمنا الاستبدال النصي '{{ message }}' ، واستخدمنا أيضًا موجّه 'v-on' للاستجابة إلى دخل المستخدم. ما يقوم به Vue.js من وراء الكواليس، هو أخذ نسخة عن شيفرة HTML وحفظها داخليًّا على شكل قالب template، بعد ذلك يتم إجراء عملية تصيير (rendering) على نسخة من القالب السابق، باستخدام الموجّهات وتعابير الاستبدال النصي (في حال وجودها ضمن القالب)، ثمّ بعد الانتهاء من التصيير يتم عرض الخرج النهائي على المستخدم.

الآن، وعندما يُحدَث أي تغيير جديد في قيمة أي حقل مرتبط من كائن Vue.js، ستُجرى عملية تصيير جديدة على نسخة جديدة من القالب السابق المخزّن داخليًّا، ثم يُعرض الخرج النهائي من جديد على المستخدم.

أي كما لو أنّنا أنشأنا ارتباطًا دائمًا بين كائن Vue.js وبين شيفرة HTML. وهذا ما رأيناه فعليًا في التطبيقات البسيطة التي تناولناها في الدرس السابق. ملاحظة من باب التذكير، نستخدم في هذه السلسلة الموقع jsfiddle.net بشكل افتراضي لتشغيل جميع التطبيقات التي نكتبها. ونحتاج بالطبع إلى إدراج ملف إطار العمل Vue.js لكي نستطيع تنفيذ هذه التطبيقات. إذا أردت أن تعرف كيف ذلك، يمكنك العودة إلى الدرس السابق.

الوصول إلى البيانات والتوابع من كائنات Vue.js

انظر إلى المثال التالي (مثل العادة، أول مقطع يمثّل شيفرة HTML وثاني مقطع يمثّل شيفرة JavaScript):

<div id="app">
  {{ title }}
</div>
var app = new Vue({
  el: '#app',
  data: {
    title: 'Hello Vue!'
  }
})

عندما نستخدم الاستبدال النصي '{{ title }}' كما وسبق أن فعلنا مسبقًا، لا نستخدم الكلمة 'this' قبل 'title' كما هو واضح. في الحقيقة أنّ أي كلمة تُشير إلى حقل (مثل 'title') موجودة ضمن حاضنة مزدوجة، سيتم اعتبارها على أنّها حقل ضمن القسم data في كائن Vue.js الموافق. الآن عند تنفيذ التطبيق السابق سيؤدي إلى ظهور الجملة Hello Vue! كما هو متوقّع. وبالمثل أيضًا، يمكننا في الواقع استخدام تابع مثل displayMessage()‎ ليحقّق نفس الخرج السابق تمامًا، وبنفس الأسلوب تقريبًا. استخدم المثال التالي:

<div id="app">
  {{ displayMessage() }}
</div>
var app = new Vue({
  el: '#app',
  data: {
    title: 'Hello Vue!'
  },
  methods:{
               displayMessage: function(){
            return this.title;
    }
  }
})

لاحظ أنّنا استخدمنا هذه المرة التابع displayMessage()‎ ضمن الحاضنة المزدوجة {{ displayMessage()‎ }} ومرّة أخرى لم نستخدم الكلمة this قبل اسم التابع. أي تابع يُكتب بهذه الطريقة سيُعتَبر افتراضيًّا على أنّه تابع موجود ضمن القسم methods من كائن Vue.js. ولكن هذا السلوك الافتراضي لا يسري على شيفرة JavaScript الموجودة ضمن كائن Vue.js حيث يجب استخدام الكلمة this في كلّ مرّة أردنا فيها الوصول إلى أحد أعضاء كائن Vue.js.

الربط مع السمات Attributes

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

<div id="app">
  <p> {{ message }} - <a href='{{link}}'>Hsoub Academy</a>  </p>
</div>
var app = new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue!',
    link: 'https://academy.hsoub.com/'
  }
})

عند تنفيذ التطبيق السابق في jsfiddle.net ستحصل على الخرج التالي:

1.png

لاحظ أنّه خرج منسّق كما هو متوقّع، ولكن إذا جربت النقر على الرابط لن ينقلك إلى موقع أكاديمية حسوب كما هو متوقّع، في الحقيقة سينقلك هذا الرابط إلى صفحة ضمن نفس موقع jsfiddle.net وهذه الصفحة بالطبع ستكون غير موجودة. السبب في ذلك أنّ تقنية الاستبدال النصّي تُعامِل محتويات الحقل link كنص مجرّد، يمكنك ملاحظة الرابط الناتج بعد النقر: https://fiddle.jshell.net/_display/{{title}} الحل لهذه المشكلة بسيط، ويتمثّل في تجنّب استخدام السمة href بهذا الشكل، إنّما ينبغي استخدام الموجّه v-bind مع الوسيط href على النحو التالي:

v-bind:href = 'link'

حيث link هو نفسه الحقل الموجود ضمن كائن Vue.js. استبدل بالتعبير السابق السمة href القديمة الموجودة ضمن شيفرة HTML الموجود في المثال السابق، بعد الاستبدال سيصبح شكل شيفرة HTML على النحو التالي:

<div id="app">
  <p> {{ message }} - <a v-bind:href = 'link'>Hsoub Academy</a>  </p>
</div>

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

كتابة شيفرة HTML خام

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

<div id="app">
  {{ raw }}
</div>
var app = new Vue({
  el: '#app',
  data: {
    raw: '<ul><li>First Item</li><li>Second Item</li><li>Third Item</li></ul>'
  }
})

الهدف من التطبيق السابق هو عرض قائمة غير مرتّبة عن طريق العنصر 'ul' تُظهر ثلاثة عناصر فقط: First Item و Second Item و Third Item. ولكن عند التنفيذ لن تحصل على ما هو متوقع، ستحصل على الخرج التالي:

First Item
Second Item
Third Item

أي أنّك ستحصل على نص عادي دون أن يتعرّف عليه المتصفّح على أنّه شيفرة HTML. يمكن هذه المشكلة بسهولة بإجراء تعديل على شيفرة HTML فقط على النحو التالي:

<div id="app">
  <p v-html='raw'>

  </p>
</div>

التعديل الذي أجريته هو استخدام الموجّه v-html الذي يسمح في حالتنا هذه باستخدام محتويات الحقل raw كشيفرة HTML نظامية وليس مجرّد نص عادي (لاحظ أنّني قد تخلصت من الاستبدال النصّي {{ raw }}. أعد تنفيذ التطبيق، لتحصل على قائمة مُنسّقة بشكل صحيح.

التعامل مع الأحداث (Events)

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

الإنصات إلى أحداث الفأرة

نبدأ بالتعامل مع أحداث الفأرة، لتُنعش ذاكرتك، انظر معي إلى التطبيق البسيط الموجود في الدرس السابق:

<div id="app">
  <input type='text' v-on:input="updateInfo"/>
  {{ message }}
</div>
var app = new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue!'
  },
  methods:{
            updateInfo:function(event){
            this.message = event.target.value;
    }
  }
})

سبق وأن ذكرنا في الدرس السابق أنّه يتم الإنصات إلى أي حدث ضمن عنصر ما باستخدام الموجّهv-on، حيث يتم تغيير الوسيط المُمرّر لهذا الموجّه بتغيّر نوع الحدث المراد الإنصات له. بعد تحديد نوع الوسيط المراد تمريره للموجّه v-on يتم تحديد التابع الذي سيستجيب (سيعالج) هذا الحدث، وهو عبارة عن تابع ضمن القسم methods ضمن كائن Vue.js يتم استدعاؤه عند وقوع الحدث.

بالنسبة للتابع المعالج للحدث (التابع updateInfo في المثال السابق) سيتم توليد كائن يحتوي على معلومات مهمّة حول الحدث الذي وقع، ويتم تمرير هذا الكائن بشكل تلقائي إلى التابع المعالج للحدث.

على العموم، يمكن الاستغناء عن هذا السلوك التلقائي، وتمرير قيمة كيفيّة للتابع المعالج للحدث. انظر معي إلى المثال التالي:

<div id='app'>
  <button v-on:click="increase(2)">Increase!</button>
  <p>{{counter}}</p>
</div> 
var app = new Vue({
  el: '#app',
  data: {
    counter: 0
  },
  methods:{
               increase: function(value){
            this.counter += value;
    }
  }
})

الشيفرة السابقة مألوفة، مع ملاحظتين جديدتين. الأولى أنّنا لم نكتفي بكتابة اسم التابع المعالج للحدث ضمن الموجّه v-on:click فحسب، إنّما قد مرّرنا القيمة 2 كوسيط لهذا التابع على الشكل: increase(2)‎ (لاحظ شيفرة HTML). بالمقابل، إذا تأملت شيفرة JavaScript ضمن تعريف التابع increase في القسم methods، فستلاحظ أنّنا نعامل الوسيط value كمتغيّر يحمل قيمة عددية وليس ككائن يحمل معلومات حول الحدث الذي وقع. أي أنّنا قد استطعنا تغيير السلوك الإفتراضي لعمليّة استدعاء التابع المعالج. بالنسبة للمثال السابق، فكما هو واضح، يعمل التطبيق على زيادة قيمة المتغيّر counter بمقدار القيمة value (في مثالنا السابق ستكون تساوي 2) في كل مرّة يتم فيها نقر الزر.

في بعض الحالات قد نحتاج إلى تمرير كائن الحدث بالإضافة إلى تمرير قيمة كيفيّة بنفس الوقت. تدعم Vue.js هذا الأمر ببساطة من خلال تمرير الكلمة المحجوزة ‎$event إلى التابع المعالج بالإضافة إلى القيمة الكيفية المراد تمريرها. إذا أردنا تطبيق ذلك على المثال الأخير فسيصبح تعريف الزر button على النحو التالي:

<button v-on:click="increase(2, $event)">Increase!</button>

وبالنسبة لتعريف التابع المعالج ضمن القسم methods فسيصبح على النحو التالي:

increase: function(value, event){
            this.counter += value;
    }

أي مجرّد إضافة وسيط آخر.

التعديل على كيفية الاستجابة للأحداث

نحتاج في بعض الأحيان أن نُعدّل على كيفيّة الاستجابة للأحداث، فربما نحتاج في وقت ما إلى إيقاف الاستجابة لحدث ما لأحد العناصر دونًا عن العناصر الأخرى في HTML. لكي أضرب لك مثالًا جميلًا حول هذا الأمر، اسمح لي أولًا أن أقدّم لك حدث حركة الفأرة mousemove. يُولّد هذا الحدث عند مرور مؤشّر الفأرة فوق عنصر ما، ويتم استخدامه كما هو متوقّع مع الموجّه v-on. انظر إلى المثال البسيط التالي:

<div id="app">
  <p v-on:mousemove='updateCoordinates'>
    Mouse cursor at: ({{x}}, {{y}})
  </p>
</div>
var app = new Vue({
  el: '#app',
  data: {
    x:0,
    y:0
  },
  methods:{
      updateCoordinates:function(event){
        this.x = event.clientX;
      this.y = event.clientY;
    }
  }
})

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

2.png

الجديد هنا هو استخدام الموجّه v-on:mousemove حيث أسندنا إليه التابع المعالج updateCoordinates المعرَّف بطبيعة الحال ضمن القسم methods في كائن Vue.js. لاحظ معي أيضًا كيف نحصل على الإحداثيات الحالية لمؤشّر الفأرة (الفاصلة x والتراتيب y) ضمن التابع updateCoordinates:

this.x = event.clientX;
this.y = event.clientY;

الآن إذا أردنا أن ننشئ منطقة "ميتة" (ضمن عنصر span مثلًا) ضمن عنصر p الذي يعرض الإحداثيات، بحيث لايؤدّي مرور مؤشّر الفأرة فوق هذه المنطقة إلى توليد الحدث mousemove، فينبغي علينا عندها التعديل على الحدث mousemove كما يلي (سألوّن التعديلات الإضافية بالأخضر):

<div id="app">
  <p v-on:mousemove='updateCoordinates'>
    Mouse cursor at: ({{x}}, {{y}}) -
    <span v-on:mousemove='uncoveredArea'>Uncovered Area</span>
  </p>
</div>
var app = new Vue({
  el: '#app',
  data: {
    x:0,
    y:0
  },
  methods:{
      updateCoordinates:function(event){
        this.x = event.clientX;
      this.y = event.clientY;
    },
    uncoveredArea: function(event){
        event.stopPropagation();
    }
  }
})

أضفت الموجّه v-on:mousemove إلى العنصر span وأسندت المعالج uncoveredArea له. بالنسبة للتابع uncoveredArea فقد أجريت تعديل على الحدث من خلال استدعاء التابع stopPropagation()‎ من الكائن event. المعنى الحرفي لهذا التابع هو "إيقاف الانتشار" أي أنّنا سنمنع الإستجابة لهذا الحدث عندما يمر مؤشّر الفأرة فوق العنصر span. جرّب تنفيذ التطبيق السابق، ولاحظ التغيير الذي سيحدث عندما يمر مؤشّر الفأرة فوق عنصر span. إذا أردت الإحساس بالفرق، يمكنك أن تحذف التعليمة event.stopPropagation()‎ ثم أعد تنفيذ التطبيق مرّة أخرى، لترى كيف أنّ الإحداثيات ستتغيّر عندما يمر مؤشّر الفأرة فوق عنصر span هذه المرة. يمكن استخدام صيغة أبسط للتعديل على الأحداث، فمن الممكن حذف التابع uncoveredArea بالكامل من قسم methods، والاكتفاء بالقسم الخاص بالموجّه على النحو التالي:

v-on:mousemove.stop=''

أي أنّنا قد استغنينا عن الشيفرة اللازمة لإيقاف انتشار الحدث mousemove. نسمي ‎.stop هنا بمعدِّل الحدث (event modifiers). هناك عدّة معدّلات أحداث مفيدة سنستعرض بعضها منها خلال مسيرتنا في هذه السلسلة.

الإنصات إلى أحداث لوحة المفاتيح

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

v-on:keyup='methodName'

حيث 'methodName' هو اسم التابع المعالج للحدث 'keyup' والذي يجب أن يُوضَع ضمن القسم methods. دعنا الآن نوظّف ذلك في مثال بسيط:

<div id="app">
  <input type='text' v-on:keyup='keyIsUp' />
    <p>
    {{message}}
    </p>

</div>
var app = new Vue({
  el: '#app',
  data: {
    message: ''
  },
  methods: {
    keyIsUp: function(event) {
            this.message = event.target.value;
    }
  }
})

يعمل هذا التطبيق البسيط على تحديث الحقل 'message' كلّما تمّ تحرير مفتاح من لوحة المفاتيح، وبالتالي سيؤدّي ذلك إلى تحديث محتويات عنصر 'p' ضمن الواجهة. ولكن دعنا نتساءل، ماذا لو أردنا أن يستجيب المعالج 'keyIsUp' كلّما حُرِّر مفتاح المسافة (space) فقط، وليس عند أيّ مفتاح يُحرِّره المستخدم. الجواب ببساطة، هو في استخدام معدّل الحدث '.space' بعد 'keyup'. أضف فقط الكلمة '.space' إلى 'keyup' إلى المثال السابق. أي على النحو التالي:

v-on:keyup.space = 'keyIsUp'

أعد تنفيذ التطبيق لترى أنّ محتويات عنصر 'p' أصبحت لا تُحدَّث إلّا بعد تحرير المفتاح space. يوجد بالطبع العديد من المعدّلات التي تمثّل جميع المفاتيح على لوحة المفاتيح، فهناك مثلًا 'enter' و 'tab' و 'up' لمفتاح السهم العلوي، و 'down' لمفتاح السهم السفلي وهكذا. لمعدّلات أحداث لوحة المفاتيح الكثير من الفوائد، يتمثّل أبسطها في إرسال المحتوى الذي أدخله المستخدم بمجرد ضغطه للمفتاح Enter، أو إرسال البيانات مباشرةً بينما يكتبها المستخدم للحصول على مقترحات أثناء عملية الكتابة (كما يفعل محرّك البحث غوغل أثناء كتابة المستخدم للمفردات المراد البحث عنها). وغيرها الكثير من الاستخدامات.

استخدام الربط ثنائي الاتجاه

في معظم الأمثلة السابقة عمدنا إلى استخدام ربط باتجاه واحد، من الشيفرة إلى عنصر HTML. وفي بعض الحالات استطعنا أن نعكس هذا الأمر. أي استطعنا تعديل قيمة الحقل عن طريق الانصات إلى حدث الإدخال v-on:input وبالتالي معالج حدث مخصّص لهذه الغاية. ولكن توجد طريقة مباشرة وسهلة لإيجاد ربط ثنائي الاتجاه فعلي في Vue.js وذلك باستخدام الموجّه v-model وبدون الحاجة إلى معالج حدث، كمال في المثال التالي:

<div id="app">
  <input type='text' v-model='name'/>
  {{ name }}
</div>
var app = new Vue({
  el: '#app',
  data: {
    name: 'Hello Vue!'
  }
})

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

3.png

لاحظ كيف أنّ محتوى مربّع النص قد تمّت تعبئته تلقائيًا بقيمة الحقل name، وبالمثل إذا حاولت الآن كتابة أي شيء ضمن مربّع النص سيتم تعديل قيمة الحقل name فورًا وفقًا له، وبالتالي سيُعدّل محتوى النص الموجود في الطرف الأيمن بسبب وجود الاستبدال النصي {{name}}.

ختامًا

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

تمارين داعمة

تمرين 1

يُطلب في هذا التمرين تطوير تطبيق الآلة الحاسبة البسيط الذي بنيناه في الدرس السابق. بحيث يسمح التطبيق الجديد بإجراء العمليات الحسابية الأربع بدلًا من عملية الجمع الوحيدة التي كان يدعمها التطبيق السابق. أقترح الواجهة التالية للتطبيق:

4.png

لاحظ أنّني قد استخدمت عنصر 'select'، يمكنك استخدام أي طريقة أخرى لاختيار العمليات الحسابية الأربع. من الضروري أن يُوجِد التطبيق الناتج النهائي إذا حدث أحد الأمرين التاليين:

  • تغيير قيمة أحد المعاملين على طرفي العملية الحسابية.
  • تغيير العملية الحسابية عن طريق القائمة المنسدلة.

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

تمرين 2

يُطلب في هذا التمرين إنشاء تطبيق يقدّم للمستخدم مقترحات نصيّة بينما يكتب المستخدم ضمن مربّع نص. سنحاكي عملية الاتصال مع خادوم بعيد عن طريق استخدام مصفوفة نصيّة ضمن الشيفرة. وسأعتبر أنّ المستخدم يحاول أن يُدخل اسم دولة عربية، فتظهر قائمة المقترحات بالأسفل بينما تتم عملية الإدخال. كما في الشكل التالي:

5.png

ستحتاج بالطبع إلى التعامل مع أحداث لوحة المفاتيح. ولكي يكون الأمر أكثر سهولة بالنسبة إليك. يمكنك استخدام المصفوفة الجاهزة التالية كمصدر للبيانات التي يُفترَض أن تكون قادمة من الخادوم:

[
      'السعودية',
      'البحرين',
      'مصر',
      'السودان',
      'ليبيا',
      'الجزائر',
      'المغرب',
      'تونس',
      'موريتانيا',
      'العراق',
      'سوريا',
      'لبنان',
      'قطر',
      'الإمارات',
      'الصومال',
      'جزر القمر',
      'الكويت',
      'سلطنة عُمان',
      'الأردن',
      'اليمن',
      'فلسطين'
    ]

اقرأ أيضًا


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

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

بتاريخ On 11/2/2020 at 12:54 قال Hafsa Aly:

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

you can by looping throught the array and for every element by using one of the fallowing methods : .match or startwith()  or look online for other methods 

and return the element that match the condition to a new array 

بتاريخ On 11/2/2020 at 13:54 قال Hafsa Aly:

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

مرحباً  @Hafsa Aly

من أجل حل التمرين 2 يجب علينا استذكار أننا يجب علينا استخدام

تابع تتبع حدث الكتابة ضمن حقل الادخال الذي تعلمناه في المقال، وهو (اسميناه في حالتنا: (keyIsUp):

v-on:keyup='keyIsUp'

وسنقوم بتعريفه في اقسم الـ methods ، و كما تعلمنا أيضا في المقال، كالتالي:

    keyIsUp: function(event) {

    }

و الان سنقوم باستخدام تابع للبحث ضمن مصفوفة اسماء البلدان التي طلب منا البحث فيها.

لكي نقوم بهذه الخطوة يجب علينا معرفة آلية الحل التي تلخص بالتالي:

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

للقيام بعملية المرور على جميع عناصر المصفوفة لدينا العديد من التوابع في javascript ولكن يمكنك استخدام الأشهر وهو التابع filter

حيث يقوم بالمرور على جميع عناصر مصفوفة ما.

وللتأكد أن عنصراً ما من المصفوفة يحوي النص المدخل أو جزءا منه يمكننا استعمال التابع includes : 

String.includes("substring");

و في حال التأكد أن هذا العنصر من المصفوفة يحوي النص المدخل نقوم بادخال عنصر المصفوفة ضمن مصفوفة أخرى تكون فارغة في البداية.

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

هل يمكنك المحاولة مجدداً باستخدام التوابع المذكورة؟

Yomna Raouf

نشر

بتاريخ On 11/2/2020 at 03:54 قال Hafsa Aly:

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

مرحبًا حفصة.

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

  • أولًا و قبل كل شئ حتى نتمكن من إظهار مقترحات للمستخدم سنحتاج لمعرفة ما هي الحروف أو ما هو النص الذي قام المستخدم بإدخاله، و لتنفيذ ذلك سنجد أننا سنحتاج للإنصات إلى أحداث لوحة المفاتيح "تمامًا كما هو موضح في هذا القسم من المقال" أي أننا سنحتاج معرفة ما يقوم المستخدم بإدخاله حرف بحرف، 
var app = new Vue({
  el: '#app',
  data: {
    userInput: ''
  },
  methods: {
    keyIsUp: function(event) {
            this.userInput = event.target.value;
    }
  },
  template: `
     <div id="app">
      <input type='text' v-on:keyup='keyIsUp' />
        <p>
        {{userInput}}
        </p>
    </div>
  `
})

لاحظي  هنا  كيف سيتم طباعة كل حرف أسفل مربع الإدخال بمجرد أن يقوم بكتابته.

  • ثانيًا الآن و قد قمنا بمعرفة دخل المستخدم سنحتاج لفلترة أو تصفية قائمة الدول بناءً على هذا الدخل و وضع المقترحات في قائمة جديدة نسميها suggestions مثلًا، و للقيام بذلك سنحتاج لندور على جميع عناصر القائمة الخاصة بالدول و التحقق من إذا كان اسم الدولة يحتوي على أحد الأحرف التي أدخلها المستخدم فإذا كان كذلك سنقوم بإضافة الدولة إلى القائمة suggestions، و للقيام بذلك سنقوم باستخدام أحد ال array methods الخاصة بلغة JavaScript و هذه ال method تسمى filter و كما يوضح اسمها هذه الدالة تقوم بعملية فلترة/تصفية/ترشيح أي أنّها تقوم بالدوران على عناصر مصفوفة و تقوم بإعادة العناصر التي ينطبق عليها الشرط الذي نقوم نحن بتحديده فقط، حسنًا و لكن ما هو هذا الشرط في حالتنا؟؟ الشرط هو أن يحتوي اسم الدولة على الحروف التي قام للمستخدم بإدخالها و للقيام بذلك سنحتاج للبحث في اسم الدولة بهذه الحروف و لحسن الحظ JavaScript توفر لنا تابع جاهز أيضًا للقيام بهذا الأمر و هذا التابع يسمى includes "هل يحتوي" فهذا التابع يقوم بالتحقق من وجود حرف ما في السلسة النصية فإذا وجده يعيد القيمة true و إن لم يجده يعيد false. إذًا ما سنقوم به الآن هو الدوران على قائمة الدول و عمل ترشيح لها بناءً على ما يعيده التابع includes فإذا أعاد true سنقوم سنقوم بإضافة الدولة إلى قائمة المقترحات suggestions 
var app = new Vue({
  el: '#app',
  data: {
    userInput: '',
    countries: [
      'السعودية',
      'البحرين',
      'مصر',
      'السودان',
      'ليبيا',
      'الجزائر',
      'المغرب',
      'تونس',
      'موريتانيا',
      'العراق',
      'سوريا',
      'لبنان',
      'قطر',
      'الإمارات',
      'الصومال',
      'جزر القمر',
      'الكويت',
      'سلطنة عُمان',
      'الأردن',
      'اليمن',
      'فلسطين'
    ],
    suggestions: []
  },
  methods: {
    keyIsUp: function (event) {
      this.userInput = event.target.value;
      this.suggestions = this.countries.filter(country => {
        return country.includes(this.userInput);
      })
    }
  },
  template: `
    <div id="app">
    <input type='text' v-on:keyup='keyIsUp' />
      <p>
      {{suggestions}}
      </p>
    </div>
  `
})

لاحظي كيف تتم عملية الترشيح  هنا

  • ثالثًا ما تبقى لنا الآن هو عرض هذه العناصر على هيئة قائمة لتصبح الأكواد النهائية كما يلي:
var app = new Vue({
  el: '#app',
  data: {
    userInput: '',
    countries: [
      'السعودية',
      'البحرين',
      'مصر',
      'السودان',
      'ليبيا',
      'الجزائر',
      'المغرب',
      'تونس',
      'موريتانيا',
      'العراق',
      'سوريا',
      'لبنان',
      'قطر',
      'الإمارات',
      'الصومال',
      'جزر القمر',
      'الكويت',
      'سلطنة عُمان',
      'الأردن',
      'اليمن',
      'فلسطين'
    ],
    suggestions: []
  },
  methods: {
    keyIsUp: function (event) {
      this.userInput = event.target.value;
      this.suggestions = this.countries.filter(country => {
        return country.includes(this.userInput);
      })
    }
  },
  template: `
  <div id="app">
  <input type='text' v-on:keyup='keyIsUp' />
    <ul>
      <li v-for="suggestion in suggestions" :key="suggestion">
        {{ suggestion }}
      </li>
    </ul>
  </div>
  `
})

يمكنك تجربة هذه الأكواد من هنا

أتمنى لك التوفيق.

Mustafa Suleiman

نشر

بتاريخ 16 دقائق مضت قال Eng Mohamed Eid:

ممكن حل التمرين 1

لحل تمرين 1 عليك بإتباع الخطوات التالية:

1- إعداد مشروع Vue.js جديد، أو استخدم مشروع Vue.js موجود بالفعل.

2- في ملف التطبيق الرئيسي، قم بتعريف المتغيرات التالية في كائن الـ "data":

  • operand1 و operand2: تستخدم لتخزين قيمة المعاملين.
  • operation: تستخدم لتخزين العملية الحسابية المحددة.
  • result: تستخدم لتخزين نتيجة العملية الحسابية.

كمثال:

data() {
  return {
    operand1: 0,
    operand2: 0,
    operation: 'addition',
    result: 0
  };
}

3- عليك بإنشاء واجهة المستخدم الخاصة بالتطبيق، حسب شكل التمرين أو الذي تريده أنت، وتستطيع استخدام عنصر <select> لاختيار العملية الحسابية وعناصر <input> لإدخال قيم المعاملين وعنصر <button> لتنفيذ العملية الحسابية.

4- قم بتعريف أسلوب للتحقق من قسمة المعاملين على الصفر وعرض رسالة مناسبة للمستخدم، وبإمكانك الإعتماد على التوجيهات الشرطية مثل v-if و v-show في Vue.js لإظهار أو إخفاء رسالة الخطأ.

5- تعريف الوظيفة التي تُطبق العملية الحسابية المحددة على المعاملين وتحسب النتيجة، وتتوفر التوجيهات الحسابية في Vue.js للقيام بذلك، مثلاً المثال، استخدم الكود التالي لتحقيق الجمع:

methods: {
  calculate() {
    if (this.operation === 'addition') {
      this.result = this.operand1 + this.operand2;
    } else if (this.operation === 'subtraction') {
      this.result = this.operand1 - this.operand2;
    } else if (this.operation === 'multiplication') {
      this.result = this.operand1 * this.operand2;
    } else if (this.operation === 'division') {
      if (this.operand2 === 0) {
        this.result = 'Error: Division by zero!';
      } else {
        this.result = this.operand1 / this.operand2;
      }
    }
  }
}

حيث قمت بتعريف دالة calculate التي تقوم بفحص العملية الحسابية المحددة وتقوم بتطبيقها على المعاملين للحصول على النتيجة. في حالة القسمة،

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

6- توصيل العناصر في واجهة المستخدم ببيانات التطبيق من خلال استخدام التوجيهات اللازمة في Vue.js.

وتستطيع استخدام التوجيهة v-model لربط قيم المعاملين بحقول الإدخال والتوجيهة v-on:change للتحقق من تغيير العملية الحسابية.

كمثال:

<div>
  <input type="number" v-model="operand1">
  <select v-model="operation">
    <option value="addition">+</option>
    <option value="subtraction">-</option>
    <option value="multiplication">*</option>
    <option value="division">/</option>
  </select>
  <input type="number" v-model="operand2">
  <button @click="calculate">Calculate</button>
  <p>Result: {{ result }}</p>
</div>

قمت بربط حقل إدخال operand1 بالمتغير operand1 في البيانات، وكذلك حقل إدخال operand2 بالمتغير operand2.

وأيضًا بربط عنصر select بالمتغير operation. وعند النقر على الزر "Calculate"، ستتم استدعاء وظيفة calculate لتنفيذ العملية الحسابية وحساب النتيجة، والتي ستظهر في العنصر <p>.



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

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

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

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   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.


×
×
  • أضف...