React: مكونات الوظائف و«props»

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

مكونات الدوال تشبه مكعبات الليغو — فكل مكعب له شكله الخاص (الخصائص)، ويمكن تجميعها ودمجها بطرق متنوعة. والخصائص هي «واجهات» المكعبات: فأيًا كان اللون أو الحجم الذي تحددانه للمكعب، فسيظهر بهذه الصورة.


1. ما ستتعلمه



2. قصة حقيقية لفريق تطوير الواجهة الأمامية

تدفق البيانات بين المكونات والخصائص

100%
flowchart TD
    A[Parent Component] -->|"name='Alice'"| B[UserCard]
    A -->|"items=[...]"| C[ProductList]
    C -->|"item={...}"| D[ProductCard]
    B -->|"children"| E[<Avatar />]
    A -->|"onFollow callback"| B
    
    style A fill:#e3f2fd,stroke:#1565c0
    style B fill:#e8f5e9,stroke:#2e7d32
    style C fill:#fff3e0,stroke:#e65100
    style D fill:#fce4ec,stroke:#c62828

(1) المشكلة: زر يتعين عليك نسخه ولصقه 50 مرة

تشارلي هو المسؤول التقني لفريق الواجهة الأمامية. وقد اكتشف وجود أكثر من 50 زرًا مختلفًا موزعة على 20 صفحة في مستودع الكود:

JSX
// Page A:Red Button
<button style={{ backgroundColor: 'red', color: 'white' }}>
  Delete
</button>

// Page B:Blue Button
<button style={{ backgroundColor: 'blue', color: 'white' }}>
  Submit
</button>

// Page C:Small gray button
<button style={{ backgroundColor: 'gray', color: 'black', fontSize: '12px' }}>
  Cancel
</button>
▶ جرّب الكود

السؤال:

(2) نهج قائم على المكونات

الإدارة الموحدة باستخدام المكونات الوظيفية و«props»:

JSX
function Button({ variant = 'primary', size = 'medium', children }) {
  const styles = {
    primary: { backgroundColor: '#1890ff', color: 'white' },
    danger:  { backgroundColor: '#ff4d4f', color: 'white' },
    default: { backgroundColor: '#f0f0f0', color: '#333' }
  }

  return (
    <button style={{
      ...styles[variant],
      padding: size === 'large' ? '12px 24px' : '8px 16px',
      border: 'none',
      borderRadius: '6px',
      cursor: 'pointer'
    }}>
      {children}
    </button>
  )
}

// Usage:Done in one line of code
<Button variant="danger">Delete</Button>
<Button variant="primary">Submit</Button>
<Button variant="default">Cancel</Button>
▶ جرّب الكود

المزايا: تم تقليل عدد الأزرار من 50 جزءًا إلى مكون واحد؛ وأصبحت التغييرات في التصميم تتطلب تعديلاً واحدًا فقط، مما يضمن اتساق الأسلوب.



3. أساسيات مكونات الوظائف

(1) تعريف المكون

في React، يُعرف مكون الدالة بأنه دالة JavaScript تُرجع JSX.

JSX
// The Simplest Function Component
function Welcome() {
  return <h1>Hello, React!</h1>
}

// How to Write Arrow Functions(More common)
const Welcome = () => {
  return <h1>Hello, React!</h1>
}

// Implicit Return(Only one line JSX "when " can be omitted return)
const Welcome = () => <h1>Hello, React!</h1>
▶ جرّب الكود
القاعدة الوصف
كتابة الحرف الأول بحرف كبير Welcomewelcome ❌ (يميز React بين المكونات وعلامات HTML)
إرجاع JSX يجب إرجاع عنصر JSX (أو null)
الدوال النقية يجب أن تُرجع نفس المدخلات (Props) نفس المخرجات (UI)
لا يمكن تعديل الخصائص الخصائص هي للقراءة فقط ولا يمكن تعديلها داخل المكون

(2) المعلمات هي معلمات الدالة

تُعرف «البروبس» (اختصار لـ «Properties») بأنها بيانات للقراءة فقط تُمرر من مكون أب إلى مكون تابع.

JSX
// ---- Define a Component ----
function Greeting(props) {
  // props It is an object,Includes all incoming parameters
  return <h1>Hello,{props.name}!This year, you {props.age} years old。</h1>
}

// ---- Using Components ----
<Greeting name="Alice" age={28} />

// Rendering Results:
// <h1>Hello,Alice!This year, you 28 years old。</h1>
▶ جرّب الكود

