Vue.js: ربط Class و Style

آخر تحديث: 2026-08-26

:classe و:style هما أكثر أشكال الربط استخدامًا في Vue — فهما يتيحان لك التبديل ديناميكيًا بين أسماء فئات CSS والأنماط المضمنة بناءً على البيانات. وفي الأساس، هما شكلان خاصان من أشكال v-bind؛ ونظرًا لاستخدامهما المتكرر، فقد تم تطبيقهما باعتبارهما «تسهيلات لغوية».

يكفي إتقان أنماط الكتابة الخمسة هذه لتغطية 95% من الحالات: بناء جملة «object»، وبناء جملة «array»، والمشغلات الثلاثية، والخصائص المحسوبة، وتسلسل «سلسلة».

1. ما ستتعلمه



2. تحدي في التصميم يتعلق بملصق status الطلب

(1) المشكلة: 5 حالات، 5 عبارات "if"

كانت أليس بحاجة إلى عرض 5 حالات للطلبات في لوحة الإدارة بألوان مختلفة:

HTML
<!-- ❌ The "Broken" Version: 5 v-if with class -->
<span v-if="status === 'pending'" class="badge yellow">Pending</span>
<span v-else-if="status === 'paid'" class="badge green">Paid</span>
<span v-else-if="status === 'shipped'" class="badge blue">Shipped</span>
<span v-else-if="status === 'delivered'" class="badge gray">Delivered</span>
<span v-else class="badge red">Cancelled</span>

مدير المنتج تشارلي:

«أليس، هذا مظهره سيئ. ماذا لو أضفنا 3 حالات أخرى الشهر المقبل؟ لا يمكنك الاكتفاء بالنسخ واللصق. نحن بحاجة إلى نهج ديناميكي منظم.»

(2) Vue :class الحل: التعامل مع 5 حالات في سطر واحد فقط

VUE
<template>
  <span :class="['badge', statusClass]">{{ statusText }}</span>
</template>

<script setup>
import { computed } from 'vue'

const props = defineProps({ status: String })

const statusClass = computed(() => ({
  pending: 'yellow',
  paid: 'green',
  shipped: 'blue',
  delivered: 'gray',
  cancelled: 'red'
}[props.status]))

const statusText = computed(() => ({
  pending: 'Pending',
  paid: 'Paid',
  shipped: 'Shipped',
  delivered: 'Delivered',
  cancelled: 'Cancelled'
}[props.status]))
</script>

(3) الإيرادات



3. 5 طرق لكتابة :class

(1) قواعد بناء الجمل النصية

VUE
<template>
  <!-- Static -->
  <div class="active">Static</div>
  
  <!-- Dynamic Strings -->
  <div :class="className">Dynamic</div>
</template>

<script setup>
import { ref } from 'vue'
const className = ref('active text-bold')
</script>

(2) بناء الجملة باستخدام الكائنات (الأكثر شيوعًا)

VUE
<template>
  <!-- Basics: isActive is true, Add active class -->
  <div :class="{ active: isActive }">Single</div>
  
  <!-- Multiple conditions -->
  <div :class="{
    active: isActive,
    'text-danger': hasError,
    disabled: !canEdit
  }">
    Multiple
  </div>
  
  <!-- Computed properties return objects -->
  <div :class="classObject">Computed</div>
</template>

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

const isActive = ref(true)
const hasError = ref(false)
const canEdit = ref(true)

// Computed Properties:Dynamic Return class Object
const classObject = computed(() => ({
  active: isActive.value && !hasError.value,
  'text-danger': hasError.value,
  'bg-success': isActive.value
}))
</script>

(3) صيغة المصفوفات

VUE
<template>
  <!-- Array: Several class concatenation -->
  <div :class="[activeClass, errorClass]">Array</div>
  
  <!-- Trinomial Expression -->
  <div :class="[isActive ? 'active' : '', errorClass]">Ternary</div>
  
  <!-- Array + Object Mixing -->
  <div :class="[activeClass, { 'text-danger': hasError }]">Mixed</div>
  
  <!-- Nested Objects in an Array -->
  <div :class="[{ active: isActive }, errorClass]">Nested</div>
