استفاده از Namespaceها در VueX

Using Namespaces in VueX

Vue.JS 2: استفاده از namespace ها در VueX - قسمت 99

حالا که در مورد ساختاردهی به فایل store و ماژولار کردن آن صحبت کرده ایم باید به سراغ مشکلی برویم که ممکن است برای همه پیش بیاید: تداخل اسامی. بگذارید برایتان یک مثال بزنم. ما در فایل counter.js کد زیر را داریم:

const getters = {
    doubleCounter: state => {
        return state.counter * 2;
    },
    stringCounter: state => {
        return state.counter + ' Clicks';
    }
};

یعنی یکی از getter های ما doubleCounter نام دارد. حالا اگر به فایل getters.js برویم و نام آن getter را (که الان value است) به doubleCounter تغییر بدهیم چه اتفاقی می افتد؟

export const doubleCounter = state => {
    return state.value;
}

اگر این کد را ذخیره کرده و در مرورگر اجرا کنیم، خطای زیر را در کنسول دریافت می کنیم:

[vuex] duplicate getter key: doubleCounter …

بنابراین اجازه نداریم که چنین کاری را انجام بدهیم. من getter بالا را به نام اصلی خودش (value) برمی گردانم. همیشه یادتان باشد که تمام این getter ها و setter ها و mutation ها و غیره، در یک namespace قرار دارند چرا که در نهایت در فایل store.js در هم ادغام می شوند. برای برنامه های کوچک یا متوسط نیازی به نگرانی نیست و می توانیم برای هر کدام از getter ها و setter ها و غیره یک نام خاص را انتخاب کنیم. برای برنامه های بزرگ تر نیز می توانید این کار را انجام بدهید اما ممکن است آزاردهنده باشد. من می خواهم روشی را به شما معرفی کنم که به شما کمک می کند تا نام های تکراری داشته باشید!

برای این کار وارد پوشه store شوید و در همین پوشه فایلی به نام types.js ایجاد کنید. در این فایل چند constant (ثابت) را تعریف می کنیم که حاوی نام های خاصی هستند. ما از این نام ها بعدا برای متدها و بقیه موارد استفاده خواهیم کرد. به طور مثال:

export const DOUBLE_COUNTER = 'counter/DOUBLE_COUNTER';

نام این ثابت را با حروف بزرگ نوشته ام چرا که نوشتن ثابت های سراسری به صورت capital case (حروف بزرگ) از قرارداد های برنامه نویسی جاوا اسکریپت است. مقداری که به این ثابت داده ام نام کامپوننت مربوط (counter) به علاوه نام خود ثابت است. در ادامه می فهمید که چرا این کار را انجام داده ام. برای click نیز همین کار بالا را انجام می دهم:

export const DOUBLE_COUNTER = 'counter/DOUBLE_COUNTER';
export const CLICK_COUNTER = 'counter/CLICK_COUNTER';

حالا می توانیم به فایل counter.js در پوشه modules رفته و types.js را در آن import کنم:

 import * as types from "../types";

سپس با استفاده از یک قابلیت های ES6 می توانیم نام key های یک شیء را به صورت پویا انتخاب کنیم. برای این کار برای key علامت [] را می گذارید و درون آن نام پویای خود را قرار می دهید. با این حساب می توان گفت:

const getters = {
    [types.DOUBLE_COUNTER]: state => {
        return state.counter * 2;
    },
    [types.CLICK_COUNTER]: state => {
        return state.counter + ' Clicks';
    }
};

توجه کنید که key ها در نهایت رشته خواهند بود و علامت [] در اینجا برای تعریف آرایه نیست. آیا متوجه شدید که دلیل تعریف ثابت ها به صورت رشته های زیر چه بود؟

export const DOUBLE_COUNTER = 'counter/DOUBLE_COUNTER';

در واقع ما نام getter های خود را به صورت counter/DOUBLE_COUNTER انتخاب کرده ایم. این رشته نام جدید getter ما است. دقیقا به همین دلیل است که ساختار آن را به صورت زیر نوشته ایم:

نام getter = نام کامپوننتی که در آن استفاده می شود + نام دلخواه ما برای getter

بدین صورت می فهمیم که هر Getter یا setter یا mutation و غیره در کجا استفاده شده و کارش چیست. در مرحله بعد باید به فایل AnotherResult.vue برویم و نام ها را در این کامپوننت ویرایش کنیم. در حال حاضر نام های موجود در این فایل به شکل زیر هستند:

