Skip to content

دایرکتیوهای شخصی سازی شده

مقدمه

Vue به شما امکان می دهد علاوه بر مجموعه دایرکتیوهایی که به صورت پیش فرض وجود دارد (مانند v-model یا v-show), دایرکتیوهای شخصی سازی شده خود را ثبت کنید.

ما دو روش کد که در ویو باز استفاده می شوند را معرفی کردیم: کامپوننت ها و کامپوزبل ها. کامپوننت ها قالب های اصلی ساخت هستند در حالیکه کامپوزبل ها روی استفاده دوباره منطق حالتی تمرکز کرده اند. دایرکتیو های شخصی سازی شده, از طرف دیگر , اساسا برای استفاده دوباره منطقی که شامل دسترسی سطح پایین DOM به المنت های ساده هستند تعیین شدند.

یک دایرکتیو شخصی سازی شده به عنوان یک شی (object) شامل هوک های چرخه حیات می باشد که مشابه هوک های کامپوننت هستند. هوک ها المنتی که به دایرکتیو متصل (bound) هست را دریافت می کنند. در اینجا مثالی از یک دایرکتیو آورده شده که عمل فوکس(focus) را بر روی المنت اینپوت(input) هنگاهی که Vue اینپوت را درون DOM وارد می کند انجام می دهد:

vue
<script setup>
// v-focus را در تمپلیت ها فعال می کند
const vFocus = {
  mounted: (el) => el.focus()
}
</script>

<template>
  <input v-focus />
</template>
js
const focus = {
  mounted: (el) => el.focus()
}

export default {
  directives: {
    // v-focus را در تمپلیت ها فعال می کند
    focus
  }
}
template
<input v-focus />

با فرض اینکه شما هیچ جای صفحه کلیک نکرده باشید, اینپوت مثال بالا باید به صورت خودکار فوکس شده باشد. دایرکتیو از ویژگی autofocus مفیدتر است زیرا نه تنها در صفحه لود شده کار می دهد بلکه درون المنت هایی که به صورت پویا (dynamic) ساخته شده اند کار می دهد.

درون <script setup>, هر متغیری به شکل camelCase که با پیشوند v شروع می شود می تواند به عنوان یک دایرکتیو شخصی سازی شده استفاده بشه. در مثال بالا, vFocus میتواند درون تمپلیت (template) به صورت v-focus استفاده بشه.

اگه از <script setup> استفاده نمی کنید, دایرکتیو های شخصی سازی شده می تونن با استفاده از گزینه (option) directives استفاده شوند.

js
export default {
  setup() {
    /*...*/
  },
  directives: {
    // v-focus را در تمپلیت فعال می کند
    focus: {
      /* ... */
    }
  }
}

مشابه با کامپوننت ها، دایرکتیوهای شخصی سازی شده برای استفاده در تمپلیت ها بایستی حتما ثبت (register) شوند. در مثال بالا، داریم از ثبت محلی (local registeration) با گزینه (option) directives استفاده می کنیم.

همچنین روش رایج دیگر، ثبت کردن دایرکتیوهای شخصی سازی شده در سطح app به صورت همگانی (globally) می باشد:

js
const app = createApp({})

// v-focus را درون همه کامپوننت ها قابل استفاده کن
app.directive('focus', {
  /* ... */
})

نکته

دایرکتیوهای شخصی سازی شده فقط باید زمانی استفاده شوند که عملکرد مورد نظر فقط از طریق دستکاری مستقیم DOM حاصل شود. در صورت امکان، قالب اعلامی با استفاده از دایرکتیوهای نهادینه شده مانند v-bind را ترجیح دهید زیرا کارامد تر و سرور-رندر دوستانه تر هستند.

هوک های دایرکتیو

یک شی دایرکتیو میتونه چندین تابع هوک چرخه حیات را فراهم کند (همگی اختیاری هستند):

js
const myDirective = {
  // قبل از اتصال ویژگی های المنت 
  // یا اعمال شدن event listeners ها صدا زده می شود
  created(el, binding, vnode, prevVnode) {
    // see below for details on arguments
  },
  // درست قبل از اینکه المنت وارد DOM شود صدا زده می شود.
  beforeMount(el, binding, vnode, prevVnode) {},
  // هنگامی صدا زده می شود که تمام المنت های کامپوننت والد
  // به همراه تمامی فرزندانش درون DOM قرار گرفته 
  mounted(el, binding, vnode, prevVnode) {},
  // قبل از اینکه کامپوننت والد بروز رسانی شود صدا زده می شود
  beforeUpdate(el, binding, vnode, prevVnode) {},
  // بعد از اینکه کامپوننت والد و 
  // همه فرزاندش به روز رسانی شدند صدا زده می شود
  updated(el, binding, vnode, prevVnode) {},
  // قبل از اینکه کامپوننت والد آنمانت شود صدا زده می شود
  beforeUnmount(el, binding, vnode, prevVnode) {},
  // هنگامی صدا زده می شود که کامپوننت والد آنمانت شده
  unmounted(el, binding, vnode, prevVnode) {}
}