(3) قواعد إزالة هيكلية الخصائص (Props)

وهناك نهج أكثر شيوعًا يُعرف بـ التعيين التفكيكي، والذي يستخرج المعلمات المطلوبة مباشرةً:

JSX
// Deconstructive Writing Style(Recommendations)
function Greeting({ name, age }) {
  return <h1>Hello,{name}!This year, you {age} years old。</h1>
}

// equivalent to:
function Greeting(props) {
  const { name, age } = props
  return <h1>Hello,{name}!This year, you {age} years old。</h1>
}
▶ جرّب الكود

4. أنواع الدعائم

نوع الكائن صيغة التمرير مثال على الاستلام ملاحظات
سلسلة name="Alice" { name } → "Alice" محاطة بعلامتي اقتباس مزدوجتين
الرقم age={30} { age } → 30 يجب استخدام {}
منطقية active / active={true} { active } → صحيح في حالة حذف القيمة، تكون القيمة الافتراضية هي «صحيح»
كائن info={{ key: 'val' }} { info } → { key: 'val' } أقواس معقوفة مزدوجة
مصفوفة items={[1, 2, 3]} { items } → [1,2,3] يجب استخدام {}
الوظيفة onClick={handler} { onClick } → fn معالج الاستدعاء/الحدث
المكون icon={<Icon />} { icon } → JSX مكون يتم عرضه ديناميكيًا

يمكن أن تقبل العناصر المساعدة أي نوع من أنواع بيانات جافا سكريبت: السلاسل، والأرقام، والقيم المنطقية، والكائنات، والمصفوفات، والدوال، وحتى المكونات الأخرى.

(1) سلسلة

يمكن تمرير السلاسل مباشرةً باستخدام علامات الاقتباس المزدوجة (تمامًا مثل سمات HTML):

JSX
function UserCard({ name, role }) {
  return (
    <div className="card">
      <h2>{name}</h2>
      <p>Characters:{role}</p>
    </div>
  )
}

// Strings are enclosed in double quotes,For other types {} Package
<UserCard name="Alice" role="Administrator" />
▶ جرّب الكود

(2) الأعداد والقيم المنطقية والكائنات

يجب أن تُحاط الأنواع غير السلسلية بعلامتي {}:

JSX
function Product({ name, price, inStock, details }) {
  return (
    <div className="product">
      <h3>{name}</h3>
      <p>Price:${price}</p>
      {/* Boolean values are used for conditional rendering */}
      {inStock ? <span>In stock ✅</span> : <span>Out of stock ❌</span>}
      {/* Object:Accessible properties */}
      <p>Category:{details.category} | Weight:{details.weight}g</p>
    </div>
  )
}

// Using Components
<Product
  name="Wireless Mouse"
  price={89}
  inStock={true}
  details={{ category: 'Peripherals', weight: 120 }}
/>
▶ جرّب الكود

(3) جدول مرجعي سريع للطرق التي تستخدم التمرير بالقيمة

النوع مثال الوصف
سلسلة name="Alice" تُكتب بنفس طريقة كتابة سمات HTML
الرقم count={42} يتطلب {}
القيمة المنطقية «true» active أو active={true} إذا تم تحديد اسم الخاصية فقط، فإن القيمة الافتراضية هي «true»
القيمة المنطقية «false» active={false} يتطلب {}
الكائن data={{ x:1, y:2 }} الأقواس المزدوجة
مصفوفة items={[1,2,3]} يتطلب {}
تعبير result={a + b} أي تعبير JS
متغير name={userName} متغير يتم تمريره بالقيمة

▶ مثال: بطاقة معلومات المستخدم

JSX 📖 للعرض فقط
// ============================================
// Example:use  Props Build a User Information Card
// Features:Display Props Transmission of Various Types
// ============================================

function UserCard({ name, age, isOnline, avatar, tags }) {
  return (
    <div style={{
      border: '1px solid #ddd',
      borderRadius: '8px',
      padding: '20px',
      maxWidth: '300px'
    }}>
      <img
        src={avatar}
        alt={name}
        style={{ width: '80px', height: '80px', borderRadius: '50%' }}
      />
      <h2>{name}</h2>
      <p>Age:{age} years old</p>
      <p>
        Status:
        <span style={{ color: isOnline ? '#52c41a' : '#999' }}>
          {isOnline ? 'Online' : 'Offline'}
        </span>
      </p>
      <div>
        Tags:
        {tags.map(tag => (
          <span key={tag} style={{
            background: '#f0f0f0',
            padding: '2px 8px',
            borderRadius: '4px',
            margin: '0 4px',
            fontSize: '12px'
          }}>
            {tag}
          </span>
        ))}
      </div>
    </div>
  )
}

