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

بناء تطبيقات ذات صفحة واحدة باستخدام التوجيه Routing في Vue.js


حسام برهان

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

  • بناء هيكل التطبيق والتعرّف على أجزاءه الرئيسية.
  • تحويل التطبيق الموجود في الدرس السابق إلى تطبيق SPA.

سنتعلّم في هذا الدرس كيفية بناء تطبيقات تعتمد على صفحة واحدة فقط (Single Page Applications) أو اختصارًا SPA. توفّر Vue.js هذه الإمكانية من خلال مكتبة اسمها vue-router تسمح بتعريف مسارات داخلية ضمن التطبيق بهدف دعم مفهوم SPA. وتطبيقات SPA هي تطبيقات ويب عادية، لكنّها تختلف عن التطبيقات الكلاسيكية في أنّ الانتقال من صفحة إلى أخرى ضمن الموقع لا يحتاج إلى إعادة تحميل كامل الصفحة بما تحويه من ملفات شيفرة نصية وصور وغيرها من أصول الموقع. فالذي يحدث في تطبيقات SPA هو أنّ جميع الواجهات المفترض وجودها في الموقع ستكون معرّفة مسبقًا ومحمّلة إلى حاسوب المستخدم، فيعمل تطبيق SPA فقط على استبدال واجهة مكان واجهة أخرى دون الحاجة إلى تحميل الصفحة كاملةً من الخادوم.

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

بناء هيكل التطبيق والتعرّف على أجزاءه الرئيسية

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

لنبدأ بإنشاء هيكل التطبيق الجديد بتنفيذ الأمر التالي ضمن موجّه الأوامر:

vue create vue-spa

لكي ننجز مفهوم SPA في تطبيقنا هذا، سنستخدام تقنية التوجيه (Routing) التي عن طريق المكتبة vue-router كما أشرنا قبل قليل. استخدم الأمر التالي لتنصيب المكتبة vue-router:

npm install vue-router

افتح مجلّد التطبيق باستخدام Visual Studio Code ثم احذف الملف HelloWorld.vue. سنحتاج إلى إنشاء مجموعة جديدة من الملفات والمجلّدات من أجل هذا التطبيق. انقر الآن بزر الفأرة الأيمن على المجلّد src واختر New Folder لإنشاء مجلّد جديد سمّه views. سنستخدم هذا المجلّد لتخزين الواجهات المختلفة للتطبيق الخاص بنا. أنشئ ضمن المجلّد views الذي أنشأناه توًّا الملفات التالية: AddUser.vue و EditUser.vue و AllUsers.vue و Home.vue. أنشئ أيضًا الملف routes.js ضمن المجلّد src. الملف routes.js سيحتوي على مسارات العناوين الداخلية التي سنستخدمها ضمن التطبيق.

ستحصل بالنتيجة على البنية التالية من الملفات:

1.png

تحويل التطبيق الموجود في الدرس السابق إلى تطبيق SPA

لكي نبدأ باستخدام التوجيه، يجب أولًا أن نستورد المكتبة vue-router عن طريق عبارة الاستيراد التالية:

import VueRouter from "vue-router";

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

import Vue from "vue"; 
import VueRouter from "vue-router";
import Home from "./views/Home";
import AddUser from "./views/AddUser";
import EditUser from "./views/EditUser";
import AllUsers from "./views/AllUsers";

Vue.use(VueRouter);

const routes = [
  {
    path: "/",
    name: "Home",
    component: Home
  },
  {
    path: "/AddUser",
    name: "AddUser",
    component: AddUser
  },
  {
    path: "/EditUser",
    name: "EditUser",
    component: EditUser
  },
  {
    path: "/AllUsers",
    name: "AllUsers",
    component: AllUsers
  },
];

const router = new VueRouter({
  routes
});

export default router;

أوضحنا قبل قليل، أنّ وظيفة الملف routes.js هي تعريف مسارات العناوين الداخلية التي سنستخدمها ضمن التطبيق. لننظر الآن إلى القسم الخاص بتعليمات الاستيراد:

import Vue from "vue"; 
import VueRouter from "vue-router";
import Home from "./views/Home";
import AddUser from "./views/AddUser";
import EditUser from "./views/EditUser";
import AllUsers from "./views/AllUsers";

أعتقد أنّ أوّل تعليمتين واضحتين. بالنسبة للتعليمات الأربع الأخرى، فهي لاستيراد الواجهات التي سنستخدمها في التطبيق. هذه الواجهات هي بطبيعة الحال مكوّنات (لأنّها موجودة ضمن ملفات تحمل الامتداد vue).

بعد ذلك نُخبر Vue.js أن يستخدم التوجيه من خلال التعليمة التالية:

Vue.use(VueRouter);

وبعد ذلك نصل إلى القسم الخاص بتعريف المسارات:

const routes = [
  {
    path: "/",
    name: "Home",
    component: Home
  },
  {
    path: "/AddUser",
    name: "AddUser",
    component: AddUser
  },
  {
    path: "/EditUser",
    name: "EditUser",
    component: EditUser
  },
  {
    path: "/AllUsers",
    name: "AllUsers",
    component: AllUsers
  },
];

لاحظ معي أننا نضع المسارات التي سنستخدمها في التطبيق ضمن مصفوفة اسمها routes. كل عنصر من هذه المصفوفة عبارة عن كائن له الحقول: path و name و component. انظر مثلًا إلى الكائن الأوّل من هذه المصفوفة:

{
    path: "/",
    name: "Home",
    component: Home
}

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

http://www.yourdomain.com/#/

أمّا اسم هذا المسار فهو Home (من الممكن أن نصل إلى أي مسار من خلال اسمه كما سنرى لاحقًا في هذا الدرس). بالنسبة للواجهة التي سترتبط بهذا المسار فهي Home (انظر إلى تعليمة الاستيراد الخاصة بالواجهة Home.vue).

بالنسبة لباقي المسارات فتعمل بنفس الأسلوب تمامًا، فإذا أخذنا مثلًا المسار الثاني فنجد أنّ المسار الذي يُشير إليه هو ‎/AddUser أي أنّنا نستطيع الوصول إليه عن طريق رابط مماثل لما يلي:

http://www.yourdomain.com/#/AddUser

نأتي إلى القسم التالي في الشيفرة البرمجية السابقة، حيث سنعرّف متغيّر جديد اسمه router ونسند إليه كائن جديد يمثّل الموجّه الذي سيدير عمليّات التوجيه ضمن التطبيق:

const router = new VueRouter({
  routes
});

لاحظ كيف مرّرنا المصفوفة التي عرفنا ضمنها المسارات توًّا إلى VueRouter (وهو معرّف ضمن إحدى تعليمات الاستيراد). وأخيرًا نضع التعليمة المسؤولة عن تصدير الموجّه router خارج هذا الملف.

لننتقل الآن إلى الملف main.js:

import Vue from 'vue'
import App from './App.vue'
import router from './routes.js'
import "bootstrap/dist/css/bootstrap.min.css";
import VueResource from 'vue-resource';
import VueSimpleAlert from "vue-simple-alert";


Vue.config.productionTip = false

Vue.use(VueResource);
Vue.use(VueSimpleAlert);

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

نستورد ضمن هذا الملف المكتبات التي سنحتاجها ضمن التطبيق. أعتقد أنّ أوّل تعليمتي استيراد واضحتين أيضًا. بالنسبة للتعليمة الثالثة، فهنا نستورد الموجّه router التي بنيناه مسبقًا ضمن الملف routes.js، أمّا بالنسبة للتعليمات الثلاث الباقية فهي على الترتيب:

  • استيراد مكتبة Bootstrap للتنسيق.
  • استيراد المكتبة vue-resource للاتصال بالخواديم البعيدة، والتي تعاملنا معها في الدرس السابق.
  • استيراد مكتبة جديدة اسمها vue-simple-alert لم نتعامل معها مسبقًا. والهدف منها عرض رسائل ذات تنسيق جميل للمستخدم، سنتعلّم بعد قليل كيفية التعامل معها.

