021-88881776

آموزش API ترکیبی (Composition API) Vue.js

در این مقاله، به آموزش Vue.js و توضیح مفصل در مورد API ترکیبی (Composition API) Vue.js می‌پردازیم. API ترکیبی یک ویژگی قدرتمند در Vue 3 است که به شما امکان می‌دهد کدهای خود را به شیوه‌ای سازمان‌یافته‌تر و قابل استفاده مجدد بنویسید. این API جدید در مقایسه با API سنتی Vue (Options API) انعطاف‌پذیری بیشتری را برای مدیریت وضعیت و منطق در کامپوننت‌ها فراهم می‌کند.

معرفی API ترکیبی (Composition API) Vue.js

قبل از معرفی API ترکیبی (Composition API) Vue.js، ابتدا باید با Vue.js آشنا شویم. Vue.js یک فریم‌ورک پیشرفته برای ساخت رابط‌های کاربری است که به توسعه‌دهندگان این امکان را می‌دهد تا اپلیکیشن‌های وب واکنش‌گرا بسازند. در Vue 2، برای سازمان‌دهی منطق و وضعیت، از Options API استفاده می‌شد. اما در Vue 3، API ترکیبی (Composition API) معرفی شد تا امکان استفاده از روش‌های جدیدتر برای مدیریت وضعیت و منطق را فراهم کند.

در API ترکیبی (Composition API) Vue.js، به جای تقسیم منطق کد در بخش‌های مختلف (مانند data، methods و computed)، می‌توانید تمام منطق را درون یک تابع به نام setup() قرار دهید. این امکان به شما کمک می‌کند که کد را تمیزتر و قابل استفاده مجددتر کنید.

تابع setup() در API ترکیبی (Composition API) Vue.js

تعریف تابع setup()

تابع setup() یکی از مهم‌ترین ویژگی‌های API ترکیبی (Composition API) Vue.js است. این تابع در زمان ساخت و قبل از رندر کامپوننت، اجرا می‌شود و به شما این امکان را می‌دهد که منطق کامپوننت را به شکلی ساختاریافته و تمیز تعریف کنید. در واقع، این تابع می‌تواند تمام وضعیت‌ها، متغیرها، توابع و حتی هوک‌های چرخه حیات را مدیریت کند.

در Vue 2، منطق کامپوننت‌ها با استفاده از Options API (مثلاً data(), methods, computed) تقسیم‌بندی می‌شد، اما در Vue 3 و با استفاده از Composition API، منطق‌های مختلف درون تابع setup() قرار می‌گیرند. این تغییر ساختاری باعث شده که کدهایی که از چندین ویژگی متفاوت استفاده می‌کنند (مثلاً وضعیت و متدهای مختلف) به راحتی قابل مدیریت و استفاده مجدد باشند.

نحوه عملکرد تابع setup()

زمان اجرا: تابع setup() پیش از رندر شدن کامپوننت و قبل از هرچیز در آن کامپوننت اجرا می‌شود. این به این معنی است که نمی‌توانید از this داخل تابع setup() استفاده کنید، زیرا کامپوننت هنوز ساخته نشده است.
داده‌های واکنش‌گرا: داخل setup() می‌توانید داده‌ها و وضعیت‌های واکنش‌گرا را با استفاده از توابع ref() یا reactive() ایجاد کنید. این داده‌ها پس از هر تغییر خود به خود در UI آپدیت می‌شوند.
بازگشت مقادیر: هر چیزی که داخل setup() تعریف شود، می‌بایست در انتهای تابع بازگشت داده شود تا در قالب (template) یا سایر بخش‌های کامپوننت قابل استفاده باشد.
بدون دسترسی به this: برخلاف Options API که در آن می‌توان از this برای دسترسی به داده‌ها و متدها استفاده کرد، در setup() از this استفاده نمی‌شود و تمام مقادیر به طور مستقیم از طریق بازگشت تابع در دسترس قرار می‌گیرند.

مثالی کامل از تابع setup()

در اینجا یک مثال کامل‌تر از نحوه استفاده از تابع setup() آورده شده است:

<template>
  <div>
    <h1>{{ count }}</h1>
    <button @click="increment">Increase</button>
    <p>{{ doubledCount }}</p>
  </div>
</template>

<script>
import { ref, computed } from 'vue';

export default {
  setup() {
    // وضعیت واکنش‌گرا برای شمارش
    const count = ref(0);

    // تابع برای افزایش شمارش
    const increment = () => {
      count.value++;
    };

    // متغیر محاسبه شده برای دو برابر کردن شمارش
    const doubledCount = computed(() => count.value * 2);

    // بازگشت مقادیر به قالب
    return { count, increment, doubledCount };
  }
};
</script>

 

توضیحات بیشتر در مورد کد مثال:

وضعیت واکنش‌گرا: در اینجا، count با استفاده از ref(0) به عنوان یک وضعیت واکنش‌گرا تعریف شده است. ref به شما امکان می‌دهد که یک مقدار ساده (مانند عدد یا رشته) را به حالت واکنش‌گرا تبدیل کنید. برای دسترسی به مقدار داخل ref، از count.value استفاده می‌کنید.

محاسبات: doubledCount یک متغیر محاسبه‌شده است که با استفاده از تابع computed() تعریف شده است. این ویژگی به طور خودکار مقدار doubledCount را هر بار که مقدار count تغییر می‌کند، به‌روزرسانی می‌کند.

تابع increment: این تابع مسئول تغییر مقدار count است و هر بار که روی دکمه کلیک می‌شود، مقدار count را افزایش می‌دهد.

بازگشت مقادیر: در انتهای تابع setup(), count, increment, و doubledCount به عنوان یک شیء بازگشت داده می‌شوند. این مقادیر سپس در قالب (template) کامپوننت قابل استفاده خواهند بود.

مزایای استفاده از تابع setup()

خوانایی بیشتر: کدهای داخل setup() به وضوح از هم جدا می‌شوند و هر بخش از منطق مربوط به کامپوننت به راحتی قابل تشخیص است. این سازماندهی بهتر باعث می‌شود که کد برای تیم‌های بزرگتر و پروژه‌های پیچیده‌تر آسان‌تر نگهداری و توسعه یابد.

استفاده مجدد از کد: یکی از بزرگ‌ترین مزایای استفاده از API ترکیبی (Composition API) Vue.js این است که می‌توانید منطق‌های مختلف را به صورت مجزا و قابل استفاده مجدد در توابع جداگانه (مثلاً useCounter, useFetch) قرار دهید. این امر از تکرار کد جلوگیری کرده و باعث می‌شود که کدهای شما تمیزتر و مقیاس‌پذیرتر باشند.

افزایش انعطاف‌پذیری: با استفاده از setup(), شما قادر خواهید بود منطق‌های مختلف را به شکلی بسیار انعطاف‌پذیرتر پیاده‌سازی کنید. مثلاً می‌توانید داده‌ها و توابع را به راحتی از یک کامپوننت به کامپوننت‌های دیگر منتقل کرده و آن‌ها را با استفاده از ترکیب provide() و inject() یا استفاده مجدد از توابع و هسته‌های مشترک، مدیریت کنید.

دسترس‌پذیری داده‌ها: تمامی متغیرها و توابع که در setup() تعریف می‌شوند، به صورت واضح و مستقیم در قالب قابل دسترس هستند و دیگر نیازی به استفاده از this ندارید.

تابع setup() در API ترکیبی (Composition API) Vue.js، ابزار قدرتمندی برای سازمان‌دهی منطق و مدیریت وضعیت کامپوننت‌ها به شکلی تمیز و مقیاس‌پذیر است. این تغییر ساختاری در Vue 3، باعث می‌شود که کد شما نه تنها ساده‌تر و خواناتر باشد، بلکه قابلیت استفاده مجدد و مقیاس‌پذیری بیشتری پیدا کند.

اگر به دنبال ساخت اپلیکیشن‌های پیچیده‌تر و مقیاس‌پذیرتر با Vue.js هستید، استفاده از تابع setup() یکی از بهترین روش‌هاست.

استفاده از وضعیت واکنش‌گرا در API ترکیبی (Composition API) Vue.js

در API ترکیبی (Composition API) Vue.js، مدیریت وضعیت واکنش‌گرا یکی از ویژگی‌های اساسی است که به شما امکان می‌دهد داده‌های کامپوننت‌ها را به گونه‌ای مدیریت کنید که هر تغییر در آن‌ها باعث بروزرسانی خودکار رابط کاربری (UI) شود. این ویژگی با استفاده از توابع ref() و reactive() در Vue.js قابل پیاده‌سازی است. استفاده از وضعیت‌های واکنش‌گرا به شما این امکان را می‌دهد که داده‌ها را با کمترین پیچیدگی به شکلی منظم و مقیاس‌پذیر مدیریت کنید.

تعریف وضعیت واکنش‌گرا

در Vue.js، هر زمان که یک وضعیت واکنش‌گرا تغییر کند، خودکار تمام اجزای وابسته به آن به‌روزرسانی می‌شوند. این یعنی وقتی شما یک داده را تغییر می‌دهید، Vue این تغییر را شناسایی کرده و قسمت‌هایی از رابط کاربری که به آن داده وابسته‌اند را دوباره رندر می‌کند.

تفاوت بین ref() و reactive()

در Vue 3، دو روش اصلی برای ایجاد وضعیت‌های واکنش‌گرا وجود دارد: ref() و reactive().