// Using Components
<UserCard
  name="Alice"
  age={28}
  isOnline={true}
  avatar="https://i.pravatar.cc/80"
  tags={['Front End', 'React', 'TypeScript']}
/>
45 سطر من الكود المنطقي (تجاوز الحد 40, للعرض فقط)

5. العناصر التابعة والقيم الافتراضية

(1) children: محتوى متداخل داخل المكون

children هو عنصر خاص يمثل المحتوى الموجود بين علامتي component.

JSX
// Definition:use  children Content between tags
function Card({ children, title }) {
  return (
    <div style={{ border: '1px solid #ddd', padding: '16px', borderRadius: '8px' }}>
      <h3>{title}</h3>
      <div>{children}</div>  {/* The content between the tags is displayed here */}
    </div>
  )
}

// Usage:The content between the tags automatically becomes children
<Card title="Announcement">
  <p>The system will go live tonight 22:00 Perform maintenance,Expected to continue 2 hours。</p>
  <p>Please save your work in advance.,To prevent data loss。</p>
</Card>

// Rendering Results:
// <div class="card">
//   <h3>Announcement</h3>
//   <div>
//     <p>The system will go live tonight 22:00 Perform maintenance...</p>
//     <p>Please save your work in advance....</p>
//   </div>
// </div>
▶ جرّب الكود

(2) القيمة الافتراضية

استخدم صيغة تفكيك ES6 مع القيم الافتراضية لتعيين قيم افتراضية لـ props:

JSX
function Button({ text = 'Click', color = 'blue', size = 'medium' }) {
  return (
    <button style={{
      backgroundColor: color,
      padding: size === 'large' ? '12px 24px' : '8px 16px',
      color: 'white',
      border: 'none',
      borderRadius: '4px'
    }}>
      {text}
    </button>
  )
}

// No parameters → Use the default values
<Button />                    // Blue、medium、"Click"

// Pass some parameters → Override the default value
<Button text="Submit" />        // Blue、medium、"Submit"
<Button color="red" size="large" />  // Red、large、"Click"
▶ جرّب الكود

6. تعليقات أنواع TypeScript (نظرة عامة)

باستخدام TypeScript، يمكنك تعريف أنواع صارمة لـ props، مما يمكّن المحرر من تقديم اقتراحات الإكمال التلقائي وإجراء عمليات التحقق من الأنواع:

TSX
// ---- Definition Props Type ----
interface ButtonProps {
  text: string           // Required:string
  color?: string         // Optional: add ? suffix
  size?: 'small' | 'medium' | 'large'  // Optional: limited to 3 values
  onClick: () => void    // Required:Function Types
  disabled?: boolean     // Optional: boolean, defaults to false
}

// ---- Using in a component ----
function Button({ text, color = 'blue', size = 'medium', onClick, disabled = false }: ButtonProps) {
  return (
    <button
      onClick={onClick}
      disabled={disabled}
      style={{
        backgroundColor: color,
        padding: size === 'large' ? '12px 24px' : '8px 16px',
        opacity: disabled ? 0.5 : 1,
        color: 'white',
        border: 'none',
        borderRadius: '4px'
      }}
    >
      {text}
    </button>
  )
}

// Usage:The editor provides smart suggestions
<Button
  text="Save"
  color="#1890ff"
  size="medium"
  onClick={() => alert('Saved successfully!')}
/>

// ❌ Error:TypeScript It will throw an error
<Button text="Test" />  // Required field is missing onClick
<Button text="Test" size="xl" onClick={fn} />  // size Outside the permitted range


7. مثال كامل: مكون «بطاقة المنتج»

TSX
// ============================================
// Example:Product Card Component(Comprehensive Application Props Various Types)
// ============================================

// Type Definitions
interface Product {
  id: number
  name: string
  price: number
  image: string
  category: string
  tags: string[]
}

interface ProductCardProps {
  product: Product
  onAddToCart: (productId: number) => void
  showDiscount?: boolean
  size?: 'small' | 'large'
}