ستحتاج بالتأكيد إلى تنصيب المكتبة vue-simple-alert بتنفيذ الأمر التالي ضمن موجّه الأوامر:

npm install vue-simple-alert

لاحظ الآن التعليمتين التاليتين:

Vue.use(VueResource);
Vue.use(VueSimpleAlert);

هاتين التعليمتين لإخبار Vue.js أن يستخدم الكائنين: VueResource و VueSimpleAlert. نأتي الآن إلى آخر تعليمة ضمن هذا الملف:

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

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

سنستعرض فيما يلي الملف App.vue بالإضافة إلى ملفات واجهات التطبيق.

الملف App.vue

ستكون محتويات هذا الملف على الشكل التالي:

<template>
  <div id="app">
    <nav id="nav">
      <p class="logo-place">Vue.js Remote Server (Enhanced)</p>
      <ul class="nav-links">
        <li class="links">
          <router-link to="/">Home</router-link>
        </li>
        <li class="links">
          <router-link to="/AddUser">Add User</router-link>
        </li>
        <li class="links">
          <router-link to="/AllUsers">All User</router-link>
        </li>
      </ul>
    </nav>
    <router-view></router-view>
  </div>
</template>

<script>
export default {
  name: "App",
  components: {},
};
</script>

<style>

#nav {
  display: flex;
  margin-bottom: 24px;
}

#nav a {
  font-weight: bold;
  color: #2c3e50;
  text-decoration: none;
  margin-right:12px;
}

#nav a.router-link-active {
  color: #ab26ab;
}

.nav-links {
  padding-right: 20px;
  list-style: none;
  display: flex;
  margin:21px 0 0 0;
}

.links-hover {
  text-decoration: underline;
}

.logo-place {
  font-size: 20px;
  color: purple;
  font-weight: bold;
  margin:16px 0 0 16px;
}
</style>

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

الأمر الآخر هو وجود وسم جديد آخر وهو router-link وهو مكوّن أيضًا ضمن نفس المكتبة. وظيفة هذا المكوّن توليد عنصر ارتباط تشعبي <a> بحيث ينتقل إلى إحدى الواجهات المعرّفة ضمنه. فمثلًا لاحظ معي المكوّن router-link التالي التي أخذته من الشيفرة السابقة:

<router-link to="/AddUser">Add User</router-link>

نجد من المقطع السابق وجود السمة to و هي مسؤولة عن تحديد المسار (Path) الذي سيُوجَّه إليه المستخدم عند نقر هذا الرابط. في المثال السابق سيُوجَّه المستخدم إلى المسار الكامل التالي:

http://www.yourdomain.com/#/AddUser

وذلك بسبب وجود ‎ /AddUser كقيمة للسمة to.

الملف Home.vue

وهو ملف الصفحة الرئيسية في التطبيق وستكون محتوياته على الشكل التالي:

<template>
  <div class="container">
    <div class="row">
      <div class="col-6 offset-2">
        <h1>Welcome in our website!</h1>
      </div>
    </div>

    <div class="row" style="margin-top:30px;">
      <div class="card" style="width: 18rem;">
        <div class="card-body">
          <h5 class="card-title">ِAdd User</h5>
          <p class="card-text">Add a new user to the Firebase experimental website.</p>
          <router-link class="btn btn-primary" to="/AddUser">Add a user</router-link>
        </div>
      </div>

      <div class="card" style="width: 18rem; margin-left:18px;">
        <div class="card-body">
          <h5 class="card-title">All User</h5>
          <p class="card-text">Display all users info from the Firebase experimental website.</p>
          <router-link class="btn btn-primary" to="/AllUsers">Get all users</router-link>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: "Home",
};
</script>

لا يوجد في الشيفرة السابقة أي جديد، سوى أنّك تمتلك الحق في إضافة أصناف تنسيقية إلى المكوّن router-link كما في:

<router-link class="btn btn-primary" to="/AddUser">Add a user</router-link>

