سلام دوستان. توی هر برنامه‌ای عملکردها (توابع، متغیرها و ...) و ویژگی‌هایی وجود داره که قسمت‌های زیادی وابسته به اونها هستن و ازشون استفاده می‌کنن. مثلا یک متد پرکاربرد به اسم clone داریم که معمولا توی همه جای برنامه استفاده میشه. اگه بخوایم توی چندین کامپوننت از این متد استفاده کنیم، در حالت عادی باید اون رو توی همه‌ی کامپوننت‌ها تکرار کنیم چون کامپوننت‌ها به اجزای هم‌دیگه دسترسی ندارن:

Vue.component('umbrella', {
  methods: {
    clone(obj) {
      return JSON.parse(JSON.stringify(obj));
    }
  }
});

Vue.component('carpet', {
  methods: {
    clone(obj) {
      return JSON.parse(JSON.stringify(obj));
    }
  }
});

همونطور که می‌بینیم مجبور شدیم متد clone رو توی هر دو کامپوننت بطور دقیق تکرار کنیم که این اصلا جالب نیست به ۳ دلیل:

  1. کدهای تکراری داریم می‌نویسیم
  2. حجم کد بالا میره
  3. برای تغییر دادن متد باید هر جایی که تکرار شده رو تغییر بدیم

یک راه بهتر اینه که ویژگی‌های پرکاربرد رو فقط یک جا تعریف کنیم به طوری که بصورت عمومی همه جا در دسترس باشن. این کار توی ویوو با Mixins انجام میشه که امروز اونها رو بررسی می‌کنیم.

 

تعریف کردن Mixin

یک میکسین یک آبجکت ساده هست که اعضای اون دقیقا همون چیزهایی هست که می‌تونیم توی یک کامپوننت تعریف کنیم. مثلا data، methods و ....

ما می‌خوایم متد clone رو بصورت عمومی در دسترس قرار بدیم. ابتدا یک فایل درست می‌کنیم به اسم mixins.js و توی اون یک آبجکت بصورت زیر export می‌کنیم:

export default {
  methods: {
    clone(obj) {
      return JSON.parse(JSON.stringify(obj));
    }
  }
}

خب نوشتن میکسین به همین راحتی بود 😎

حالا باید به کامپوننت‌هایی که اون رو لازم دارن، میکسین رو شناسایی کنیم. برای این کار توی تعریف کامپوننت یک پراپرتی درست می‌کنیم به اسم mixins که یک آرایه هست. توی این آرایه می‌تونیم چندین میکسین اضافه کنیم:

import myMixin from './mixins';

Vue.component('umbrella', {
  mixins: [ myMixin ],
  // ...
});

مرحله شناسایی هم تموم شد. حالا متد clone توی هر کامپوننتی که از اون میکسین استفاده می‌کنه در دسترس هست. روش دسترسی به اعضای میکسین مثل دسترسی به بقیه اعضای کامپوننت هست. حالا می‌تونیم به متد clone خیلی راحت با this دسترسی داشته باشیم:

Vue.component('umbrella', {
  mixins: [ myMixin ],
  data() {
    user: {}
  }
  mounted() {
    const user = this.clone(this.user);
    // ...
  },
  computed: {
    user() {
      return this.clone(this.user);
    }
  }
});

 

فرض کنیم یک میکسین داریم به صورت زیر:

const myMixin = {
  data() {
    return {
      a: 1,
      b: 2,
    }
  }
}

و یک کامپوننت به صورت زیر:

Vue.component('umbrella', {
  mixins: [ myMixin ],
  data() {
    return {
      x: 3,
      y: 4,
    }
  }
});

همونطور که می‌بینیم هم میکسین و هم کامپوننت data دارن. توی چنین شرایطی اعضای data (یا هر آپشن دیگه‌ای مثل methods، computed و ...) با هم دیگه ادغام میشن. یعنی data شبیه به این میشه:

{
  a: 1,
  b: 2,
  x: 3,
  y: 4,
}

 

اگه یک عضو data کامپوننت، اسم مشابه با یک عضو میکسین داشته باشه مثلا هر دو شامل پراپرتی a باشن، مقداری که توی کامپوننت هست اولویت داره و در نظر گرفته میشه:

const myMixin = {
  data() {
    return {
      a: 1,
      b: 2
    }
  }
}

const app = new Vue({
  mixins: [ myMixin ],
  data() {
    return {
      a: 8,
      b: 9
    }
  }
});

app.a; // 8

این قضیه برای آپشن‌هایی مثل methods و components و directives هم وجود داره. برای آپشن‌هایی مثل created() و mounted() و ... قضیه فرق می‌کنه. اگه هم میکسین و هم کامپوننت created() داشته باشن، هر دو اجرا میشن. اول اونی که توی میکسین هست و بعد اونی که توی کامپوننت:

const myMixin = {
  created() {
      alert(1);
  }
}

const app = new Vue({
  mixins: [ myMixin ],
  created() {
      alert(2);
  }
});

توی این مثال هر اولین alert مقدار 1 و دومی مقدار 2 رو به ما نشون میده.

 

میکسین سراسری

توی مثال‌های بالا میکسین‌هایی ساختیم رو باید دستی به هر کامپوننت اضافه می‌کردیم. اگه ویژگی‌هایی داریم که می‌خوایم بصورت خود کار توی همه‌ی کامپوننت‌ها در دسترس باشه باید میکسین رو بصورت سراسری ثبت کنیم. برای این کار از Vue.mixin استفاده می‌کنیم که یک آبجکت می‌گیره به صورت زیر:

Vue.mixin({
  data() {
    return {
      name: 'Jeff'
    }
  }
});

الان چیزایی که توی این میکسین تعریف کردیم توی همه‌ی کامپوننت‌ها و حتی نمونه (new Vue...) قابل دسترسی هست:

Vue.component('run', {
  created() {
    alert(this.name);
  }
});

// ...

const app = new Vue({
  created() {
      alert(this.name);
  }
});

 

خب دوستان این قسمت هم به پایان رسید و امیدوارم استفاده کرده باشید. روزتون خوش 😉 ✌️