
ما در قسمت قبل پس از نمایش funds با مشکلی روبرو شدیم: برنامه ما اعتبارسنجی نداشت بنابراین می توانستیم بیشتر از چیزی که داریم بفروشیم که خطای بزرگی است! مثلا اگر 10 سهم داشتیم، می توانستیم 400 سهم را بفروشیم! چند خطای دیگر به همین شکل نیز داریم که می توانیم بیشتر از موجودی حساب خود خرید کنیم. مثلا اگر 10 هزار دلار داریم، می توانیم 20 هزار دلار سهم بخریم! مشکل خرید را در همان جلسه قبل حل کردیم اما مشکل فروش هنوز پابرجاست. برای حل این مشکل باید به پوشه portfolio و سپس فایل stock.vue برویم چرا که این کامپوننت مسئول فروش سهام است. در قدم اول باید خصوصیتی computed به نام insufficientQuantity (به معنی تعداد ناکافی) را تعریف کنیم:
<script> import { mapActions } from "vuex"; export default { props: ["stock"], data() { return { quantity: 0 }; }, computed: { insufficientQuantity() { return this.quantity > this.stock.quantity; } }, methods: { // بقیه کدها //
در اینجا this.quantity یعنی مقدار تایپ شده در input (تعداد سهمی که می خواهیم بفروشیم) و this.stock.quantity یعنی تعداد سهمی که داریم (از قبل خریده ایم). خصوصیت insufficientQuantity نیز همین مسئله را به صورت یک مقایسه ساده انجام می دهد که نهایتا یا true و یا false است. مثل جلسه قبل باید این خصوصیت را نیز به عنوان شرط سوم برای دکمه Sell در نظر بگیریم:
<div class="pull-right"> <button class="btn btn-success" @click="sellStock" :disabled="insufficientQuantity || quantity <= 0 || !Number.isInteger(quantity)" >Sell</button> </div>
حالا هر سه شرط باید برقرار باشند تا بتوانیم سهام خود را بفروشیم. البته برای بهتر شدن UX باید متن دکمه را نیز تغییر بدهیم که دقیقا مانند جلسه قبل انجام می شود:
<div class="pull-right"> <button class="btn btn-success" @click="sellStock" :disabled="insufficientQuantity || quantity <= 0 || !Number.isInteger(quantity)" >{{ insufficientQuantity ? 'Low Stocks' : 'Sell' }}</button> </div>
یعنی اگر insufficientQuantity صحیح بود (تعداد سهام هایی که قصد فروششان را داریم بیشتر از تعداد سهام های موجود بود) عبارت Low Stocks (یعنی سهام ناکافی) و در غیر این صورت Sell (یعنی «فروش») نمایش داده می شود. قدم بعدی برای بهتر کردن UX، قرمز کردن input در وضعیت insufficientQuantity است بنابراین مانند جلسه قبل ابتدا کلاسی را در این فایل تعریف می کنیم:
<style scoped> .danger { border: 1px solid red; } </style> <script> import { mapActions } from "vuex"; // بقیه کدها //
سپس بر اساس اینکه insufficientQuantity صحیح یا غلط است، آن را به input خود متصل می نماییم:
<div class="pull-left"> <input type="number" class="form-control" placeholder="Quantity" v-model.number="quantity" :class="{danger: insufficientQuantity }" /> </div>
در حال حاضر اگر به مرورگر بروید، همه چیز باید بدون مشکل کار کند اما باز هم می توانیم قدمی را برای بهتر شدن UX و UI برداریم. در حال حاضر funds به صورت یک عدد خالی نمایش داده می شود (مثلا 10000) اما بهتر است واحد این پول را هم در کنارش بگذاریم. ده هزار دلار؟ ده هزار پوند؟ واحد این عدد باید در کنارش باشد. راه حل های مختلفی برای حل این مشکل وجود دارد اما من می خواهم حتما funds در state را به صورت عددی نگه دارم بنابراین نمی توانیم آن را به صورت رشته در بیاوریم و علامت $ را در کنار آن اضافه کنیم. بهترین راه حل از نظر من استفاده از filter ها است.
اگر یادتان باشد به شما گفتم که filter ها در Vue.js معمولا برای کارهای text formatting (قالب بندی متون) به کار گرفته می شوند و دو راه اصلی برای استفاده از آن ها وجود دارد:
- روشی به نام mustache interpolations (کلمه mustache به معنی سبیل است!) که همان string interpolation است اما دو قسمت دارد که آن را شبیه به یک سبیل می کند!
- استفاده از v-bind که فقط از نسخه 2.1.0 به بعد js پشتیبانی می شود.
نمونه کد استفاده از روش اول به صورت زیر است:
{{ message | capitalize }}
نمونه کد استفاده از روش دوم به صورت زیر است:
<div v-bind:id="rawId | formatId"></div>
همچنین می توانیم فیلترها را به صورت محلی تعریف کنیم:
filters: { capitalize: function (value) { if (!value) return '' value = value.toString() return value.charAt(0).toUpperCase() + value.slice(1) } }
همانطور که می بینید این فیلتر یک مقدار را گرفته، آن را به رشته تبدیل کرده و سپس حرف اول آن را بزرگ می کند (حروف بزرگ انگلیسی). همچنین اگر مقداری داده نشود، یک رشته خالی را return خواهد کرد.
اما اگر بخواهیم آن ها را به صورت سراسری تعریف کنیم باید به فایل main.js برویم:
Vue.filter('capitalize', function (value) { if (!value) return '' value = value.toString() return value.charAt(0).toUpperCase() + value.slice(1) }) new Vue({ // ... })
همانطور که می بینید خوبی فیلترها اینجاست که می توانیم بدون تغییر داده اصلی، آن را به شکل دیگری نمایش بدهیم. در ضمن شما می توانستید برای مقدار funds یک getter دیگر را نیز تعریف کنید که funds را به همراه علامت $ برمی گرداند اما فیلترها کم دردسر تر و ساده تر هستند.
فیلتر ما قرار است علامت $ را در کنار عدد funds نمایش دهد و از طرفی می خواهیم از فیلتر خود در دو کامپوننت جدا استفاده کنیم:
- کامپوننت Home.vue
- کامپوننت Header.vue
بنابراین عاقلانه تر است که فیلتر را به صورت سراسری تعریف کنیم تا اینکه بخواهیم آن را دو بار به صورت محلی در دو کامپوننت مختلف تعریف نماییم. برای این کار به فایل main.js می رویم و می گوییم:
Vue.use(VueRouter); Vue.filter('currency', (value) => { return '$' + value.toLocaleString(); }); const router = new VueRouter({ mode: 'history', routes });
من نام این فیلتر را ‘currency’ گذاشته ام. همانطور که یاد گرفته ایم آرگومان دوم یک تابع است (من از توابع ES6 استفاده کرده ام) که value یا مقدار پاس داده شده را گرفته و مقدار جدید را return می کند. در اینجا علامت $ را به عدد خود چسبانده ام. تابع toLocaleString نیز مسئول نمایش صحیح قیمت برای کاربران مختلف از کشورهای مختلف است. در بعضی از کشور ها برای نمایش قیمت، هر سه رقم سه رقم جدا می کنند اما در بعضی از کشور ها اینطور نیست. این تابع کاری می کند که این مقدار به درستی نمایش داده شود (زمانی که آرگومانی را به آن ندهیم، خودش locale کاربر را تشخیص می دهد). به این مثال توجه کنید:
var totn_number = 123456.789; console.log(totn_number.toLocaleString('en-US')); console.log(totn_number.toLocaleString('en-IN')); console.log(totn_number.toLocaleString('fr-FR'));
کشور اول آمریکا، کشور دوم هند و کشور سوم فرانسه است. خروجی این کد به شکل زیر خواهد بود:
123,456.789 1,23,456.789 123 456,789
این ها فقط نحوه زیبانویسی قیمت هستند بنابراین اهمیت آنچنانی ندارند (ویرگول فقط برای جدا کردن اعداد است تا راحت تر خوانده شوند و مثل علامت اعشار نیست که عدد را تغییر بدهد). حالا که نوشتن فیلتر تمام شده است به header.vue برمی گردیم و می گوییم:
<strong class="navbar-text navbar-right">Funds: {{ funds | currency }}</strong>
همین کار را با home.vue نیز انجام می دهیم:
<p>Your Funds: {{ funds | currency }}</p>
حالا به جای نمایش 1000، مقدار 10,000$ نمایش داده می شود که از نظر ظاهری زیباتر است. حالا همه چیز به خوبی کار می کند.
- نصب و راهاندازی فریمورک 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