ستبدو هذه الواجهة على النحو التالي:

2.png

الملف AddUser.vue

يحتوي هذا الملف على الواجهة المسؤولة عن إضافة مستخدم جديد. انظر معي إلى الشيفرة البرمجية الخاصّة به:

<template>
  <div class="container">
    <div class="row">
      <div class="col-6 offset-2">
        <h1>Add User</h1>
      </div>
    </div>
    <div class="row">
      <div class="col-6 offset-2">
        <div class="container">
          <div class="row">
            <div class="col-12">
              <div class="form-group">
                <label>Username</label>
                <input type="text" class="form-control" v-model="user.username" />
              </div>
              <div class="form-group">
                <label>First name</label>
                <input type="text" class="form-control" v-model="user.firstname" />
              </div>
              <div class="form-group">
                <label>Last name</label>
                <input type="text" class="form-control" v-model="user.lastname" />
              </div>
            </div>
          </div>
        </div>
        <button class="btn btn-primary float-left" style="margin-left:12px;" @click="postUser()">Add</button>
      </div>
    </div>
  </div>
</template>


<script>
export default {
  name: "AddUser",
  methods: {
    postUser() {
      this.$http
        .post("https://vue-remote-servers.firebaseio.com/users.json", this.user)
        .then(
          () => {
            this.user.username = "";
            this.user.firstname = "";
            this.user.lastname = "";

            this.$alert("A new user is added.", "Operation Succeeded", "success");
          },
          (error) => {
            console.log(error);
          }
        );
    },
  },
  data() {
    return {
      user: {
        username: "",
        firstname: "",
        lastname: "",
      },
    };
  },
};
</script>

<style scoped>
.row {
  margin-top: 8px;
}
</style>

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

على أية حال توجد ميزة جديدة استُخدِمت ضمن هذه الواجهة، وهي رسالة ستُعرَض للمستخدم في حال نجاح عملية الإضافة إلى قاعدة بيانات Firebase:

this.$alert("A new user is added.", "Operation Succeeded", "success");

كما كان من الممكن إضافة رسالة شبيهة بالرسالة السابقة في حال فشلت عملية الإضافة للمستخدم (لم أُضف مثل هذه الرسالة إلى الشيفرة السابقة). التابع ‎ $alert موجود ضمن المكتبة vue-simple-alert وظيفته كما هو واضح، هو في عرض رسالة منسّقة للمستخدم. بالنسبة لمثالنا هذا، سنعرض رسالة تُخبر المستخدم بأنّ عملية إضافة بيانات المستخدم إلى قاعدة بيانات Firebase قد تمت بنجاح. يمثّل الوسيط الأوّل للتابع ‎ $alert الرسالة التي نريد عرضها، أما الوسيط الثاني فهو عنوان صندوق الرسالة، أمّا الوسيط الثالث فهو نوع الرسالة وهي في حالتنا هذه success. توجد أنواع أخرى للرسائل التي يمكن للتابع ‎ $alert عرضها مثل success و error. للاطلاع على المزيد من الوثائق المتعلّقة بهذه المكتبة يمكنك زيارة الصفحة الرسمية لها.

ستبدو هذه الواجهة على النحو التالي:

3.png

الملف AllUsers.vue

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

<template>
  <div class="container">
    <div class="row">
      <h2>All Users</h2>
      <button style="margin-left:16px;" class="btn btn-primary" @click="getData()">Retrieve</button>
    </div>
    <hr />
    <div class="row" v-for="usr in users" v-bind:key="usr.username">
      <div class="col-2">{{usr.username}}</div>
      <div class="col-4">{{usr.firstname}} {{usr.lastname}}</div>
      <div class="col-1">
        <router-link :to="{name: 'EditUser', params: {user:usr}}">Edit</router-link>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      user: {
        username: "",
        firstname: "",
        lastname: "",
      },
      users: [],
    };
  },
  methods: {
    getData: function () {
      this.$http
        .get("https://vue-remote-servers.firebaseio.com/users.json")
        .then((response) => {
          return response.json();
        })
        .then((data) => {
          const tmpArray = [];

          for (let key in data) {
            let withId = data[key];
            withId.id = key;
            tmpArray.push(data[key]);
          }

          this.users = tmpArray;
        });
    },
  },
};
</script>

