اعتبارسنجی برای فروش سهام و استفاده از فیلترها

Validation for Stock Sales and the Use of Filters

Vue.JS 2: اعتبارسنجی برای فروش سهام و استفاده از فیلتر ها - قسمت 109

ما در قسمت قبل پس از نمایش 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$ نمایش داده می شود که از نظر ظاهری زیباتر است. حالا همه چیز به خوبی کار می کند.

microsoft project 2019 lizenz kaufen

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

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

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