محافظت از Routeها با استفاده از Gaurdها (قسمت دوم)

(Protecting Routes Using Gaurds (Part 2

Vue.JS 2: محافظت از Route ها با استفاده از Gaurd ها (قسمت دوم) - قسمت 86

در جلسه قبل به شما توضیح دادم که gaurd ها برای محافظت از ورود به یا خروج از URL ها و صفحات می باشند. همچنین برایتان توضیح دادم که انواع gaurd ها به چهار بخش تقسیم می شود که سه بخش اول آن مربوط به ورود به URL ها و بخش آخر مربوط به خروج از آن ها است:

  • محافظت قبل از اینکه کاربر وارد URL خاصی شود (آیا او اجازه دارد این مسیر را باز کند؟). این مرحله را می توانیم به سه شکل مختلف اجرا کنیم.
  • محافظت پس از اینکه کاربر وارد URL خاصی شده است (آیا او اجازه ترک این مسیر را دارد؟). این مرحله به یک شکل انجام می شود.

در همان جلسه دو بخش اول را بررسی کردیم که به ترتیب مربوط به متدهای beforeEach (اجرا روی تک تک صفحات - تعریف شده در فایل main.js) و beforeEnter (اجرا روی مسیر های خاص - تعریف شده در routes.js) بود. در این جلسه نوبت به بررسی دو روش نهایی است که یکی از آن ها مربوط به ورودی URL ها و روش بعدی مربوط به خروجی URL ها است.

روش سوم به جای اینکه از main.js یا routes.js استفاده کند، مستقیما روی خود کامپوننت پیاده سازی می شود. من می خواهم مثال جلسه قبل را ادامه دهم بنابراین باید به فایل userDetail.vue برویم و درون شیء Vue از متد خاصی به نام beforeRouteEnter استفاده کنیم:

<script>
export default {
  data() {
    return {
      link: {
        name: "userEdit",
        params: { id: this.$route.params.id },
        query: { locale: "en", q: 100 },
        hash: "#data"
      }
    };
  },
  beforeRouteEnter(to, from, next) {
    if (true) {
      next();
    } else {
      next(false);
    }
  }
};
</script>

باید نکاتی را در رابطه با کد بالا خدمت شما عرض کنم. اول از همه توجه داشته باشید که این متد مانند lifecycle hook ها اجرا می شود بنابراین نباید آن را درون methods قرار دهید. نکته دوم این است که این متد دقیقا مانند متدهای قبلی کار می کند و همان سه آرگومان to و from و next را می گیرد اما تفاوت بسیار مهمی در مورد next وجود دارد: این کامپوننت (UserDetail) ساخته نمی شود مگر بعد از صدا زدن next. آیا می دانید این مسئله به چه معناست؟ این مسئله یعنی در این متد نمی توانید به خصوصیات data دسترسی داشته باشید چرا که اصلا این کامپوننت هنوز ساخته نشده است. مثلا کد زیر غلط است:

  beforeRouteEnter(to, from, next) {
    this.link
    next();
  }

یعنی دسترسی پیدا کردن به خصوصیت link غیر ممکن است. البته اگر واقعا مجبور هستید که به خصوصیات data در این فایل دسترسی داشته باشید، می توانیم یک متد را به عنوان آرگومان به next پاس بدهیم:

  beforeRouteEnter(to, from, next) {
    next(vm => {
      vm.link;
    });
  }

vm مخفف vue model است (یعنی همین instance یا نمونه از کلاس Vue یا به زبان ساده تر همین شیء Vue که در آن هستیم) و یک نام انتخابی است بنابراین لازم نیست حتما آن را vm بگذارید. بقیه کد نیز ساده است. حالا به کد اصلی خودمان برگردیم:

  beforeRouteEnter(to, from, next) {
    if (true) {
      next();
    } else {
      next(false);
    }
  }

من در اینجا یک شرط ساده گذاشته ام که همیشه اجرا می شود (چرا که true را به آن داده ام) بنابراین همیشه next اجرا خواهد شد و کامپوننت ما باز می شود. باز هم می گویم که در برنامه های واقعی باید کد های واقعی خودتان را بنویسید. اگر می خواهید باز نشدن کامپوننت را تست کنید، می توانید این کد را در برنامه خود قرار دهید:

  beforeRouteEnter(to, from, next) {
    if (false) {
      next();
    } else {
      next(false);
    }
  }

حالا اگر به http://localhost:8080/user رفته و روی هر کدام از سه کاربر ما کلیک کنید، هیچ اتفاقی نمی افتد.

محافظت از خروج از URL

حالت نوبت به بررسی خروج کاربر از URL ها است. اگر یادتان باشد یک دکمه ساده را در UserEdit.vue نوشتیم. حالا نوبت تعریف یک متد برای این دکمه است:

<template>
  <div>
    <h3>Edit the User</h3>
    <p>Locale: {{ $route.query.locale }}</p>
    <p>Analytics: {{ $route.query.q }}</p>
    <hr />
    <button class="btn btn-primary" @click="confirmed = true">Confirm</button>
    <div style="height: 700px"></div>
    <p id="data">Some extra Data</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      confirmed: false
    };
  }
};
</script>

همانطور که می بینید من یک listener را برای دکمه خودم در نظر گرفته ام که خصوصیتی به نام confirmed را روی true قرار می دهد. همچنین این خصوصیت را در script تعریف کرده ام. در مرحله بعد باید از متد beforeRouteLeave استفاده کنیم:

beforeRouteLeave(to, from, next) {
  if (this.confirmed) {
    next();
  } else {
    if (confirm("Are you sure?")) {
      next();
    } else {
      next(false);
    }
  }
}

این متد مانند متدهای قبلی سه آرگومان to و from و next را می گیرد اما نکته مهمی در مورد آن وجود دارد: در این متد برخلاف beforeRouteEnter می توانیم به خصوصیات خود در data دسترسی داشته باشیم چرا که در هنگام اجرای این متد، کامپوننت قطعا ساخته شده است (ما در حال بستن این کامپوننت هستیم بنابراین قبلا حتما باز شده است که حالا می خواهد بسته شود). سپس خصوصیت confirmed را که خودمان تعریف کرده بودیم به شرط if پاس داده ام تا اگر true بود next اجرا شده و کامپوننت بسته شود. در غیر این صورت با متد confirm (یک متد جاوا اسکریپتی است و ربطی به Vue ندارد) از کاربر می پرسیم که آیا مطمئن است یا خیر؟ اگر پاسخ او مثبت بود که next را اجرا می کنیم تا کامپوننت بسته شود و در غیر این صورت کامپوننت را نمی بندیم.

معمولا این کار را در صفحات فرم یا صفحات پرداخت بانکی انجام می دهیم تا مطمئن شویم کاربر به اشتباه دستش به دکمه back نخورده باشد و صفحه را تصادفی نبندد.

تمام فصل‌های سری ترتیبی که روکسو برای مطالعه‌ی دروس سری آموزش رایگان Vue js از صفر تا صد توصیه می‌کند:
نویسنده شوید

دیدگاه‌های شما

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.