home / blog / نصائح Vue.js ستجعلك مطوراً أكثر إنتاجية
جافاسكريبت Jan 28, 2026

نصائح Vue.js ستجعلك مطوراً أكثر إنتاجية

مجموعة من أنماط ونصائح Vue.js العملية — من composables وprovide/inject إلى تحسينات الأداء — التي تمنيت لو عرفتها مبكراً.

نصائح Vue.js ستجعلك مطوراً أكثر إنتاجية

Composables: قلب Vue 3

إذا كنت لا تزال تضع كل منطقك في setup() أو تستخدم Options API للمكونات المعقدة، فإن composables ستغير حياتك. هي ببساطة دوال تغلّف المنطق التفاعلي ويمكن مشاركتها بين المكونات.

// composables/useDebounce.js
import { ref, watch } from 'vue'

export function useDebounce(value, delay = 300) {
  const debouncedValue = ref(value.value)

  let timeout
  watch(value, (newValue) => {
    clearTimeout(timeout)
    timeout = setTimeout(() => {
      debouncedValue.value = newValue
    }, delay)
  })

  return debouncedValue
}

// Usage in a component
const search = ref('')
const debouncedSearch = useDebounce(search, 500)

watch(debouncedSearch, (value) => {
  fetchResults(value)
})

مثال عملي أكثر: جلب البيانات من API

// composables/useApi.js
import { ref, shallowRef } from 'vue'

export function useApi() {
  const data = shallowRef(null)
  const error = ref(null)
  const loading = ref(false)

  async function execute(url, options = {}) {
    loading.value = true
    error.value = null

    try {
      const response = await fetch(url, {
        headers: { 'Content-Type': 'application/json', ...options.headers },
        ...options,
      })

      if (!response.ok) throw new Error(`HTTP ${response.status}`)

      data.value = await response.json()
      return data.value
    } catch (e) {
      error.value = e.message
      throw e
    } finally {
      loading.value = false
    }
  }

  return { data, error, loading, execute }
}

// Usage
const { data: users, loading, execute: fetchUsers } = useApi()
await fetchUsers('/api/users')

Provide/Inject: تخلّص من تمرير الخصائص عبر المستويات

عندما تحتاج إلى تمرير بيانات عبر عدة مستويات من المكونات، فإن provide و inject أنظف بكثير من تمرير الخصائص (prop drilling) عبر كل مستوى.

// In a parent component
import { provide, ref } from 'vue'

const currentTheme = ref('dark')
const toggleTheme = () => {
  currentTheme.value = currentTheme.value === 'dark' ? 'light' : 'dark'
}

provide('theme', { currentTheme, toggleTheme })

// In any descendant (no matter how deep)
import { inject } from 'vue'

const { currentTheme, toggleTheme } = inject('theme')

v-model مع المكونات: الطريقة الصحيحة

ماكرو defineModel في Vue 3 (الإصدار 3.4 وما بعد) يجعل دعم v-model المخصص أمرًا بسيطًا للغاية:

<!-- BaseInput.vue -->
<script setup>
const model = defineModel()
const props = defineProps({
  label: String,
  type: { type: String, default: 'text' },
})
</script>

<template>
  <div class="form-group">
    <label>{{ label }}</label>
    <input :type="type" v-model="model" class="input" />
  </div>
</template>

<!-- Usage -->
<BaseInput v-model="form.email" label="Email" type="email" />

الأداء: التحميل الكسول للمسارات

لا تقم بتحميل تطبيقك بالكامل دفعة واحدة. قسّمه حسب المسارات:

// router/index.js
const routes = [
  {
    path: '/',
    component: () => import('./views/Home.vue'),
  },
  {
    path: '/dashboard',
    component: () => import('./views/Dashboard.vue'),
    // Only loads when user navigates to /dashboard
  },
  {
    path: '/settings',
    component: () => import('./views/Settings.vue'),
  },
]

المراقبون: استخدم watchEffect للحالات البسيطة

// Instead of manually listing dependencies...
watch([firstName, lastName], ([first, last]) => {
  fullName.value = `${first} ${last}`
})

// ...let Vue track them automatically
watchEffect(() => {
  fullName.value = `${firstName.value} ${lastName.value}`
})

Template Refs مع TypeScript

<script setup lang="ts">
import { ref, onMounted } from 'vue'

const inputRef = ref<HTMLInputElement | null>(null)

onMounted(() => {
  inputRef.value?.focus()
})
</script>

<template>
  <input ref="inputRef" />
</template>

ملخص سريع للنصائح

  • استخدم shallowRef للكائنات الكبيرة التي لا تحتاج إلى تفاعلية عميقة — فهو أسرع بشكل ملحوظ
  • فضّل computed على الدوال في القوالب — القيم المحسوبة يتم تخزينها مؤقتًا
  • استخدم toRefs عند تفكيك الكائنات التفاعلية للحفاظ على التفاعلية
  • أضف خاصية key لحلقات v-for بمعرّفات فريدة، وليس فهارس المصفوفة
  • استخدم <Suspense> مع المكونات غير المتزامنة لحالات التحميل
  • حافظ على حجم المكونات تحت 200 سطر — إذا كانت أطول، استخرج composable أو مكوّنًا فرعيًا

أفضل كود Vue يُقرأ كوصف لما تفعله الواجهة، لا كيف تفعله. الـ composables تتولى "الكيف"، والمكونات تصف "الماذا".

العودة لجميع المقالات