<style scoped>
.row{
    margin-top:8px;
}
</style>

مرة أخرى، لا تختلف الشيفرة البرمجية الموجودة هنا عن تلك التي كانت موجودة في الدرس السابق. فعندما ينتقل المستخدم لهذه الواجهة وينقر على الزر Retrieve، ستُحدّث الواجهة بحيث تعرض جميع المستخدمين المخزنين حاليًا ضمن قاعدة بيانات Firebase. بعد عرض هؤلاء المستخدمين، ستلاحظ وجود رابط اسمه Edit يظهر بجوار كل مستخدم. عند نقر هذا الزر سينقلك التطبيق إلى واجهة تحرير بيانات المستخدم EditUser لإجراء التعديلات المطلوبة عليه.

ولكنّ السؤال هنا، كيف ستتمكّن الواجهة EditUser من معرفة المستخدم المطلوب تحرير بياناته؟ الجواب هو في المكوّن router-link الموجود ضمن هذه الواجهة AllUsers. انظر معي إلى الاستخدام الجديد للمكوّن router-link:

<router-link :to="{name: 'EditUser', params: {user:usr}}">Edit</router-link>

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

{name: 'EditUser', params: {user:usr}}

هذا الكائن لديه مفتاحين. الأول هو name ويمتلك القيمة 'EditUser'، ويمثّل اسم الواجهة التي نريد الانتقال إليها عندما ينقر المستخدم هذا الرابط. لاحظ أنّني قلت "اسم" وليس "مسار"، أي أنّ الاسم الذي نكتبه هنا يحب أن يكون موافقًا للقيمة name التي كانت موجودة ضمن ملف المسارات routes.js عندما عرفنا تلك المسارات إذا كنت تذكر.

بالنسبة للمفتاح الثاني فهو params وهو مسؤول عن تمرير أية وسائط نرغبها إلى الواجهة التي نريد الانتقال إليها. في حالتنا هذه نرغب بتمرير بيانات المستخدم المراد تحريرها بشكل كامل. طريقة التمرير مفيدة للغاية، لاحظ كيف مرّرنا كائن جديد للمفتاح params يحتوي هذا الكائن في حالتنا هذه، على مفتاح وحيد اسمه user ونسند له القيمة usr التي تُعتبر كائنًا مستقلًا بحد ذاته يحتوي على بيانات المستخدم المراد تحرير بياناته. أي أنّ {user:usr} عبارة عن ثنائية تحوي اسم الوسيط user مع القيمة المرتبطة به usr.

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

params: {key1:val1, key2:val2, ...}

ستبدو الواجهة AllUsers على النحو التالي:

4.png

الملف EditUser.vue

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

إليك الشيفرة البرمجية الخاصة بهذا الملف:

<template>
  <div class="container">
    <div class="row">
      <div class="col-6 offset-2">
        <h1>Edit User</h1>
      </div>
    </div>
    <div class="row">
      <div class="col-6 offset-2">
        <div class="container">
          <div class="row">
            <div class="col-12">
              <div class="form-group">
                <label>Username</label>
                <input type="text" class="form-control" v-model="user.username" />
              </div>
              <div class="form-group">
                <label>First name</label>
                <input type="text" class="form-control" v-model="user.firstname" />
              </div>
              <div class="form-group">
                <label>Last name</label>
                <input type="text" class="form-control" v-model="user.lastname" />
              </div>
            </div>
          </div>
        </div>
        <button class="btn btn-primary float-left" style="margin-left:12px;" @click="putUser()">Save</button>
        <button
          class="btn btn-danger float-right"
          style="margin-right:12px;"
          @click="deleteUser()"
        >Delete</button>
      </div>
    </div>
  </div>
</template>


<script>
export default {
  name: "EditUser",
  methods: {
    putUser() {
      this.$http
        .put(
          "https://vue-remote-servers.firebaseio.com/users/" +
            this.$route.params.user.id +
            ".json",
          this.user
        )
        .then(
          () => {
            this.$alert(
              "The user is updated.",
              "Operation Succeeded",
              "success"
            );
          },
          (error) => {
            console.log(error);
          }
        );
    },
    deleteUser() {
      this.$confirm("Are you sure you want to delete the user?").then(() => {
        this.$http
          .delete(
            "https://vue-remote-servers.firebaseio.com/users/" +
              this.$route.params.user.id +
              ".json"
          )
          .then(
            () => {
              this.$router.push('AllUsers');
            },
            (error) => {
              console.log(error);
            }
          );
      });
    },
  },
  computed: {
    user() {
      return this.$route.params.user;
    },
  },
};
</script>

<style scoped>
.row {
  margin-top: 8px;
}
</style>

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

user() {
      return this.$route.params.user;
}

تحتوي هذه الخاصية المحسوبة على تعليمة برمجية واحدة ترُجع الوسيط الذي مرّرناه من الواجهة AllUsers قبل قليل:

this.$route.params.user

الوسيط هو user كما أسميناه ضمن الواجهة AllUsers، يحتوي هذا الوسيط على بيانات المستخدم username و firstname و lastname كما وردت من الواجهة AllUsers. هذا الوسيط موجود ضمن المفتاح params كما هو واضح، والموجود بدوره ضمن الكائن ‎ $route (الموجود ضمن المكتبة vue-router). وبما أنّ الخاصية user محسوبة فإنّ البيانات المستخلصة منها ستُعمّم مباشرة على الحقول الثلاثة الموجودة ضمن الواجهة EditUser كما يلي:

<div class="col-12">
    <div class="form-group">
        <label>Username</label>
        <input type="text" class="form-control" v-model="user.username" />
    </div>
    <div class="form-group">
        <label>First name</label>
        <input type="text" class="form-control" v-model="user.firstname" />
    </div>
    <div class="form-group">
        <label>Last name</label>
        <input type="text" class="form-control" v-model="user.lastname" />
    </div>
</div>

أود أيضًا التحدث عن التابع ‎ $confirm الموجود ضمن المكتبة vue-simple-alert ووظيفته تخييرك بين أمرين. استخدمت التابع ‎ $confirm ضمن التابع deleteUser وذلك لكي نطلب من المستخدم تأكيد أنّه يريد حذف المستخدم الحالي من قاعدة البيانات. انظر الشيفرة البرمجية للتابع deleteUser:

this.$confirm("Are you sure you want to delete the user?").then(() => {
    this.$http
        .delete(
            "https://vue-remote-servers.firebaseio.com/users/" +
            this.$route.params.user.id +
            ".json"
        )
        .then(
            () => {
            this.$router.push('AllUsers');
            },
            (error) => {
            console.log(error);
            }
        );
});

في حال تمت الموافقة على حذف المستخدم الحالي، سيُنفَّذ تابع السهم المُمرّر لتابع then الأوّل. يحتوي تابع السهم هذا على الشيفرة البرمجية التي ستحذف بيانات المستخدم من قاعدة بيانات Firebase وهي مألوفة وتشبه أخواتها من المقاطع البرمجية الأخرى المسؤولة عن التعامل مع قاعدة بيانات Firebase. لاحظ أنّنا ننفّذ تابع then آخر يحتوي على تعليمة برمجيّة أخرى وظيفتها تحويل المستخدم إلى الواجهة AllUsers بعد الانتهاء من حذف المستخدم الحالي.انظر لهذه التعليمة:

 this.$router.push('AllUsers');

هذا هو الأسلوب المتبع للانتقال بين الواجهات بشكل برمجي، وذلك عن طريق استخدام التابع push من الكائن ‎ $router، حيث نمرّر "اسم" الواجهة التي نرغب بالانتقال إليها كوسيط للتابع push.

ختامًا

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

اقرأ أيضًا


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

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

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



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

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

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

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


×
×
  • أضف...