ref():
ref() برای ایجاد وضعیت‌های ساده (مانند اعداد، رشته‌ها و سایر مقادیر ابتدایی) استفاده می‌شود. این تابع یک شیء باز می‌گرداند که در آن داده اصلی تحت ویژگی .value قرار می‌گیرد.
برای مثال، اگر شما یک عدد یا رشته را می‌خواهید که واکنش‌گرا باشد، از ref() استفاده می‌کنید.

مثال از ref():

<template>
  <div>
    <h1>{{ count }}</h1>
    <button @click="increment">Increase</button>
  </div>
</template>

<script>
import { ref } from 'vue';

export default {
  setup() {
    const count = ref(0);

    const increment = () => {
      count.value++;
    };

    return { count, increment };
  }
};
</script>

در این مثال، count یک عدد ساده است که به صورت واکنش‌گرا با استفاده از ref(0) تعریف شده است. توجه کنید که برای دسترسی به مقدار واقعی count، باید از count.value استفاده کنید.

reactive():

reactive() برای ایجاد وضعیت‌های پیچیده‌تر، مانند آرایه‌ها یا شیء‌ها، استفاده می‌شود. این تابع یک شیء یا آرایه را به یک وضعیت واکنش‌گرا تبدیل می‌کند.
برخلاف ref() که باید مقدار آن را با استفاده از .value دسترسی داشته باشیم، داده‌های برگشتی از reactive() به صورت مستقیم قابل دسترسی هستند.

مثال از reactive():

<template>
  <div>
    <h1>{{ user.name }}</h1>
    <button @click="updateName">Change Name</button>
  </div>
</template>

<script>
import { reactive } from 'vue';

export default {
  setup() {
    const user = reactive({ name: 'John' });

    const updateName = () => {
      user.name = 'Jane';
    };

    return { user, updateName };
  }
};
</script>

در این مثال، user یک شیء است که به وسیله reactive() واکنش‌گرا شده است. توجه کنید که برای تغییر و دسترسی به ویژگی‌های شیء user، نیازی به استفاده از .value نیست و می‌توان به طور مستقیم از user.name استفاده کرد.

استفاده از وضعیت‌های واکنش‌گرا در پروژه‌ها

حالت ساده (استفاده از ref())

هنگامی که شما یک وضعیت ساده مانند شمارنده یا یک رشته دارید، بهترین روش استفاده از ref() است. این روش برای مواردی که شما فقط یک مقدار واحد را نیاز دارید بسیار مفید است.

مثال: شمارشگر ساده با ref():

<template>
  <div>
    <h1>{{ count }}</h1>
    <button @click="increment">Increase</button>
  </div>
</template>

<script>
import { ref } from 'vue';

export default {
  setup() {
    const count = ref(0);

    const increment = () => {
      count.value++;
    };

    return { count, increment };
  }
};
</script>

در این مثال، شمارشگر هر بار که کاربر روی دکمه کلیک می‌کند، مقدار خود را افزایش می‌دهد. با استفاده از ref(), وضعیت count واکنش‌گرا می‌شود و با هر تغییر، UI به‌طور خودکار به‌روزرسانی می‌شود.

حالت پیچیده‌تر (استفاده از reactive())

وقتی که نیاز به مدیریت وضعیت‌های پیچیده‌تری مانند آرایه‌ها یا اشیاء دارید، reactive() بهترین انتخاب است. این حالت به شما این امکان را می‌دهد که تمام ویژگی‌های شیء یا آرایه را به طور واکنش‌گرا مدیریت کنید.

مثال: مدیریت وضعیت یک شیء با reactive():

<template>
  <div>
    <h1>{{ user.name }}</h1>
    <button @click="updateName">Change Name</button>
  </div>
</template>

<script>
import { reactive } from 'vue';

export default {
  setup() {
    const user = reactive({ name: 'John' });

    const updateName = () => {
      user.name = 'Jane';
    };

    return { user, updateName };
  }
};
</script>

در این مثال، شیء user به صورت واکنش‌گرا تعریف شده است و به محض تغییر مقدار user.name، Vue UI را به‌روزرسانی می‌کند.

ترکیب ref() و reactive()

در بسیاری از پروژه‌ها، ممکن است لازم باشد که از هر دو روش ref() و reactive() به طور همزمان استفاده کنید. به عنوان مثال، می‌توانید از ref() برای مقادیر ساده و از reactive() برای شیء‌های پیچیده‌تر استفاده کنید.

مثال از ترکیب ref() و reactive():

<template>
  <div>
    <h1>{{ user.name }}</h1>
    <p>{{ user.age }}</p>
    <button @click="updateName">Change Name</button>
    <button @click="incrementAge">Increase Age</button>
  </div>
</template>

<script>
import { ref, reactive } from 'vue';

export default {
  setup() {
    const user = reactive({ name: 'John', age: 30 });
    const count = ref(0);

    const updateName = () => {
      user.name = 'Jane';
    };

    const incrementAge = () => {
      user.age++;
    };

    return { user, count, updateName, incrementAge };
  }
};
</script>