</template>

<script setup>
import { ref } from 'vue'
const activeClass = ref('active')
const errorClass = ref('text-danger')
const isActive = ref(true)
const hasError = ref(false)
</script>

(4) التعايش مع الفئات الثابتة

VUE
<template>
  <!-- Static + Dynamic Merging(Vue Automatic Merge) -->
  <div class="static-class" :class="{ active: isActive }">
    Both
  </div>
  
  <!-- In the end class: "static-class active" or "static-class" -->
</template>

(5) دروس حول المكونات

VUE
<!-- Parent Component -->
<UserCard class="shadow-lg" :class="{ active: isActive }" />

<!-- Child component UserCard.vue -->
<template>
  <!-- Receive -->
  <div :class="$attrs.class">
    <!-- Rendering "shadow-lg active" -->
  </div>
</template>


4. 5 طرق لكتابة :style

(1) قواعد بناء الجملة الخاصة بالكائنات

VUE
<template>
  <!-- Basic Objects -->
  <div :style="{ color: activeColor, fontSize: fontSize + 'px' }">
    Object
  </div>
</template>

<script setup>
import { ref } from 'vue'
const activeColor = ref('red')
const fontSize = ref(16)
</script>

(2) تحويل أسماء خصائص CSS

يقوم Vue تلقائيًا بتحويل قواعد تسمية JavaScript إلى قواعد تسمية CSS:

VUE
<template>
  <div :style="{
    backgroundColor: 'red',        // → background-color
    fontSize: '16px',              // → font-size
    marginTop: '10px',             // → margin-top
    WebkitTransform: 'scale(2)'     // → -webkit-transform
  }">
    CSS naming
  </div>
</template>

(3) صيغة المصفوفات (دمج كائنات متعددة)

VUE
<template>
  <!-- Array:Merge style objects in order(The later one overrides the earlier one)-->
  <div :style="[baseStyles, overrideStyles]">Array</div>
</template>

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

const baseStyles = ref({
  color: 'blue',
  fontSize: '14px'
})

const overrideStyles = ref({
  color: 'red',  // Coverage baseStyles.color
  fontWeight: 'bold'
})
</script>

(4) إضافة البادئة تلقائيًا

يضيف Vue 3 تلقائيًا بادئات المتصفح إلى خصائص CSS (بناءً على محرك المتصفح):

JS
// Write:
{ transform: 'rotate(45deg)' }

// Vue Auto-add:
{
  -webkit-transform: 'rotate(45deg)',
  transform: 'rotate(45deg)'
}

(5) متغيرات CSS (موصى بها لـ Vue 3)

VUE
<template>
  <div :style="{
    '--main-color': mainColor,
    '--spacing': spacing + 'px'
  }">
    CSS Variables
  </div>
</template>

<script setup>
import { ref } from 'vue'
const mainColor = ref('#42b883')
const spacing = ref(20)
</script>

<style>
.dynamic {
  color: var(--main-color);
  padding: var(--spacing);
}
</style>


5. مثال كامل: status الطلب الديناميكية

▶ مثال: 1. 5 طرق لكتابة :class

VUE
<template>
  <!-- 1. String -->
  <div :class="className">String</div>
  
  <!-- 2. Object -->
  <div :class="{ active: isActive, error: hasError }">Object</div>
  
  <!-- 3. Array -->
  <div :class="[activeClass, errorClass]">Array</div>
  
  <!-- 4. Array + Object -->
  <div :class="[activeClass, { disabled: !canEdit }]">Mixed</div>
  
  <!-- 5. Computed Properties -->
  <div :class="dynamicClass">Computed</div>
</template>

<script setup>
import { ref, computed } from 'vue'
const isActive = ref(true)
const hasError = ref(false)
const canEdit = ref(true)
const className = ref('badge')
const activeClass = ref('active')
const errorClass = ref('error')

const dynamicClass = computed(() => ({
  active: isActive.value,
  error: hasError.value,
  'cursor-not-allowed': !canEdit.value
}))
</script>
▶ جرّب الكود

▶ مثال: 2. 5 طرق لكتابة :style