// Component Implementation
function ProductCard({
  product,
  onAddToCart,
  showDiscount = false,
  size = 'large'
}: ProductCardProps) {
  return (
    <div style={{
      border: '1px solid #eee',
      borderRadius: '8px',
      padding: size === 'large' ? '16px' : '10px',
      width: size === 'large' ? '280px' : '200px'
    }}>
      <img
        src={product.image}
        alt={product.name}
        style={{ width: '100%', height: '150px', objectFit: 'cover' }}
      />
      <h3>{product.name}</h3>
      <p style={{ color: '#ff4d4f', fontSize: '20px', fontWeight: 'bold' }}>
        ${product.price}
        {showDiscount && <span style={{ fontSize: '12px', color: '#999', textDecoration: 'line-through', marginLeft: '8px' }}>${(product.price * 1.2).toFixed(0)}</span>}
      </p>
      <p style={{ color: '#666', fontSize: '14px' }}>{product.category}</p>
      <div>
        {product.tags.map(tag => (
          <span key={tag} style={{ background: '#f0f5ff', color: '#1890ff', padding: '2px 6px', borderRadius: '4px', margin: '0 2px', fontSize: '12px' }}>
            {tag}
          </span>
        ))}
      </div>
      <button
        onClick={() => onAddToCart(product.id)}
        style={{
          width: '100%',
          padding: '8px',
          marginTop: '10px',
          backgroundColor: '#1890ff',
          color: 'white',
          border: 'none',
          borderRadius: '4px',
          cursor: 'pointer'
        }}
      >
        Add to Cart
      </button>
    </div>
  )
}

// Using Components
const myProduct = {
  id: 101,
  name: 'Mechanical Keyboard',
  price: 299,
  image: 'https://via.placeholder.com/280x150',
  category: 'Computer Peripherals',
  tags: ['Hot Seller', 'New Products']
}

<ProductCard
  product={myProduct}
  onAddToCart={(id) => console.log('Add to Cart:', id)}
  showDiscount={true}
/>

النتيجة المتوقعة: بطاقة منتج تعرض صورة لوحة مفاتيح، واسم «لوحة مفاتيح ميكانيكية»، والسعر 299 دولارًا (مع خط مشطوب يشير إلى السعر الأصلي البالغ 359 دولارًا)، والفئة «ملحقات الكمبيوتر»، والعلامات «منتج مبيعًا» و«وصول جديد»، مع زر أزرق «إضافة إلى سلة التسوق» أسفلها.


▶ المثال 2: الاستخدام الشامل لتمرير أنواع المعلمات والقيم الافتراضية

JSX
// ============================================
// Example:Profile Card——Props Combined Use of Types and Default Values
// Features:Display string、number、boolean、object、function etc. Props Type Passing
// ============================================

function ProfileCard({
  name = 'Anonymous User',
  age = 0,
  isActive = false,
  avatar = 'https://via.placeholder.com/60',
  skills = [],
  onGreet
}) {
  return (
    <div style={{
      border: '1px solid #e8e8e8',
      borderRadius: '12px',
      padding: '20px',
      maxWidth: '320px',
      boxShadow: '0 2px 8px rgba(0,0,0,0.06)'
    }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: '16px', marginBottom: '16px' }}>
        <img
          src={avatar}
          alt={name}
          style={{ width: '60px', height: '60px', borderRadius: '50%', objectFit: 'cover' }}
        />
        <div>
          <h3 style={{ margin: 0 }}>{name}</h3>
          <p style={{ margin: '4px 0 0 0', color: '#666', fontSize: '14px' }}>
            {age} years old · {isActive ? '🟢 Online' : '🔴 Offline'}
          </p>
        </div>
      </div>

      {skills.length > 0 && (
        <div style={{ marginBottom: '12px' }}>
          <p style={{ margin: '0 0 8px 0', fontWeight: 'bold', fontSize: '14px' }}>Skills:</p>
          <div style={{ display: 'flex', flexWrap: 'wrap', gap: '6px' }}>
            {skills.map((skill, index) => (
              <span key={index} style={{
                backgroundColor: '#f0f5ff',
                color: '#1890ff',
                padding: '4px 10px',
                borderRadius: '12px',
                fontSize: '12px'
              }}>
                {skill}
              </span>
            ))}
          </div>
        </div>
      )}

      {onGreet && (
        <button
          onClick={() => onGreet(name)}
          style={{
            width: '100%',
            padding: '8px',
            backgroundColor: '#1890ff',
            color: 'white',
            border: 'none',
            borderRadius: '6px',
            cursor: 'pointer',
            fontSize: '14px'
          }}
        >
          Say hello to {name}
        </button>
      )}
    </div>
  )
}