در این مثال، user یک شیء است که با reactive() واکنش‌گرا شده و count یک عدد است که با ref() مدیریت می‌شود. این ترکیب می‌تواند در پروژه‌هایی که نیاز به مدیریت انواع مختلف وضعیت‌ها دارند، بسیار مفید باشد.
استفاده از وضعیت واکنش‌گرا در API ترکیبی (Composition API) Vue.js باعث می‌شود که مدیریت داده‌ها در کامپوننت‌ها ساده‌تر، مقیاس‌پذیرتر و قابل نگهداری‌تر باشد. تفاوت‌های اصلی بین ref() و reactive() به شما این امکان را می‌دهد که بسته به نیاز خود از هر یک استفاده کنید. اگر وضعیت ساده دارید، ref() بهترین انتخاب است، اما اگر با وضعیت‌های پیچیده‌تری سروکار دارید، reactive() گزینه مناسبی خواهد بود.

هوک‌های چرخه حیات در API ترکیبی (Composition API) Vue.js

در Vue.js، هوک‌های چرخه حیات به شما این امکان را می‌دهند که در مراحل مختلف زندگی یک کامپوننت کد خود را اجرا کنید. این هوک‌ها به شما کمک می‌کنند تا کد خود را در نقاط مختلفی از چرخه حیات یک کامپوننت، مانند قبل از رندر، پس از رندر، هنگام آپدیت یا هنگام تخریب کامپوننت، اجرا کنید.

در API ترکیبی (Composition API)، هوک‌های چرخه حیات به صورت توابع جداگانه و قابل استفاده مجدد در دسترس هستند که در داخل تابع setup() استفاده می‌شوند. این تفاوت قابل توجهی با API گزینه‌ای (Options API) دارد، جایی که هوک‌ها به صورت مشخص در گزینه‌های مختلف کامپوننت (مانند mounted(), created(), beforeDestroy() و غیره) قرار می‌گرفتند.

معرفی هوک‌های چرخه حیات در API ترکیبی

در API ترکیبی، برای استفاده از هوک‌های چرخه حیات باید از توابع خاصی که Vue در اختیار شما قرار می‌دهد، استفاده کنید. این توابع به شما اجازه می‌دهند که در هر مرحله از چرخه حیات کامپوننت، کد مورد نظر خود را اجرا کنید. برخی از مهم‌ترین هوک‌های چرخه حیات در Vue 3 شامل onMounted(), onCreated(), onUpdated() و onUnmounted() هستند.

مهم‌ترین هوک‌های چرخه حیات در API ترکیبی

onBeforeMount()
این هوک قبل از رندر کامپوننت، درست قبل از افزودن آن به DOM اجرا می‌شود. می‌توانید از این هوک برای انجام کارهایی استفاده کنید که قبل از ایجاد کامپوننت در DOM باید انجام شوند.
مثال:

import { onBeforeMount } from 'vue';

export default {
  setup() {
    onBeforeMount(() => {
      console.log('کامپوننت قبل از رندر شدن به DOM');
    });
  }
};

onMounted()

این هوک زمانی اجرا می‌شود که کامپوننت به DOM اضافه شده است. این هوک برای انجام کارهایی مانند فراخوانی API‌ها یا تنظیمات بعد از رندر کامپوننت مناسب است.

مثال:

<template>
  <div>
    <h1>{{ message }}</h1>
  </div>
</template>

<script>
import { onMounted, ref } from 'vue';

export default {
  setup() {
    const message = ref('Loading...');

    onMounted(() => {
      message.value = 'Hello, Vue!';
    });

    return { message };
  }
};
</script>

 

در این مثال، از هوک onMounted() استفاده شده است تا پس از رندر شدن کامپوننت، مقدار message تغییر کند.

onBeforeUpdate()

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

import { onBeforeUpdate } from 'vue';

export default {
  setup() {
    onBeforeUpdate(() => {
      console.log('قبل از به‌روزرسانی کامپوننت');
    });
  }
};

onUpdated()

این هوک بعد از هر به‌روزرسانی در کامپوننت اجرا می‌شود. وقتی که داده‌ها تغییر می‌کنند و دوباره کامپوننت رندر می‌شود، این هوک فعال می‌شود.
مثال:

import { onUpdated } from 'vue';

export default {
  setup() {
    onUpdated(() => {
      console.log('کامپوننت پس از به‌روزرسانی');
    });
  }
};

onBeforeUnmount()

این هوک قبل از آنکه کامپوننت از DOM حذف شود، اجرا می‌شود. از آن می‌توان برای تمیز کردن منابع، لغو تایمرها یا رها کردن هر گونه وابستگی استفاده کرد.
مثال:

import { onBeforeUnmount } from 'vue';

export default {
  setup() {
    onBeforeUnmount(() => {
      console.log('قبل از حذف کامپوننت از DOM');
    });
  }
};