VUE
<template>
  <!-- 1. Basic Objects -->
  <div :style="{ color: 'red', fontSize: '16px' }">Object</div>
  
  <!-- 2. Multiple properties -->
  <div :style="{ backgroundColor: bg, padding: p + 'px' }">Multi</div>
  
  <!-- 3. Merging Sets -->
  <div :style="[baseStyles, themeStyles]">Array</div>
  
  <!-- 4. CSS Variable -->
  <div :style="{ '--theme-color': theme }">CSS Var</div>
  
  <!-- 5. Computed Properties -->
  <div :style="computedStyle">Computed</div>
</template>

<script setup>
import { ref, computed } from 'vue'
const bg = ref('#42b883')
const p = ref(20)
const theme = ref('#35495e')
const baseStyles = ref({ color: 'white' })
const themeStyles = ref({ backgroundColor: '#42b883' })

const computedStyle = computed(() => ({
  color: 'white',
  backgroundColor: theme.value,
  padding: `${p.value}px`
}))
</script>
▶ جرّب الكود

▶ مثال: 3. شارة status الطلب

VUE 📖 للعرض فقط
<template>
  <span :class="['order-badge', statusClass]">
    {{ statusText }}
  </span>
</template>

<script setup>
import { computed } from 'vue'

const props = defineProps({
  status: { type: String, required: true }
})

// 5 Status → 5 class
const statusClass = computed(() => {
  const map = {
    pending: 'bg-yellow',
    paid: 'bg-green',
    shipped: 'bg-blue',
    delivered: 'bg-gray',
    cancelled: 'bg-red'
  }
  return map[props.status] || 'bg-default'
})

const statusText = computed(() => {
  const map = {
    pending: 'Pending',
    paid: 'Paid',
    shipped: 'Shipped',
    delivered: 'Delivered',
    cancelled: 'Cancelled'
  }
  return map[props.status] || 'Unknown'
})
</script>