// Usage:Pass all parameters
<ProfileCard
  name="Alice"
  age={28}
  isActive={true}
  avatar="https://i.pravatar.cc/60"
  skills={['React', 'TypeScript', 'Node.js']}
  onGreet={(name) => alert(`Hello,${name}!`)}
/>

// Usage:Pass only some parameters(Use the default values for the rest)
<ProfileCard
  name="Bob"
  skills={['Vue', 'Python']}
/>

// Usage:Do not pass any parameters(Use all default values)
<ProfileCard />

▶ المثال 3: خصائص استدعاء رد الفعل للأحداث — المكونات الفرعية تُخطر المكونات الرئيسية

JSX
function AddToCartButton({ productName, onAdd }) {
  const [adding, setAdding] = useState(false)

  async function handleClick() {
    setAdding(true)
    await onAdd(productName)
    setAdding(false)
  }

  return (
    <button onClick={handleClick} disabled={adding}
      style={{ padding: '8px 16px', cursor: adding ? 'wait' : 'pointer' }}>
      {adding ? 'Adding...' : `Add ${productName}`}
    </button>
  )
}

function ProductPage() {
  const [cart, setCart] = useState([])

  function handleAdd(name) {
    setCart(prev => [...prev, name])
  }

  return (
    <div>
      <h2>Products</h2>
      <AddToCartButton productName="Keyboard" onAdd={handleAdd} />
      <AddToCartButton productName="Mouse" onAdd={handleAdd} />
      <p>Cart: {cart.join(', ') || 'empty'}</p>
    </div>
  )
}
▶ جرّب الكود

▶ المثال 4: العرض الشرطي لخصائص المكونات — التبديل الديناميكي بين المكونات

JSX
function StatusMessage({ status }) {
  const config = {
    loading: { icon: '⏳', color: '#1890ff', text: 'Loading...' },
    success: { icon: '✅', color: '#52c41a', text: 'Success!' },
    error:   { icon: '❌', color: '#ff4d4f', text: 'Error occurred' },
    empty:   { icon: '📭', color: '#999', text: 'No data' },
  }
  const { icon, color, text } = config[status] || config.empty

  return (
    <div style={{ padding: 16, textAlign: 'center', color }}>
      <span style={{ fontSize: 32 }}>{icon}</span>
      <p>{text}</p>
    </div>
  )
}

function DataViewer() {
  const [status, setStatus] = useState('loading')
  return (
    <div style={{ maxWidth: 300, margin: '0 auto' }}>
      <StatusMessage status={status} />
      <div style={{ display: 'flex', gap: 4 }}>
        {['loading', 'success', 'error', 'empty'].map(s => (
          <button key={s} onClick={() => setStatus(s)}
            style={{ padding: '4px 8px', cursor: 'pointer', fontSize: 12 }}>
            {s}
          </button>
        ))}
      </div>
    </div>
  )
}
▶ جرّب الكود

▶ المثال 5: نمط renderProps — مكونات القوائم والعرض المخصص

JSX
function DataList({ items, renderItem, keyExtractor, emptyMessage = 'No items' }) {
  if (!items || items.length === 0) {
    return <p style={{ color: '#999', textAlign: 'center', padding: 20 }}>{emptyMessage}</p>
  }

  return (
    <ul style={{ listStyle: 'none', padding: 0 }}>
      {items.map(item => (
        <li key={keyExtractor(item)} style={{ borderBottom: '1px solid #f0f0f0', padding: 8 }}>
          {renderItem(item)}
        </li>
      ))}
    </ul>
  )
}

function App() {
  const users = [
    { id: 1, name: 'Alice', email: 'alice@example.com', active: true },
    { id: 2, name: 'Bob', email: 'bob@example.com', active: false },
    { id: 3, name: 'Charlie', email: 'charlie@example.com', active: true },
  ]

  const products = [
    { id: 'a', name: 'Keyboard', price: 79 },
    { id: 'b', name: 'Monitor', price: 399 },
  ]

  return (
    <div style={{ maxWidth: 400, margin: '0 auto' }}>
      <h3>Users</h3>
      <DataList
        items={users}
        keyExtractor={u => u.id}
        renderItem={u => (
          <div style={{ display: 'flex', justifyContent: 'space-between' }}>
            <span>{u.name} ({u.email})</span>
            <span style={{ color: u.active ? '#52c41a' : '#999' }}>
              {u.active ? 'Active' : 'Inactive'}
            </span>
          </div>
        )}
      />
      <h3>Products</h3>
      <DataList
        items={products}
        keyExtractor={p => p.id}
        emptyMessage="No products available"
        renderItem={p => (
          <span>{p.name} - ${p.price}</span>
        )}
      />
    </div>
  )
}


❓ أسئلة شائعة

س لماذا تعتبر خصائص props للقراءة فقط؟ ألا يمكن تعديلها مباشرةً؟
ج تتمثل فلسفة تصميم React في «تدفق البيانات أحادي الاتجاه» — حيث تتدفق البيانات من المكونات الأبوية إلى المكونات الفرعية، ولا يمكن للمكونات الفرعية تعديل بيانات المكون الأبوي. وإذا احتاج مكون تابع إلى تعديل البيانات، فيجب عليه إخطار المكون الأصلي للقيام بذلك عبر دالة استدعاء مرتدة (callback) يتم تمريرها عبر الخصائص (للحفاظ على «مصدر وحيد للحقيقة»). وهذا يضمن تدفقًا واضحًا للبيانات، مما يسهل عملية تصحيح الأخطاء والصيانة.
س ما الفرق بين «props» و«state»؟
ج يتم تمرير «props» من الخارج وهي قابلة للقراءة فقط؛ أما «state» فتديرها المكونة داخليًّا وهي قابلة للتغيير. يمكنك اعتبار «props» بمثابة «معلمات التكوين» للمكونة و«state» بمثابة «حالتها الداخلية». إذا تغيرت «props»، يتم إعادة عرض المكونة؛ وإذا تغيرت «state»، يتم إعادة عرض المكونة.
س هل يجب أن تكون أسماء المكونات بأحرف كبيرة؟ ماذا يحدث إذا كانت بأحرف صغيرة؟
ج يجب أن تكون بأحرف كبيرة. يميز React بين المكونات وعلامات HTML بناءً على استخدام الأحرف الكبيرة: <div> هي علامة div في HTML؛ <Div> هو مكون مخصص. إذا كُتب اسم المكون بأحرف صغيرة، فسيتعامل React معه على أنه علامة HTML، مما يؤدي إلى فشل عملية العرض.
س إلى أي عمق يمكن تداخل المكونات؟ هل هناك أي قيود؟
ج لا توجد قيود تقنية، لكننا نوصي بعدم تجاوز 3–4 مستويات. فقد يؤدي التداخل المفرط إلى تعقيد عملية تمرير البيانات (props drilling) وتقليل قابلية قراءة الكود. إذا كنت بحاجة إلى تمرير البيانات عبر مستويات متعددة، ففكر في استخدام واجهة برمجة تطبيقات Context (الدرس 13) أو إدارة الحالة العامة (الدرس 18).
س كيف أقوم بتعيين القيم الافتراضية للـ props؟
ج هناك طريقتان: ① تعيين القيم الافتراضية أثناء عملية تفكيك function Card({ title = 'Untitled' }) {}؛ ② استخدام Card.defaultProps = { title: 'Untitled' }. لاحظ أن React لم تعد توصي باستخدام defaultProps (في مكونات الدالة)؛ ويُنصح باستخدام عملية التفكيك لتعيين القيم الافتراضية. في TypeScript، يمكنك أيضًا استخدام title?: string للإشارة إلى أن الخاصية اختيارية، مما يجعل الكود أكثر وضوحًا عند دمجه مع تفكيك المتغيرات لتعيين القيم الافتراضية.

📖 ملخص


📝 تمارين

  1. المشكلة الأساسية (مستوى الصعوبة ⭐): أنشئ مكونًا باسم Avatar يقبل خاصيتين — name (سلسلة نصية) وsize (رقم، القيمة الافتراضية 50) — ويعرض الصورة الرمزية للمستخدم واسمه.
  2. مشكلة متقدمة (درجة الصعوبة ⭐⭐): أنشئ مكونًا TagList يقبل خاصيتين — tags (مصفوفة من السلاسل) وonRemove (دالة) — ويعرض قائمة من العلامات. يؤدي النقر على أي علامة إلى حذفها.
  3. التحدي (الصعوبة ⭐⭐⭐): قم بإنشاء مكون DataTable بلغة TypeScript يقبل columns (مصفوفة من تعريفات الأعمدة) وdata (مصفوفة من البيانات) ويعرض جدول بيانات بسيطًا. حاول إضافة خاصية striped (من نوع Boolean، اختيارية) للتحكم في نمط الزبرا.
Web-Tutorial.com

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

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

100%