onUnmounted()

این هوک پس از آنکه کامپوننت از DOM حذف شد، اجرا می‌شود. از آن برای تمیز کردن نهایی و آزادسازی منابع استفاده می‌شود.
مثال:

import { onUnmounted } from 'vue';

export default {
  setup() {
    onUnmounted(() => {
      console.log('کامپوننت از DOM حذف شد');
    });
  }
};

 

استفاده از هوک‌ها برای کنترل زندگی کامپوننت‌ها

استفاده از هوک‌های چرخه حیات در API ترکیبی (Composition API) Vue.js به شما این امکان را می‌دهد که بر روند اجرای کامپوننت‌ها کنترل بیشتری داشته باشید. به عنوان مثال، اگر شما نیاز دارید که داده‌ها را فقط زمانی بارگذاری کنید که کامپوننت به DOM اضافه شده باشد، می‌توانید از onMounted() استفاده کنید. اگر نیاز دارید که پس از تغییر داده‌ها، کار خاصی انجام دهید، از onUpdated() استفاده می‌کنید.

مثال ترکیبی از چند هوک چرخه حیات

در این مثال، از چند هوک چرخه حیات برای کنترل مراحل مختلف یک کامپوننت استفاده شده است. در اینجا، هوک‌های onBeforeMount(), onMounted(), onBeforeUpdate(), و onUpdated() به‌طور همزمان استفاده می‌شوند.

<template>
  <div>
    <h1>{{ count }}</h1>
    <button @click="increment">Increase</button>
  </div>
</template>

<script>
import { onBeforeMount, onMounted, onBeforeUpdate, onUpdated, ref } from 'vue';

export default {
  setup() {
    const count = ref(0);

    onBeforeMount(() => {
      console.log('قبل از رندر کامپوننت');
    });

    onMounted(() => {
      console.log('کامپوننت به DOM اضافه شد');
    });

    onBeforeUpdate(() => {
      console.log('قبل از به‌روزرسانی');
    });

    onUpdated(() => {
      console.log('کامپوننت به‌روزرسانی شد');
    });

    const increment = () => {
      count.value++;
    };

    return { count, increment };
  }
};
</script>

در این مثال، هر بار که کامپوننت وارد مراحل مختلف چرخه حیات می‌شود، پیامی در کنسول نمایش داده می‌شود. این به شما کمک می‌کند که متوجه شوید هر هوک در کدام مرحله از زندگی کامپوننت فعال می‌شود.

هوک‌های چرخه حیات در API ترکیبی (Composition API) Vue.js به شما این امکان را می‌دهند که کنترل دقیق‌تری بر روی مراحل مختلف زندگی یک کامپوننت داشته باشید. با استفاده از توابع مختلف مانند onMounted(), onUpdated(), onUnmounted() و سایر هوک‌ها، می‌توانید عملکردهای پیچیده‌ای را در زمان مناسب اجرا کنید و همچنین کد خود را قابل نگهداری‌تر و مقیاس‌پذیرتر کنید.

تزریق وابستگی در API ترکیبی (Composition API) Vue.js

در Vue.js، یکی از ویژگی‌های مهم برای سازماندهی و بهبود ساختار کد، تزریق وابستگی (Dependency Injection) است. این قابلیت به شما اجازه می‌دهد که داده‌ها یا توابع را از یک کامپوننت به کامپوننت‌های دیگر به راحتی و بدون نیاز به ارسال از طریق props یا emit ارسال کنید. در API ترکیبی (Composition API) Vue.js، این امکان از طریق توابع provide() و inject() فراهم می‌شود.

مفهوم تزریق وابستگی

تزریق وابستگی به معنی فراهم کردن داده‌ها یا توابع برای کامپوننت‌های دیگر است به گونه‌ای که کامپوننت‌ها بتوانند به راحتی به این داده‌ها یا توابع دسترسی پیدا کنند. این تکنیک به ویژه زمانی مفید است که شما بخواهید داده‌ها یا رفتارهایی را که در کامپوننت‌های بالاتر (والد) تعریف شده‌اند، در کامپوننت‌های پایین‌تر (فرزند) استفاده کنید، بدون اینکه نیاز به ارسال مداوم آن‌ها از طریق props باشد.

توابع provide() و inject()

در API ترکیبی (Composition API)، برای تزریق وابستگی‌ها از دو تابع اصلی استفاده می‌شود:

provide(): این تابع داده‌ها یا توابع را از کامپوننت والد به کامپوننت‌های فرزند فراهم می‌کند.
inject(): این تابع داده‌ها یا توابع فراهم شده را از کامپوننت والد به کامپوننت فرزند تزریق می‌کند.

نحوه استفاده از provide() و inject()

۱. استفاده از provide() در کامپوننت والد

