Vue.js: ربط Class و Style
آخر تحديث: 2026-08-26
:classe و:style هما أكثر أشكال الربط استخدامًا في Vue — فهما يتيحان لك التبديل ديناميكيًا بين أسماء فئات CSS والأنماط المضمنة بناءً على البيانات. وفي الأساس، هما شكلان خاصان من أشكال v-bind؛ ونظرًا لاستخدامهما المتكرر، فقد تم تطبيقهما باعتبارهما «تسهيلات لغوية».
يكفي إتقان أنماط الكتابة الخمسة هذه لتغطية 95% من الحالات: بناء جملة «object»، وبناء جملة «array»، والمشغلات الثلاثية، والخصائص المحسوبة، وتسلسل «سلسلة».
1. ما ستتعلمه
:classeبناء جملة الكائنات: التبديل بين الفئة الواحدة والفئات المتعددة بناءً على الشروط:classeصيغة المصفوفات: تطبيق فئات متعددة في آن واحد- المزج بين المصفوفات والكائنات: تركيبات معقدة لأسماء الفئات
:styleبناء الجملة للكائنات: الأنماط المضمنة الديناميكية:styleصيغة المصفوفات: دمج عدة كائنات أنماط- ربط متغيرات CSS (موصى به لـ Vue 3)
2. تحدي في التصميم يتعلق بملصق status الطلب
(1) المشكلة: 5 حالات، 5 عبارات "if"
كانت أليس بحاجة إلى عرض 5 حالات للطلبات في لوحة الإدارة بألوان مختلفة:
<!-- ❌ 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 حالات في سطر واحد فقط
<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) الإيرادات
- تقليص كود HTML: 5 أسطر من if-else → سطر واحد من :class
- قابلية الصيانة: لإضافة status جديدة، ما عليك سوى تعديل الخاصية
computed؛ بينما يظل القالب دون تغيير. - سهولة القراءة: يتم تجميع تعيينات فئات الstatus في مكان واحد، مع اتباع منطق واضح
3. 5 طرق لكتابة :class
(1) قواعد بناء الجمل النصية
<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) بناء الجملة باستخدام الكائنات (الأكثر شيوعًا)
<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) صيغة المصفوفات
<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) التعايش مع الفئات الثابتة
<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) دروس حول المكونات
<!-- 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) قواعد بناء الجملة الخاصة بالكائنات
<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:
<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) صيغة المصفوفات (دمج كائنات متعددة)
<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 (بناءً على محرك المتصفح):
// Write:
{ transform: 'rotate(45deg)' }
// Vue Auto-add:
{
-webkit-transform: 'rotate(45deg)',
transform: 'rotate(45deg)'
}
(5) متغيرات CSS (موصى بها لـ Vue 3)
<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
<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
<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 الطلب
<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>
▶ مثال: 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' }" يتيح لك ربط المتغيرات ديناميكيًا. نوصي باستخدام كائن.{'--my-var': value} في :style وvar(--my-var) في CSS. يوصي Vue 3 باستخدام متغيرات CSS لتبديل السمات، حيث إنها أكثر كفاءة من ربط الأنماط مباشرةً (فكل ما عليك هو تحديث متغير واحد، ولن يتكرر ترتيب العناصر في DOM).class تلقائيًا (السلوك الافتراضي في Vue 3). أما المكونات متعددة الجذور فتستخدم $attrs.class للربط صراحةً بعنصر معين.<div v-if="show" :class="{ active: isActive }"> عندما تكون قيمة show=false، لا يتم عرض العنصر بأكمله، ولا يكون لـ isActive أي تأثير.:style="{ '--primary': theme.primary }" على جميع العناصر color: var(--primary). يتطلب التبديل بين السمات تغيير متغير واحد فقط، وهو ما يعد أكثر كفاءة من تبديل 100 فئة.📖 ملخص
:classو:styleهما صيغتان مبسطتان لـ v-bind؛ وهما الأكثر استخدامًا، ولذلك تم تبسيطهما.- :class — 5 طرق لتعريفه: سلسلة، كائن، array، array + كائن، خاصية محسوبة
- :style — 5 طرق لكتابته: كائن، array، array + كائن، متغيرات CSS، الخصائص المحسوبة
- الدمج التلقائي للفئات الثابتة و
:classالديناميكية - يضيف Vue 3 بادئات CSS الخاصة بالمتصفحات تلقائيًا
- تُعد متغيرات CSS الحل الموصى به لتبديل السمات في Vue 3 (وهي أكثر كفاءة من تبديل الأنماط)
- الأداء: الخصائص الكائنية/المحسوبة > المصفوفات > السلاسل
📝 تمارين
-
أسئلة أساسية (مستوى الصعوبة: ⭐)
استخدم محدد :class لتنفيذ ثلاث حالات للأزرار:
- الأساسي: نص أبيض على خلفية زرقاء
- النجاح: نص أبيض على خلفية خضراء
- خطر: نص أبيض على خلفية حمراء
البيانات:
const variant = ref('primary') -
مسائل متقدمة (مستوى الصعوبة: ⭐⭐)
قم بتنفيذ قائمة الطلبات بحيث يعرض كل صف شارة بلون مختلف بناءً على status الطلب:
- 5 حالات (قيد الانتظار/مدفوعة/مشحونة/مسلّمة/ملغاة)
- إرجاع كائن
classباستخدام خاصية محسوبة - :style إضافة لون الرمز المطابق للstatus
-
مسألة التحدي (مستوى الصعوبة: ⭐⭐⭐)
تنفيذ نظام كامل لتبديل السمات:
- 3 أنماط (فاتح/داكن/عالي التباين)
- استخدم متغيرات CSS لربط ألوان السمة (الأساسية/الثانوية/الخلفية/النص)
- :class — تغيير اسم فئة السمة
- استخدم localStorage لتخزين اختيار المستخدم
- لا يؤدي تغيير السمات إلى تحديث الصفحة (يتم تحديث التصميم المتجاوب تلقائيًا)