Skip to content

أحداث المكونات

لقراءة هذه الصفحة يجب عليك أولا الاطلاع على أساسيات المكونات. ثم العودة إلى هنا.

الإرسال والاستماع للأحداث

يمكن للمكون إرسال أحداث مخصصة مباشرة في تعبيرات القالب (على سبيل المثال ، في معالج v-on) باستخدام التابع المدمج emit$:

template
<!-- MyComponent -->
<button @click="$emit('someEvent')">انفر الزر</button>

التابع $emit() متوفر أيضًا على نسخة المكون باستخدام this.$emit():

js
export default {
  methods: {
    submit() {
      this.$emit('someEvent')
    }
  }
}

المكون الأب يمكنه الاستماع لها باستخدام v-on:

template
<MyComponent @some-event="callback" />

المعدل .once مدعوم أيضًا على مستمعي أحداث المكون:

template
<MyComponent @some-event.once="callback" />

مثل المكونات والخصائص ، توفر أسماء الأحداث تحويل تلقائي لحالة الأحرف. يمكن ملاحظة أننا أرسلنا حدث مكتوب بنمط سنام الجمل camelCase ، لكن يمكننا الاستماع له باستخدام مستمع مكتوب بنمط أسياخ الشواء kebab-case داخل المكون الأب. كما في تسمية الخاصيات ، نوصي باستخدام مستمعي أحداث بنمط kebab-case في القوالب.

ملاحظة

على عكس أحداث DOM الأصلية، فإن أحداث المكونات المرسلة لا تنتشر عبر شجرة مكونات التطبيق. يمكنك الاستماع فقط إلى الأحداث المرسلة من المكون الابن المباشر. إذا كان هناك حاجة للتواصل بين المكونات الشقيقة أو المكونات المتداخلة بعمق، فاستخدم ناقل خارجي للأحداث أو حلول إدارة الحالة العامة.

وسائط الحدث

في بعض الأحيان ، يكون من المفيد إرسال قيمة معينة مع الحدث. على سبيل المثال، قد نرغب في أن يكون المكون <BlogPost> مسؤولًا عن حجم تكبير النص. في هذه الحالات ، يمكننا إرسال وسائط إضافية إلى emit$ لتوفير هذه القيمة:

template
<button @click="$emit('increaseBy', 1)">
زيادة بـ 1
</button>

ثم، عندما نستمع إلى الحدث في المكون الأب، يمكننا استخدام الدالة السهمية السطرية كمستمع، والتي تسمح لنا بالوصول إلى وسيط الحدث المرسل:

template
<MyButton @increase-by="(n) => count += n" />

أو، إذا كان معالج الحدث عبارة عن تابع:

template
<MyButton @increase-by="increaseCount" />

ثم ستُمرَّر القيمة كأول وسيط لهذا التابع:

js
methods: {
  increaseCount(n) {
    this.count += n
  }
}
js
function increaseCount(n) {
  count.value += n
}

ملاحظة

تمرر جميع الوسائط الإضافية المرسلة عبر ()emit$ بعد اسم الحدث إلى المستمع. على سبيل المثال ، مع emit('foo', 1, 2, 3)$ ستتلقى دالة المستمع ثلاثة وسائط.

التصريح بالأحداث المرسلة

يمكن للمكون التصريح بشكل واضح عن الأحداث التي سيقوم بإرسالها باستخدام التعليمة العامة ()defineEmitsخيار emits:

vue
<script setup>
defineEmits(['inFocus', 'submit'])
</script>

emit$ هو التابع الذي استخدمناه في <template> غير متاح داخل قسم <script setup> للمكون ، ولكن ()defineEmits تعيد دالة مكافئة يمكننا استخدامها بدلاً من ذلك:

vue
<script setup>
const emit = defineEmits(['inFocus', 'submit'])

function buttonClick() {
  emit('submit')
}
</script>

التعليمة العامة ()defineEmits لا يمكن استخدامها داخل دالة ، يجب وضعها مباشرة داخل <script setup> ، كما هو الحال في المثال أعلاه.

إذا كنت تستخدم الدالة setup بدلاً من <script setup> ، فيجب عليك الإعلان عن الأحداث باستخدام خيار emits ، ويتم توفير التابع emit في سياق ()setup كوسيط ثاني:

js
export default {
  emits: ['inFocus', 'submit'],
  setup(props, ctx) {
    ctx.emit('submit')
  }
}

كما هو الحال مع الخاصيات الأخرى في سياق ()setup ، يمكن تفكيك emit بأمان:

js
export default {
  emits: ['inFocus', 'submit'],
  setup(props, { emit }) {
    emit('submit')
  }
}
js
export default {
  emits: ['inFocus', 'submit']
}

خيار emits يدعم أيضًا صيغة الكائن، إذا كنت تستخدم الـTypescript تستطيع تمرير وسائط ذات نوع، والتي تسمح لنا بتنفيذ التحقق من صحة الحمولة الممررة للأحداث المرسلة في وقت التشغيل :

vue
<script setup>
const emit = defineEmits({
  submit(payload: { email: string, password: string }) {
    // اعد `true` أو `false` للإشارة إلى
    // نجاح / فشل التحقق
  }
})
</script>

إذا كنت تستخدم TypeScript مع <script setup> ، فمن الممكن أيضًا تعريف الأحداث المرسلة باستخدام التوصيفات النوعية البحتة:

vue
<script setup lang="ts">
const emit = defineEmits<{
  (e: 'change', id: number): void
  (e: 'update', value: string): void
}>()
</script>

أكثر تفاصيل حول : إضافة الأنواع إلى الأحداث المرسلة

js
export default {
  emits: {
    submit(payload: { email: string, password: string }) {
       // اعد true` أو `false` للإشارة إلى
       // نجاح / فشل التحقق
    }
  }
}

أكثر تفاصيل حول : إضافة الأنواع إلى الأحداث المرسلة

على الرغم من أن الأمر اختياري، إلا أنه ينصح بتعريف جميع الأحداث المرسلة من أجل توثيق جيد لكيفية عمل المكون. كما يسمح لـ Vue باستبعاد المستمعين المعروفين من السمات المستترة ، وتجنب الحالات القصوى الناتجة عن أحداث الـDOM الموزعة يدويا من المكتبات الخارجية.

ملاحظة

إذا تم تعريف حدث أصلي (على سبيل المثال ، click) في خيار emits ، فسينصت المستمع الآن فقط إلى أحداث click المنشأة من المكون ولن يستجيب لأحداث click الأصلية.

التحقق من صحة الأحداث

مثلما هو الحال بالنسبة للتحقق من صحة نوع الخاصية ، يمكن التحقق من صحة الحدث المرسل إذا تم تعريفه باستخدام صيغة الكائن بدلاً من صيغة المصفوفة.

لإضافة التحقق ، يعطىالحدث دالة كقيمة والتي تتلقى الوسائط الممررة إلى الاستدعاء this.$emitemit وتعيد قيمة منطقية لتشير إلى صحة الحدث من عدمها.

vue
<script setup>
const emit = defineEmits({
  // لا يوجد تحقق
  click: null,

  // تحقق من حدث الإرسال
  submit: ({ email, password }) => {
    if (email && password) {
      return true
    } else {
      console.warn('وسائط حدث الإرسال غير صالحة!')
      return false
    }
  }
})

function submitForm(email, password) {
  emit('submit', { email, password })
}
</script>
js
export default {
  emits: {
    // لا يوجد تحقق
    click: null,

    // تحقق من حدث الإرسال
    submit: ({ email, password }) => {
      if (email && password) {
        return true
      } else {
        console.warn('وسائط حدث الإرسال غير صالحة!')
        return false
      }
    }
  },
  methods: {
    submitForm(email, password) {
      this.$emit('submit', { email, password })
    }
  }
}

الأحداث كخاصيات

يمكنك أيضًا تعريف وتمرير الأحداث كخاصيات، عن طريق إضافة النص on مع اسم الحدث بالحروف الكبيرة. استخدام props.onEvent له سلوك مختلف عن استخدام emit('event')، حيث سيمرر الأول فقط المستمع المعتمد على الخاصية (سواء event@ أو on-event:)

WARNING

إذا مُرِّر كل من :onEvent و event@ فقد يكون props.onEvent مصفوفة من الدوال بدلاً من دالة، هذا السلوك غير مستقر وقد يتغير في المستقبل.

لهذا السبب، يُفضل استخدام emit('event') بدلاً من props.onEvent عند إرسال الأحداث.

أحداث المكونات has loaded