در ابتدا، شما داده‌ای را که می‌خواهید از کامپوننت والد به فرزند ارسال کنید، با استفاده از provide() فراهم می‌کنید. این داده می‌تواند هر نوع مقداری باشد، از جمله اشیاء، رشته‌ها، توابع و غیره.

۲. استفاده از inject() در کامپوننت فرزند

در کامپوننت فرزند، شما از تابع inject() برای دریافت داده‌ای که در کامپوننت والد با استفاده از provide() فراهم شده است، استفاده می‌کنید.

مثال عملی از provide() و inject()

در اینجا یک مثال ساده از استفاده از provide() و inject() آورده شده است که در آن داده‌ای به نام message از کامپوننت والد به کامپوننت فرزند منتقل می‌شود.

کامپوننت والد (ParentComponent.vue)

در اینجا، از provide() برای ارسال داده‌ها به کامپوننت فرزند استفاده می‌کنیم.

<template>
  <ChildComponent />
</template>

<script>
import { provide } from 'vue';
import ChildComponent from './ChildComponent.vue';

export default {
  setup() {
    // فراهم کردن داده برای کامپوننت‌های فرزند
    provide('message', 'Hello from Parent');
  }
};
</script>

در این مثال، کامپوننت والد با استفاده از provide() مقدار Hello from Parent را به عنوان داده‌ای با کلید message فراهم کرده است. این داده می‌تواند توسط هر کامپوننت فرزند که از inject() استفاده می‌کند، دریافت شود.

کامپوننت فرزند (ChildComponent.vue)

در کامپوننت فرزند، از inject() برای دریافت داده‌های فراهم شده استفاده می‌شود.

<template>
  <div>{{ message }}</div>
</template>

<script>
import { inject } from 'vue';

export default {
  setup() {
    // دریافت داده از کامپوننت والد
    const message = inject('message');
    return { message };
  }
};
</script>

در این مثال، کامپوننت فرزند با استفاده از inject() داده‌ای که با کلید message از کامپوننت والد فراهم شده است را دریافت می‌کند و آن را در قالب (template) نمایش می‌دهد.

ویژگی‌های کلیدی provide() و inject()

ساده‌سازی ارتباطات بین کامپوننت‌ها: این روش می‌تواند بسیار مفید باشد وقتی که شما نمی‌خواهید داده‌ها را از کامپوننت والد به کامپوننت‌های فرزند از طریق props ارسال کنید، به‌ویژه در درخت‌های کامپوننت‌های بزرگ.

مستقل از سلسله‌مراتب کامپوننت‌ها: برخلاف استفاده از props و emit که نیاز به سلسله‌مراتب خاصی از کامپوننت‌ها دارند، provide() و inject() به شما این امکان را می‌دهند که وابستگی‌ها را حتی از کامپوننت‌های والد به کامپوننت‌های فرزند دورتر تزریق کنید.

قابلیت استفاده مجدد: داده‌ها و توابعی که از طریق provide() فراهم می‌شوند می‌توانند در هر کامپوننت فرزند با استفاده از inject() تزریق شوند، بنابراین می‌توان از آن‌ها در چندین نقطه از برنامه استفاده کرد.

مثال پیچیده‌تر از provide() و inject()

در این مثال، از provide() و inject() برای اشتراک‌گذاری یک تابع برای افزایش شمارش بین کامپوننت‌های والد و فرزند استفاده می‌شود.

کامپوننت والد (ParentComponent.vue)

<template>
  <ChildComponent />
  <p>{{ count }}</p>
</template>

<script>
import { provide, ref } from 'vue';
import ChildComponent from './ChildComponent.vue';

export default {
  setup() {
    const count = ref(0);

    // فراهم کردن داده و تابع برای فرزند
    provide('count', count);
    provide('increment', () => count.value++);

    return { count };
  }
};
</script>

 

کامپوننت فرزند (ChildComponent.vue)

<template>
  <button @click="increment">Increase Count</button>
</template>

<script>
import { inject } from 'vue';

export default {
  setup() {
    const count = inject('count');
    const increment = inject('increment');

    return { count, increment };
  }
};
</script>

در این مثال، تابع increment() که برای افزایش مقدار count است، از کامپوننت والد به فرزند تزریق شده است. وقتی کاربر روی دکمه کلیک می‌کند، مقدار count در کامپوننت والد تغییر می‌کند و کامپوننت فرزند نیز این تغییرات را مشاهده می‌کند.

مزایای استفاده از provide() و inject()

سادگی در مدیریت وابستگی‌ها: در پروژه‌های بزرگ، provide() و inject() می‌توانند به کاهش پیچیدگی کد و حذف ارسال داده‌ها از طریق props کمک کنند.
سازماندهی بهتر کد: این روش به شما این امکان را می‌دهد که داده‌ها را در سطح بالاتر از درخت کامپوننت‌ها فراهم کرده و در هر جایی از درخت کامپوننت‌ها که نیاز به آن‌ها دارید، دسترسی داشته باشید.