<template>
  <div>
    <p>Counter is: {{ doubleCounter }}</p>
    <p>Number of Clicks: {{ stringCounter }}</p>
  </div>
</template>

<script>
import { mapGetters } from "vuex";
export default {
  computed: {
    ...mapGetters(["doubleCounter", "stringCounter"])
  }
};
</script>

از آنجایی که ما نام های doubleCounter و stringCounter را تغییر داده ایم، دیگر این getter ها وجود ندارند. بنابراین در اینجا نیز باید types.js را import کنیم:

<template>
  <div>
    <p>Counter is: {{ doubleCounter }}</p>
    <p>Number of Clicks: {{ stringCounter }}</p>
  </div>
</template>

<script>
import { mapGetters } from "vuex";
import * as types from "../store/types";

export default {
  computed: {
    ...mapGetters({
      doubleCounter: types.DOUBLE_COUNTER,
      stringCounter: types.CLICK_COUNTER
    })
  }
};
</script>

از آنجایی که نمی خواهم نام های استفاده شده در قسمت template (یعنی doubleCounter و stringCounter) را تغییر بدهم، به جای پاس دادن یک آرایه به mapGetters، یک شیء را پاس داده ام. با این کار می توانیم خودمان تعیین کنیم که key ها چه مقداری داشته باشند. بنابراین نام های doubleCounter و stringCounter را دوباره انتخاب کرده ام تا کدهایمان کار کنند.

حالا همین کار را با فایل Result.vue انجام داده و کدهایش را به شکل زیر تغییر می دهیم:

<template>
  <p>Counter is: {{ counter }}</p>
</template>

<script>
import { mapGetters } from "vuex";
import * as types from "../store/types";

export default {
  computed: {
    ...mapGetters({
      counter: types.DOUBLE_COUNTER
    })
  }
};
</script>

اگر کدهای بالا را ذخیره کرده و به مرورگر برویم، همه چیز به درستی کار می کند. من می خواهم بقیه فایل ها را نیز به همین شکل ویرایش کنم اما مشکلی وجود دارد. تعیین مقدار key به صورت پویا (ویژگی ES6 که در این جلسه به شما یاد دادم) فقط روی اشیاء کار می کند نه روی const ها بنابراین زمانی که به فایلی مانند actions.js رفتم، مجبور شدم آن را از حالت const خارج کرده و یک شیء default را export کنم:

import * as types from './types';

export default {
    [types.UPDATE_VALUE]: ({commit}, payload) => {
        commit(types.MUTATE_UPDATE_VALUE, payload)
    }
};

طبیعتا با این کار باید به Store.js برویم و دستورات import آن را به شکل زیر تغییر دهیم:

import actions from './actions';
import getters from './getters';
import mutations from './mutations';

یعنی دیگر از حالت import * as X استفاده نمی کنیم. چرا؟ به دلیل اینکه حالا یک شیء برای export default داریم. از آنجایی که این مسائل ساده و بدیهی است، نیازی به توضیح بیشتر نداریم. شما می توانید سورس کد آماده شده (پس از اعمال این تغییرات) را از این لینک دانلود کرده و آن را با کار نهایی خودتان مقایسه کنید.

به عنوان نکته آخر باید بگویم که این روش، روش مشهور برای تعیین namespace است اما در نسخه های جدید تر VueX این قابلیت به صورت خودکار طراحی شده است. مثلا:

  const store = new Vuex.Store({
    modules: {
      foo: {
        namespaced: true,
        // ...
      }
    }
  })

یعنی با اضافه کردن namespaced: true به VueX می گوییم که برای ماژول ها به صورت خودکار namespace تعیین کند. آقای Evan You در این صفحه گیت هاب از این قابلیت خبر داده است. شما می توانید برای مطالعه جزئیات و توضیحات بیشتر، به documentation رسمی و به روز شده VuX مراجعه کنید.

این آخرین قسمت از فصل VueX است. در فصل بعدی وارد پروژه نهایی این سری آموزشی می شویم که در آن با استفاده از Vue.js یک وب سایت ساده را می سازیم. البته بعد از آن فصل، فصل های ضمیمه ای را نیز خواهیم داشت که مربوط به Authentication و غیره هستند.

windows 8.1 pro lizenz kaufen

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

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

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