آرگومان های هوک

هوک های دایرکتیو آرگومان های زیر را قبول می کنند:

  • el: المنتی که دایرکتیو به آن متصل است. این آرگومان می تواند مستقیما برای دستکاری DOM استفاده شود.

  • binding: این شی شامل پراپرتی های زیر است.

    • value: مقداری که به دایرکتیو ارسال میشود. برای مثال در v-my-directive="1 + 1", مقدار ارسال شده 2 خواهد بود.

    • oldValue: مقدار قبلی، تنها درون هوک های beforeUpdate و updated قابل دسترس هست. خواه مقدار تغییر بکند خواه نکند این پراپرتی در دسترس هست.

    • arg: آرگومانی که در صورت وجود به دایرکتیو ارسال می شود. برای مثال در v-my-directive:foo, آرگومان "foo" می باشد.

    • modifiers: یک شی که شامل مدیفایرها هست که در صورت وجود به دایرکتیو ارسال می شود. برای مثال در v-my-directive.foo.bar, شی شامل مدیفایرهای { foo: true, bar: true } می باشد.

    • instance: نمونه ای از کامپوننتی که دایرکتیو درون آن استفاده شده.

    • dir: مشخصات شی دایرکتیو

  • vnode: نود اصلی که ارائه دهنده المنت متصل است

  • prevNode: نودی که ارائه دهنده المنت اصلی از رندر قبلی است. فقط درون هوک های beforeUpdate و updated قابل دسترس هست.

به عنوان مثال، کاربرد دایرکتیو زیر را در نظر بگیرید:

template
<div v-example:foo.bar="baz">

آرگومان binding یک شی به شکل زیر است:

js
{
  arg: 'foo',
  modifiers: { bar: true },
  value: /*  مقدار `baz` */,
  oldValue: /* مقدار `baz` از بروزرسانی قبلی */
}

مشابه دایرکتیوهای نهادینه شده, آرگومان های دایرکیتو شخصی سازی شده میتوانند پویا باشند. برای مثال:

template
<div v-example:[arg]="value"></div>

در اینجا آرگومان دایرکتیو بر اساس پراپرتی arg درون استیت کامپوننت ما به صورت ری اکتیو بروزرسانی می شود.

توجه

جدا از el, شما باید با این آرگومان ها به صورت فقط خواندنی (read-only) رفتار کنید و هرگز آنها را تغییر ندهید. اگر شما نیاز دارید این اطلاعات را از طریق هوک ها به اشتراک بزارید، پیشنهاد میشه که این کار را از طریق المنت های dataset انجام دهید.

مختصر نویسی تابع

معمول است که یک دایرکتیو شخصی سازی شده برای هوک های mounted و updated رفتار یکسانی داشته باشد، بدون نیاز به هوک های دیگر. در چنین مواردی میتوانیم دایرکتیو را به صورت تابع تعریف کنیم:

template
<div v-color="color"></div>
js
app.directive('color', (el, binding) => {
  // برای هر دو هوک `mounted` و `updated` صدا زده می شود
  el.style.color = binding.value
})

اشیاء تحت اللفظی

اگر دایرکتیو شما نیازمند مقادیر مختلفی هست، شما میتوانید یک شی تحت اللفظی(object literal) جاوااسکریپتی را بعنوان مقدار تعیین کنید. به یاد داشته باشید، دایرکتیوها می توانند هر عبارت معتبر جاوااسکریپتی را دریافت کنند.

template
<div v-demo="{ color: 'white', text: 'hello!' }"></div>
js
app.directive('demo', (el, binding) => {
  console.log(binding.value.color) // => "white"
  console.log(binding.value.text) // => "hello!"
})

کاربرد در کامپوننت ها

دایرکتیوهای شخصی سازی شده همانند Fallthrough Attributes برای استفاده در کامپوننت ها باید در نود ریشه (root node) به کار روند.

template
<MyComponent v-demo="test" />
template
<!-- template of MyComponent -->

<div> <!-- دایرکتیو v-demo اینجا به کار می رود -->
  <span>My component content</span>
</div>

توجه داشته باشید که کامپوننت ها به طور بالقوه میتوانند بیشتر از یک نود ریشه داشته باشند. یک دایرکتیو هنگامی که بر کامپوننتی با چندین نود ریشه اعمال می شود نادیده گرفته خواهد شد و اخطار داده می شود. دایرکتیوها برخلاف ویژگی ها(attributes) نمی توانند با استفاده از v-bind="$attrs" به المنت دیگری ارسال شوند. به طور کلی، توصیه می شود که از دایرکتیوهای شخصی سازی شده درون کامپوننت ها استفاده نکنید.

دایرکتیوهای شخصی سازی شده has loaded