<style scoped>
.order-badge {
  padding: 4px 12px;
  border-radius: 12px;
  color: white;
  font-size: 12px;
}
.bg-yellow { background: #f59e0b; }
.bg-green { background: #10b981; }
.bg-blue { background: #3b82f6; }
.bg-gray { background: #6b7280; }
.bg-red { background: #ef4444; }
</style>
44 سطر من الكود المنطقي (تجاوز الحد 40, للعرض فقط)

▶ مثال: 4. 5 أخطاء شائعة

الخطأ الأعراض الحل
فئة String لا تستجيب الفئة مبرمجة بشكل ثابت ولا يمكن تغييرها تم ربطها باستخدام :class
فئة array بها أخطاء إملائية وجود عدة فئات تحمل الاسم نفسه تتداخل مع بعضها البعض استخدام صيغة الكائنات
وحدة النمط مفقودة يتم تفسير الرقم 16 على أنه 16px ويتم تجاهله يتم كتابة السلسلة '16px'
اسم خاصية CSS غير صحيح font-size يجب أن يكون fontSize استخدم أسلوب كتابة camelCase أو علامات الاقتباس
:تعارض الفئات تضارب بين الأسماء الثابتة والديناميكية تقوم Vue بدمجها تلقائيًا، لا بأس

▶ مثال: 5. 5 مقارنات الأداء

التنفيذ ناتج التجميع الأداء قابلية التطبيق
سلسلة التسلسل المباشر للسلاسل ⭐⭐⭐⭐⭐ بسيط
الكائن التحليل الثابت ⭐⭐⭐⭐ معتدل
المصفوفات ربط السلاسل ⭐⭐⭐⭐ فئات متعددة
المصفوفات + الكائنات المعالجة المختلطة ⭐⭐⭐ معقدة
الخاصية المحسوبة القيمة المخزنة مؤقتًا ⭐⭐⭐⭐⭐ منطق معقد

▶ مثال: 6. الاختلافات الخمسة الرئيسية بين «الفئة» و«الأسلوب»

الجانب الفئة النمط
التقييم ⭐⭐⭐⭐⭐ ⭐⭐⭐
قابلية إعادة استخدام CSS سهل (إعادة استخدام أسماء الفئات) صعب (أنماط متناثرة)
الأداء أعلى (تحسين المتصفح) أقل قليلاً
الأولوية تعتمد على المحدد مضمنة (الأعلى)
تبديل القوالب سهل (تغيير الفئة) سهل (تغيير متغير CSS)


❓ أسئلة شائعة

س هل يمكن أن تتعايش ربطات الفئة والأسلوب معًا؟
ج نعم. يتم دمج class="x" الثابت و:class="{active: y}" الديناميكي تلقائيًا (مما ينتج عنه إما class="x active" أو "x").
س لماذا يجب كتابة السمة style ككائن؟ ألا يمكنني استخدام سلسلة CSS فحسب؟
ج نعم، يمكنك ذلك. <div style="color: red"> هي صيغة HTML الأصلية، و<div :style="'color: red'"> هي أيضًا طريقة تعتمد على السلسلة. ومع ذلك، فإن استخدام كائن :style="{ color: 'red' }" يتيح لك ربط المتغيرات ديناميكيًا. نوصي باستخدام كائن.
س كيف تُستخدم متغيرات CSS؟
ج استخدم {'--my-var': value} في :style وvar(--my-var) في CSS. يوصي Vue 3 باستخدام متغيرات CSS لتبديل السمات، حيث إنها أكثر كفاءة من ربط الأنماط مباشرةً (فكل ما عليك هو تحديث متغير واحد، ولن يتكرر ترتيب العناصر في DOM).
س كيف تستقبل المكونات الفئات الخارجية؟
ج ترث المكونات أحادية الجذر السمة class تلقائيًا (السلوك الافتراضي في Vue 3). أما المكونات متعددة الجذور فتستخدم $attrs.class للربط صراحةً بعنصر معين.
س ما هو ترتيب الفئات في صيغة الarray؟
ج يتم ربطها بالترتيب الذي تظهر به في الarray، لكن هذا الترتيب لا يؤثر على خصوصية CSS (التي تتحدد حسب خصوصية محددات CSS).
س هل يمكن استخدام :class مع v-if؟
ج نعم. <div v-if="show" :class="{ active: isActive }"> عندما تكون قيمة show=false، لا يتم عرض العنصر بأكمله، ولا يكون لـ isActive أي تأثير.
س كيف يمكنني التبديل بين السمات ديناميكيًا؟
ج نوصي باستخدام متغيرات CSS. ينطبق :style="{ '--primary': theme.primary }" على جميع العناصر color: var(--primary). يتطلب التبديل بين السمات تغيير متغير واحد فقط، وهو ما يعد أكثر كفاءة من تبديل 100 فئة.

📖 ملخص


📝 تمارين

  1. أسئلة أساسية (مستوى الصعوبة: ⭐)

    استخدم محدد :class لتنفيذ ثلاث حالات للأزرار:

    • الأساسي: نص أبيض على خلفية زرقاء
    • النجاح: نص أبيض على خلفية خضراء
    • خطر: نص أبيض على خلفية حمراء

    البيانات: const variant = ref('primary')

  2. مسائل متقدمة (مستوى الصعوبة: ⭐⭐)

    قم بتنفيذ قائمة الطلبات بحيث يعرض كل صف شارة بلون مختلف بناءً على status الطلب:

    • 5 حالات (قيد الانتظار/مدفوعة/مشحونة/مسلّمة/ملغاة)
    • إرجاع كائن class باستخدام خاصية محسوبة
    • :style إضافة لون الرمز المطابق للstatus
  3. مسألة التحدي (مستوى الصعوبة: ⭐⭐⭐)

    تنفيذ نظام كامل لتبديل السمات:

    1. 3 أنماط (فاتح/داكن/عالي التباين)
    2. استخدم متغيرات CSS لربط ألوان السمة (الأساسية/الثانوية/الخلفية/النص)
    3. :class — تغيير اسم فئة السمة
    4. استخدم localStorage لتخزين اختيار المستخدم
    5. لا يؤدي تغيير السمات إلى تحديث الصفحة (يتم تحديث التصميم المتجاوب تلقائيًا)
Web-Tutorial.com

فريق Web-Tutorial التقني

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

100%