در API ترکیبی (Composition API) Vue.js، توابع provide() و inject() به شما این امکان را می‌دهند که وابستگی‌ها را به طور مؤثری بین کامپوننت‌های والد و فرزند به اشتراک بگذارید. این ویژگی می‌تواند به شما کمک کند تا کد خود را تمیزتر و قابل نگهداری‌تر کنید و از پیچیدگی‌های انتقال داده‌ها با استفاده از props یا emit جلوگیری کنید.

سازماندهی کد و استفاده مجدد در API ترکیبی (Composition API) Vue.js

یکی از بزرگترین مزایای API ترکیبی (Composition API) Vue.js این است که به شما امکان می‌دهد کد خود را به طور مؤثری سازماندهی کنید و از آن در قسمت‌های مختلف برنامه استفاده مجدد کنید. این ویژگی به شما این امکان را می‌دهد که منطق‌های مختلف برنامه را به توابع کوچک و قابل استفاده مجدد تقسیم کنید، که به ویژه در پروژه‌های بزرگ و پیچیده به طرز چشمگیری کارایی و نگهداری کد را بهبود می‌بخشد.

چرا سازماندهی کد و استفاده مجدد مهم است؟

در Vue.js با استفاده از Options API، برای هر کامپوننت معمولاً تمامی داده‌ها، متدها، computed‌ها و watch‌ها در یک ساختار واحد (یک شیء) قرار می‌گیرند. این روش برای برنامه‌های کوچک مناسب است، اما با افزایش اندازه پروژه و پیچیدگی منطق کامپوننت‌ها، این ساختار می‌تواند به راحتی کد را شلوغ و غیرقابل نگهداری کند.

در API ترکیبی (Composition API)، شما می‌توانید منطق‌های مختلف را به توابع کوچک و مستقل تقسیم کنید و این توابع را در کامپوننت‌های مختلف استفاده کنید. این روش به شما اجازه می‌دهد که کد را بهتر سازمان‌دهی کنید، بخش‌های مختلف منطق را مجزا کنید و از آن‌ها در چندین کامپوننت استفاده کنید.

استفاده مجدد از منطق با Composition API

در API ترکیبی (Composition API)، شما می‌توانید منطق‌های کامپوننت‌ها را به صورت توابع جداگانه و قابل استفاده مجدد در فایل‌های مستقل قرار دهید. این توابع به نام “کامپوزابل‌ها” (composables) شناخته می‌شوند.

یک کامپوزابل در Vue.js یک تابع است که از توابع داخلی Vue مانند ref(), reactive(), computed() و watch() استفاده می‌کند تا منطق خاصی را در قالب یک تابع مستقل قرار دهد. سپس این تابع می‌تواند در هر کامپوننتی که نیاز به آن منطق دارد، مورد استفاده قرار گیرد.

مثال از استفاده مجدد منطق با Composition API

در این مثال، منطق شمارش (یک شمارش‌گر) در یک فایل جداگانه به نام useCounter.js قرار می‌گیرد و سپس در کامپوننت‌ها می‌تواند به راحتی مورد استفاده مجدد قرار گیرد.
useCounter.js

// useCounter.js
import { ref } from 'vue';

export function useCounter() {
  const count = ref(0);

  const increment = () => {
    count.value++;
  };

  const decrement = () => {
    count.value--;
  };

  return { count, increment, decrement };
}

در این فایل، یک تابع useCounter تعریف شده است که منطق شمارش را شامل می‌شود. این تابع یک متغیر واکنش‌گرا (count) و دو متد برای افزایش و کاهش شمارش (increment و decrement) را باز می‌گرداند.

CounterComponent.vue

<template>
  <div>
    <h1>{{ count }}</h1>
    <button @click="increment">Increase</button>
    <button @click="decrement">Decrease</button>
  </div>
</template>

<script>
import { useCounter } from './useCounter';

export default {
  setup() {
    const { count, increment, decrement } = useCounter();

    return { count, increment, decrement };
  }
};
</script>

در این کامپوننت، تابع useCounter که در فایل useCounter.js تعریف شده است، وارد می‌شود و متغیر count و توابع increment و decrement به راحتی در setup() کامپوننت استفاده می‌شوند. به این ترتیب، شما می‌توانید منطق شمارش را به راحتی در هر کامپوننت دیگری که نیاز به این منطق دارد، استفاده کنید.

مزایای سازماندهی کد و استفاده مجدد

