
در جلسه قبل منطق نسبتا ساده ای را برای logout کردن خودکار کاربران ایجاد کردیم تا پس از منقضی شدن توکن امنیتی، کاربر از حساب کاربری اش بیرون انداخته شود. در این قسمت می خواهیم این کار را برای login انجام بدهیم. مسئله اینجاست که login بودن کاربر در حال حاضر در vuex (مدیریت state) ذخیره می شود و vuex نیز چیزی جز جاوا اسکریپت نیست بنابراین مانند تمام کدهای جاوا اسکریپت دیگر، با refresh شدن صفحه از کار می افتد. با این حساب راه حل ما استفاده از چیزی است که با refresh مرورگر حذف نشود: localStorage. باید در همین ابتدا تاکید کنم که localStorage ربطی به Vue ندارد و یکی از API های ساده خود مرورگر است. بنابراین می توانیم به فایل store.js رفته و در قسمت signup بگوییم:
signup({ commit, dispatch }, authData) { axios .post("/accounts:signUp?key=AIzaSyDtirb936QLEAL9Hbkn1st5c3cF3U7_cFI", { email: authData.email, password: authData.password, returnSecureToken: true }) .then(res => { console.log(res); commit('authUser', { token: res.data.idToken, userId: res.data.localId }); localStorage.setItem('token', res.data.idToken); localStorage.setItem('expiresIn', res.data.expiresIn); dispatch('storeUser', authData); dispatch('setLogoutTimer', res.data.expiresIn); }) .catch(error => console.log(error)); }
همانطور که مشاهده می کنید به راحتی به localStorage دسترسی داریم و می توانیم متد SetItem را روی آن صدا بزنیم. آرگومان اول setItem یک نام برای مقداری است که باید در مرورگر ذخیره شود بنابراین هر نامی را که دوست دارید به صورت یک رشته به آن بدهید (من Token را انتخاب کرده ام). مقدار دیگری که به آن نیاز داریم، expiresIn است و همانطور که در جلسه قبل گفتم 3600 ثانیه می باشد اما کد بالا برای ذخیره آن کاملا غلط است! من در نوشتن کد بالا برای expiresIn از یک خطای منطقی استفاده کرده ام. آیا می توانید آن را تشخیص دهید؟ مشکل اینجاست که expiresIn برابر با 3600 ثانیه است (در زمان نوشتن این مقاله – ممکن است گوگل در آینده آن را تغییر بدهد) بنابراین ما 3600 ثانیه را ذخیره می کنیم و این مقدار در مرورگر تغییر نخواهد کرد، بلکه هر زمان هم که بخواهیم آن را دریافت کنیم، همان مقدار 3600 را دریافت می کنیم. راه حل صحیح بدین صورت است که زمان انقضاء را بر اساس این 3600 ثانیه محاسبه کنیم:
signup({ commit, dispatch }, authData) { axios .post("/accounts:signUp?key=AIzaSyDtirb936QLEAL9Hbkn1st5c3cF3U7_cFI", { email: authData.email, password: authData.password, returnSecureToken: true }) .then(res => { console.log(res); commit('authUser', { token: res.data.idToken, userId: res.data.localId }); const now = new Date(); const expirationDate = new Date(now.getTime() + res.data.expiresIn * 1000); localStorage.setItem('token', res.data.idToken); localStorage.setItem('expirationDate', expirationDate); dispatch('storeUser', authData); dispatch('setLogoutTimer', res.data.expiresIn); }) .catch(error => console.log(error)); }
من در اینجا برای محاسبه تاریخ انقضا به شکل زیر عمل کرده ام:
- در ابتدا با صدا زدن Date بدون آرگومان، تاریخ حال حاضر را دریافت کرده و درون ثابتی به نام now قرار می دهیم.
- سپس now را به علاوه expiresIn (3600 ثانیه) کرده ام اما ما باید کل عبارت را به صورت میلی ثانیه حساب کنیم بنابراین تابع getTime را روی now صدا زده ام که زمان را به صورت میلی ثانیه برمی گرداند و از طرفی expiresIn را نیز در 1000 ضرب کرده ام تا آن هم میلی ثانیه شود. با این کار کل عبارت در واحد میلی ثانیه حساب خواهد شد. سپس با استفاده از Date معادل تاریخ این میلی ثانیه را گرفته ام. توجه کنید که Date تاریخ را برمی گرداند نه میلی ثانیه.
- در نهایت به جای expiresIn از expirationDate به عنوان آرگومان دوم استفاده کرده ام تا در localStorage ذخیره شود.
از آنجایی که ممکن است کد expirationDate کمی گیج کننده باشد آن را به قسمت های مختلف تقسیم کرده و توضیح می دهم. ما در ابتدا باید زمان حال را به علاوه مدت زمان اعتبار توکن امنیتی کنیم تا زمان دقیق انقضای آن را به دست بیاوریم:
const expirationDate = now + res.data.expiresIn;
در حال حاضر مقداری که محاسبه می شود بر اساس میلی ثانیه نیست و باید آن را بر اساس میلی ثانیه محاسبه کنیم. چرا؟ به دلیل اینکه بعدا آن را به date پاس خواهیم داد:
const expirationDate = now.getTime() + res.data.expiresIn * 1000;
حالا مقدار expirationDate بر اساس میلی ثانیه است. در نهایت ما تاریخ را می خواهیم نه میلی ثانیه را چرا که میلی ثانیه عدد بسیار بزرگی است و کار با آن جالب نیست. بنابراین کل این عبارت را به Date می دهیم:
const expirationDate = new Date(now.getTime() + res.data.expiresIn * 1000);
ما می توانیم همین منطق را عینا کپی کرده و در اکشن login قرار بدهیم چرا که در هنگام login نیز باید توکن کاربر را در مرورگر ذخیره کنیم:
login({ commit, dispatch }, authData) { axios .post( "/accounts:signInWithPassword?key=AIzaSyDtirb936QLEAL9Hbkn1st5c3cF3U7_cFI", { email: authData.email, password: authData.password, returnSecureToken: true } ) .then(res => { console.log(res); const now = new Date(); const expirationDate = new Date(now.getTime() + res.data.expiresIn * 1000); localStorage.setItem('token', res.data.idToken); localStorage.setItem('expirationDate', expirationDate); commit('authUser', { token: res.data.idToken, userId: res.data.localId }); dispatch('setLogoutTimer', res.data.expiresIn); }) .catch(error => console.log(error)); }
با این کار کدها را ذخیره کرده و به مرورگر می رویم. به نظر شما کدها کار می کنند؟ برای بررسی این موضوع باید به صفحه login رفته و وارد حساب خود شوید. در آنجا dev tools مرورگر خود را باز کرده (معمولا کلید f12) و به سربرگ Application بروید. از آنجا روی LocalStorage کلیک کرده و URL برنامه خودمان را (http://localhost:8080/) انتخاب می کنیم. سپس در قسمت راست پنجره مقادیر خود را مشاهده می کنیم (البته یک مقدار دیگری هم داریم که متعلق به webpack است و به خاطر npm run dev در حال اجرا است بنابراین با آن کاری نداریم):

بنابراین کدهای ما با موفقیت اجرا می شوند. حالا باید کاری کنیم که هنگام بالا آمدن برنامه، این مقادیر دریافت شده و با استفاده از آن ها login خودکار صورت بگیرد. راه حل شما برای این کار چیست؟
- نصب و راهاندازی فریمورک VueJS
- مثالی قویتر و نصب محلی Vue
- درکی ساده از Tamplateها در Vue
- درک بهتر Directiveها + برخی از Directiveهای مشهور
- تعامل با Event Listenerها
- قدرت Vue با انواع Modifierها
- مبحث two-way-binding و پاسخ به تغییرات
- خصوصیات محاسبهشده (Computed Properties)
- روش جایگزین خصوصیات Computed
- استایلدهی پویا با اشیاء
- استایلدهی پویا اسمی بدون استفاده از کلاسها
- ایجاد شرط با v-if
- نمایش لیستها با v-for
- گردش درون اشیاء
- رهگیری عناصر در v-for
- اولین پروژه تمرینی – آمادهسازی اولیه
- پیادهسازی منطق شروع بازی
- تکمیل دکمه Attack
- کدنویسی متدهای باقیمانده در بازی
- نمایش log و اتمام پروژه
- آشنایی و تعامل بیشتر با شیء Vue
- نحوه مدیریت دادهها در شیء Vue
- استفاده از ref$ در قالبهای HTML
- آشنایی با Mount کردن Templateها
- نحوه بهروزرسانی DOM و چرخه زندگی شیء Vue
- استفاده از Lifecycleها در عمل
- راهاندازی سرور محلی Vue
- آشنایی با Vue CLI
- درک بهتر فایلهای Vue
- آشنایی با کامپوننتها
- ساخت کامپوننتها
- استفاده از کامپوننتها و قوانین آن
- ارتباط بین کامپوننتها با Props
- اعتبارسنجی Props
- رویدادهای شخصیسازیشده
- ارتباط بین کامپوننتهای خواهر و برادر
- استفاده از یک شیء سراسری Vue
- آشنایی با Slotها
- بررسی جزئیات بیشتری از Slotها
- قابلیتی جدید به نام Dynamic Components
- مرگ کامپوننتهای پویا
- فصل جدید و پروژه جدید
- پروژه Quote – پاسدادن دادهها با Prop
- پروژه Quote – تکمیل ثبت Quote
- تکمیل پروژه Quoteها
- فصل جدید، کار با فرمها
- کار با عناصر Textarea
- عناصر Checkbox و Radiobutton
- کار با منوهای آبشاری و جزئیات v-model
- تعریف عناصر شخصیسازیشده
- نگاهی عمیقتر به Directiveها
- ساخت یک Directive شخصی
- ثبت محلی Directiveها + قدمی پیشرفتهتر
- آشنایی با Filterها
- جایگزینی برای Filterها
- آشنایی با Mixinها
- جزئیات تکمیلی در مورد Mixinها
- آشنایی با انیمیشنها در Vue
- استفاده عملی از Transition و Animation
- ترکیب Transition و Animation
- استفاده از کلاسهای CSS مختلف
- تبدیل عناصر مختلف به یکدیگر با انیمیشن
- اعمال انیمیشن با جاوا اسکریپت
- کدنویسی متدهای مربوط به hookهای جاوا اسکریپتی
- تکمیل انیمیشن جاوا اسکریپتی + کامپوننتهای پویا
- ساخت یک لیست برای انیمیشنهای گروهی
- اضافهکردن انیمیشن به لیست ساختهشده
- مینی پروژه فصل – سوالات ریاضی
- تکمیل پروژه و اضافهکردن انیمیشن
- فصل جدید، درخواستهای HTTP
- ارسال اطلاعات به Firebase
- دریافت دادهها از Firebase
- آشنایی با Interceptorها در Vue-Resource
- آشنایی با مفهوم Resource در Vue-Resource
- جزئیات تکمیلی Resourceها
- فصل جدید، آشنایی با Routing
- آشنایی با Routing Modes و اضافهکردن لینکها
- استایلدهی لینک فعال
- ایجاد Navigation با کد و پارامترهای URL
- واکنش به تغییرات URL و پارامترهای آن
- ساخت URLهای پویاتر با Named Routes
- مباحث Query Parameter و Redirection
- مبحث Redirect و اضافهکردن انیمیشن
- پاسدادن # و کنترل عملیات اسکرول
- محافظت از Routeها با استفاده از Gaurdها (قسمت اول)
- محافظت از Routeها با استفاده از Gaurdها (قسمت دوم)
- بارگذاری Routeها به صورت lazy
- فصل جدید، آشنایی با VueX
- نحوهی پیادهسازی اولیهی پکیج VueX
- آشنایی با Getterها در VueX
- اتصال خودکار Getterها به خصوصیات
- حل مشکل ترکیب Getterها و Computed Props
- آشنایی با مبحث Mutation در VueX
- آشنایی با Actionها در Mutations
- درک عملیاتهای پشت صحنه در mapActions
- خلاصهی جلسات قبل + معرفی مشکلی جدید
- اعمال two-way-binding در VueX
- ماژولار کردن مدیریت State در VueX
- استفاده از Namespaceها در VueX
- فصل جدید، پروژهی نهایی دوره
- پیادهسازی Header یا Navigation سایت
- ایجاد ساختار برای قسمت سهام (stocks)
- اضافهکردن منطق دکمهی Buy
- پیادهسازی VueX روی پروژه
- تعریف Mutationهای ماژول Portfolio در VueX
- پیادهسازی Getters برای ماژول Portfolio در VueX
- تکمیل کامپوننت Portfolio و نمایش سهام
- اعتبارسنجی برای فروش سهام و استفاده از فیلترها
- نمایش Funds و اعتبارسنجی برای خرید سهام
- پایان دادن به روز + اضافه کردن انیمیشن به صفحات
- پیادهسازی drop-down و راهاندازی Firebase
- ذخیره و دریافت قیمتها با درخواستهای PUT و GET
- تکمیل دکمهی Load Data و کار با Vue dev Tools
- خروجیگرفتن نهایی از برنامه برای قرارگیری روی سرور
- فصل پیوست ۱: استفاده از axios به جای vue-resource
- فصل پیوست ۱: درخواست GET در axios
- فصل پیوست ۱: استفاده از Interceptorها در Axios
- فصل پیوست ۲: احراز هویت در برنامههای SPA
- فصل پیوست ۲: ساخت کاربر جدید با ایمیل و رمز عبور
- فصل پیوست ۲: دریافت توکن احراز هویت در مرورگر
- فصل پیوست ۲: تکمیل منطق برنامه و کدهای باقیمانده
- فصل پیوست ۲: پیوست توکن به درخواستهای خروجی
- فصل پیوست ۲: بهینهسازی برنامه و Path Guard
- فصل پیوست ۲: اضافهکردن مکانیسم logout از حساب
- فصل پیوست ۲: پیادهسازی logout خودکار از حساب
- فصل پیوست ۲: ذخیرهی دادهها در localStorage
- فصل پیوست ۲: پیادهسازی فرآیند login خودکار
- فصل پیوست ۳: فصل جدید، اعتبارسنجی دادههای کاربر
- فصل پیوست ۳: ارائهی فیدبک اعتبارسنجی در UI
- فصل پیوست ۳: آشنایی با Validatorهای عددی
- فصل پیوست ۳: آشنایی با Validatorهای رمز عبور
- فصل پیوست ۳: آشنایی با requiredUnless
- فصل پیوست ۳: اعتبارسنجی آرایههای پویا
- فصل پیوست ۳: ثبت فرم و اعتبارسنجیهای ناهمگام
- فصل پیوست ۴: نسخهی 3 از Vue CLI
- فصل پیوست ۴: آشنایی با پروژه در CLI جدید
- فصل پیوست ۴: استفاده و کار با پلاگینها در CLI جدید
- فصل پیوست ۴: آشنایی با Environment Variables
- فصل پیوست ۴: خروجی گرفتن از برنامه نهایی
- فصل پیوست ۴: شخصیسازی بیشتر Build
- فصل پیوست ۴: استفاده از GUI