سازماندهی بهتر کد: با تقسیم منطق‌های مختلف به توابع مستقل و استفاده از کامپوزابل‌ها، کد شما مرتب‌تر و خواناتر خواهد بود.
استفاده مجدد از منطق: شما می‌توانید منطق‌های پیچیده را در توابع جداگانه قرار دهید و آن‌ها را در چندین کامپوننت استفاده کنید. این کار از تکرار کد جلوگیری می‌کند و نگهداری آن را ساده‌تر می‌سازد.
بهبود تست‌پذیری: وقتی منطق‌ها در توابع مجزا قرار می‌گیرند، تست آن‌ها راحت‌تر می‌شود، زیرا هر تابع را می‌توان به صورت مستقل از کامپوننت تست کرد.
کاهش پیچیدگی کامپوننت‌ها: با استفاده از توابع مجزا برای منطق‌های مختلف، کامپوننت‌ها ساده‌تر و مشخص‌تر خواهند بود. این کار می‌تواند به کاهش پیچیدگی و بهبود عملکرد در پروژه‌های بزرگ کمک کند.

مثال‌های دیگر از استفاده مجدد منطق

استفاده از useFetch برای دریافت داده‌ها

فرض کنید شما نیاز دارید که در چند کامپوننت مختلف داده‌ها را از یک API دریافت کنید. به جای نوشتن کد مشابه در هر کامپوننت، می‌توانید یک کامپوزابل برای این کار ایجاد کنید.

// useFetch.js
import { ref } from 'vue';

export function useFetch(url) {
  const data = ref(null);
  const loading = ref(true);
  const error = ref(null);

  fetch(url)
    .then(response => response.json())
    .then(result => {
      data.value = result;
      loading.value = false;
    })
    .catch(err => {
      error.value = err;
      loading.value = false;
    });

  return { data, loading, error };
}

در اینجا، یک کامپوزابل به نام useFetch ایجاد کرده‌ایم که URL را به عنوان ورودی می‌گیرد و داده‌ها را از آن دریافت می‌کند. این کامپوزابل می‌تواند در هر کامپوننتی که نیاز به دریافت داده از API دارد، مورد استفاده قرار گیرد.

استفاده از useLocalStorage برای ذخیره داده‌ها در localStorage

// useLocalStorage.js
import { ref } from 'vue';

export function useLocalStorage(key, initialValue) {
  const storedValue = localStorage.getItem(key);
  const value = ref(storedValue ? JSON.parse(storedValue) : initialValue);

  const setValue = (newValue) => {
    value.value = newValue;
    localStorage.setItem(key, JSON.stringify(newValue));
  };

  return { value, setValue };
}

در اینجا، یک کامپوزابل به نام useLocalStorage ایجاد کرده‌ایم که به شما این امکان را می‌دهد که داده‌ها را در localStorage ذخیره کنید و از آن‌ها در سراسر برنامه استفاده کنید.
در API ترکیبی (Composition API) Vue.js، سازماندهی کد و استفاده مجدد از منطق یک روش مؤثر برای بهبود خوانایی، نگهداری، و تست‌پذیری کد است. با استفاده از توابع مجزا برای منطق‌های مختلف، شما می‌توانید کد خود را تمیزتر، مقیاس‌پذیرتر و قابل نگهداری‌تر کنید. این ویژگی به ویژه در پروژه‌های بزرگ و پیچیده بسیار مفید است.

نتیجه‌گیری

در این مقاله، به بررسی API ترکیبی (Composition API) Vue.js پرداخته شد و مفاهیم کلیدی آن از جمله تابع setup(), استفاده از وضعیت واکنش‌گرا با توابع ref() و reactive(), هوک‌های چرخه حیات، تزریق وابستگی با provide() و inject(), و مزایای سازماندهی کد و استفاده مجدد مورد بررسی قرار گرفت. API ترکیبی یک روش قدرتمند و انعطاف‌پذیر برای ساخت کامپوننت‌ها در Vue.js است که به توسعه‌دهندگان این امکان را می‌دهد تا کدهای خود را ساده‌تر، مقیاس‌پذیرتر و قابل نگهداری‌تر کنند.

این API به خصوص برای پروژه‌های بزرگ و پیچیده مفید است زیرا به شما اجازه می‌دهد که منطق‌های مختلف را در توابع مجزا قرار دهید و از آن‌ها در کامپوننت‌های مختلف استفاده کنید. همچنین، این روش باعث می‌شود که کد شما خواناتر و قابل تست‌تر باشد و توسعه را سریع‌تر و آسان‌تر کند.

در نهایت، API ترکیبی در Vue.js یک گام بزرگ به سوی بهبود ساختار کد و تسهیل فرآیند توسعه است. اگر شما قصد دارید پروژه‌های پیچیده‌تری بسازید یا نیاز به سازماندهی بهتری در کدهای خود دارید، یادگیری و استفاده از این API می‌تواند تأثیر بسزایی در کیفیت و مقیاس‌پذیری پروژه‌های شما داشته باشد.

برای یادگیری بیشتر در مورد API ترکیبی (Composition API) Vue.js، می‌توانید از مستندات رسمی Vue.js و منابع آموزشی معتبر دیگر بهره‌مند شوید.

آموزش API ترکیبی (Composition API) Vue.js

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

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *