برنامه نویسی

مهارت های React خود را بالا ببرید: نمایندگی رویداد استاد برای برنامه های نرم

توضیحات:
کشف جادوی نمایندگی رویداد در React! بیاموزید که چگونه این الگوی قدرتمند سردردهای عملکرد و نگهداری مشترک را در لیست های بزرگ حل می کند ، چرا React به طور پیش فرض از آن استفاده می کند و چگونه می توان با زحمت داده ها را از عناصر کلیک بازیابی کرد.

آیا تا به حال خود را در حال ساختن لیست باشکوهی از موارد ، شاید یک مدیر وظیفه ، یک کاتالوگ تجارت الکترونیکی یا یک جدول کاربر ساده پیدا کرده و سپس به یک ضربه محکم و ناگهانی ضربه بزنید؟ شما می خواهید هر ردیف یا مورد تعاملی باشد – شاید کلیک کردن روی یک کار ، آن را کامل کند ، یا کلیک کردن روی یک محصول شما را به صفحه جزئیات آن می برد. اولین غریزه شما ، و کاملاً معتبر ، ممکن است ضمیمه آن باشد onClick کنترل کننده به هر مورد لیست.

// The "Intuitive" (but potentially problematic) way
function TaskItem({ task }) {
  const handleClick = () => {
    console.log(`Task "${task.name}" clicked!`);
    // Do something with task.id
  };

  return (
    <li onClick={handleClick}>
      {task.name}
    li>
  );
}

function TaskList({ tasks }) {
  return (
    <ul>
      {tasks.map(task => (
        <TaskItem key={task.id} task={task} />
      ))}
    ul>
  );
}
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

این کار می کند ، درست است؟ کاملا برای یک لیست کوچک از 5-10 مورد ، شما چیزی را متوجه نمی شوید. اما تصور کنید که لیست شما به صدها یا حتی هزاران مورد منفجر می شود. هر یک

  • اکنون با چمدان های خاص خود همراه است: یک شنونده اختصاصی رویداد.

    هزینه پنهان بیش از حد شنوندگان

    هنگامی که یک شنونده رویداد جداگانه را به هر عنصر وصل می کنید ، اساساً چندین هزینه پنهان را متحمل می شوید:

    • گرگ حافظه: هر شنونده رویداد مقدار کمی از حافظه را مصرف می کند. صدها یا هزاران آن را ضرب کنید و ردپای حافظه برنامه شما شروع به رشد می کند.
    • تخلیه عملکرد (تنظیم): مرورگر برای تنظیم و پاره کردن همه این شنوندگان فردی باید سخت تر کار کند. اگر لیست شما پویا باشد (موارد غالباً اضافه می شوند یا حذف می شوند) ، این سربار می تواند به یک تنگنا با عملکرد قابل توجه تبدیل شود.

    • درهم و برهمی کد: در حالی که React به انتزاع برخی از این موارد کمک می کند ، در جاوا اسکریپت وانیل ، مدیریت بسیاری از شنوندگان فردی ، به ویژه برای عناصر اضافه شده پویا ، می تواند به سرعت منجر به کد کثیف و سخت و سخت شود.

    اینجاست نمایندگی مانند یک ابرقهرمان در حال جابجایی!

    نمایندگی رویداد چیست؟ جادوی پشت صحنه

    در هسته اصلی آن ، نمایندگی رویداد یک تکنیک هوشمندانه است که از طبیعی استفاده می کند event bubbling مکانیسم DOM (مدل شیء سند).

    به حباب های رویداد مانند این فکر کنید: وقتی روی یک عنصر خاص کلیک می کنید (مثلاً یک دکمه داخل یک مورد لیست) ، این رویداد فقط روی آن دکمه اتفاق نمی افتد و متوقف می شود. این “حباب بالا” – به این معنی document وت window اشیاء

    نمایندگی رویداد با پیوست کردن مجرد شنونده رویداد به یک عنصر اجداد مشترک (والدین)، به جای اتصال شنوندگان فردی به هر کودک. هنگامی که یک رویداد در یکی از کودکان رخ می دهد ، به والدین حباب می شود. سپس شنونده والدین این رویداد را “صید” می کند و می گوید کدام کودک خاص در واقع آن را تحریک کرده است.

    چرا React عاشق نمایندگی رویداد است (و شما هم باید!)

    یکی از جالب ترین موارد در مورد React این است که به عنوان بخشی از سیستم رویداد مصنوعی خود از نمایندگی رویداد در زیر کاپوت استفاده می کند. حتی اگر بنویسید onClick در مورد عناصر JSX فردی ، React شنوندگان رویداد DOM بومی را به هر یک از آنها وصل نمی کند. درعوض ، یک شنونده رویداد سطح بالا را به ریشه برنامه React شما متصل می کند (معمولاً document شیء یا عنصری که برنامه React شما نصب شده است).

    هنگامی که یک رویداد DOM آتش می گیرد ، سیستم رویداد مصنوعی React آن را رهگیری می کند ، آن را در مرورگرهای مختلف عادی می کند و سپس آن را بر اساس درخت مؤلفه داخلی خود به اجزای React مناسب اعزام می کند. این رفتار پیش فرض به این معنی است که برنامه های React اغلب از مزایای عملکرد نمایندگی رویداد لذت می برند بدون اینکه بخواهید صریحاً آن را برای هر سناریو تنظیم کنید.

    مزایای آن واضح است:

    • عملکرد و حافظه بهینه شده: کمتر شنوندگان DOM واقعی به معنای مصرف حافظه کمتر و ارائه سریع تر هستند.
    • محتوای پویا را با زحمت کنترل می کند: اگر مواردی را از لیست خود اضافه یا حذف کنید ، شنونده مجرد به طور خودکار آنها را می پوشاند. نیازی به اضافه کردن یا حذف شنوندگان نیست!
    • پاک کننده ، کد قابل نگهداری تر: تمرکز منطق رویداد ، مؤلفه های شما را مرتب تر و اشکال زدایی آسان تر می کند.

    event.target در مقابل event.currentTarget: خصوصیات رویداد خود را بدانید!

    هنگامی که یک رویداد به شنونده نماینده شما حباب می کند ، شیء رویداد (e در e.target) دو بخش مهم اطلاعات را به شما می دهد:

    • e.target: این به عنصر دقیقی اشاره دارد که در ابتدا این رویداد را برانگیخته است. اگر روی یک کلیک کنید در داخل
    • e.currentTarget: این به عنصری است که شنونده رویداد در واقع به آن وصل شده است. اگر شنونده را به , then e.currentTarget خواهد شد , regardless of which

    • یا فرزند آن کلیک شد.

    درک این تمایز برای نمایندگی موفقیت آمیز رویداد مهم است.

    سوال میلیون دلاری: گرفتن هر شیء در ردیف در نمایندگی رویداد کلیک کنید

    بنابراین ، شما لیست خود را دریافت کرده اید ، از نمایندگی رویداد (یا به طور ضمنی با React یا صریح) استفاده می کنید ، و اکنون باید بدانید که کدام مورد خاص از آرایه شما کلیک شده است.

    این جایی است که سفارشی است data-* ویژگی ها مفید هستند!

    استراتژی:

    • یک شناسه را تعبیه کرد: هنگام ارائه هر مورد در آرایه خود ، یک شناسه منحصر به فرد (مانند شناسه یا فهرست) را در یک ویژگی داده-* در عنصر قابل کلیک قرار دهید (به عنوان مثال ،
    • یا
      ).

    • بازیابی در کنترل کننده: در کنترل کننده رویداد خود در والدین ، ​​از Event.Target استفاده کنید تا عنصری را که کلیک شده است بدست آورید و سپس برای بازیابی شناسه خود به ویژگی Dataset خود دسترسی پیدا کنید.
    • شیء را پیدا کنید: برای یافتن شیء مربوطه در آرایه داده اصلی خود از آن شناسه استفاده کنید.
    • بیایید به چند نمونه نگاه کنیم:

      مثال 1: لیست اصلی محصولات (با استفاده از data-id)

      تصور کنید که شما مجموعه ای از اشیاء محصول را دارید:

      // dummy data
      const products = [
        { id: 'p1', name: 'Laptop', price: 1200 },
        { id: 'p2', name: 'Mouse', price: 25 },
        { id: 'p3', name: 'Keyboard', price: 75 },
      ];
      

      در اینجا نحوه تنظیم نمایندگی رویداد برای دریافت محصول کلیک شده آورده شده است:

      // how product list work
      function ProductList({ products }) {
        const handleProductClick = (event) => {
          // Traverse up from event.target to find the element with data-product-id
          // This is important because the click might be on a child of the 
    • const listItem = event.target.closest('li[data-product-id]'); if (listItem) { // Ensure a list item was actually clicked const productId = listItem.dataset.productId; // Access data-product-id const clickedProduct = products.find(product => product.id === productId); if (clickedProduct) { console.log("Clicked product:", clickedProduct); // Navigate to product detail page, add to cart, etc. // Example: navigate(`/products/${clickedProduct.id}`); } } }; return ( <ul onClick={handleProductClick} style={{ cursor: 'pointer' }}> {products.map(product => ( <li key={product.id} data-product-id={product.id} style={{ padding: '8px', borderBottom: '1px solid #eee' }}> <h3>{product.name}h3> <p>${product.price}p> li> ))} ul> ); } // Usage in App.js function App() { const myProducts = [ { id: 'p1', name: 'Laptop', price: 1200 }, { id: 'p2', name: 'Mouse', price: 25 }, { id: 'p3', name: 'Keyboard', price: 75 }, { id: 'p4', name: 'Monitor', price: 300 }, { id: 'p5', name: 'Webcam', price: 50 }, ]; return ( <div> <h1>Our Productsh1> <ProductList products={myProducts} /> div> ); }
    • توضیح:

      • ما قرار دادیم onClick کنترل کننده در (the parent).
      • Each
      • می شود data-product-id ویژگی ، نگه داشتن منحصر به فرد خود product.idبشر
      • درون handleProductClick، ما استفاده می کنیم event.target.closest('li[data-product-id]')بشر این یک روش فوق العاده مفید است که به دنبال نزدیکترین اجداد (از جمله خود) است که با انتخاب CSS مطابقت دارد. این مواردی را انجام می دهد که کاربر روی آن کلیک می کند

        یا inside the

      • ، اطمینان از اینکه ما همیشه دریافت می کنیم
      • خود عنصر.
      • هنگامی که ما listItem، ما می توانیم دسترسی پیدا کنیم listItem.dataset.productId برای دریافت شناسه ما
      • بالاخره ، products.find() به ما کمک می کند تا شیء کامل محصول را از اصلی خود بازیابی کنیم products آرایه

      مثال 2: جدول تعاملی (با استفاده از data-index)

      برای جداول ، استفاده از index همچنین می تواند یک گزینه مناسب باشد ، به خصوص اگر داده های شما برای داشتن شناسه های منحصر به فرد تضمین نشده باشد ، یا اگر سفارش از اهمیت ویژه ای برخوردار باشد.

      function UserTable({ users }) {
        const handleRowClick = (event) => {
          const tableRow = event.target.closest('tr[data-user-index]');
      
          if (tableRow) {
            // data-index values are strings, so convert to number
            const userIndex = parseInt(tableRow.dataset.userIndex, 10);
            const clickedUser = users[userIndex]; // Direct access by index
      
            if (clickedUser) {
              console.log("Clicked user:", clickedUser);
              // Example: show user details modal
            }
          }
        };
      
        return (
          <table onClick={handleRowClick} style={{ width: '100%', borderCollapse: 'collapse', cursor: 'pointer' }}>
            <thead>
              <tr>
                <th>IDth>
                <th>Nameth>
                <th>Emailth>
              tr>
            thead>
            <tbody>
              {users.map((user, index) => (
                <tr key={user.id} data-user-index={index} style={{ borderBottom: '1px solid #eee' }}>
                  <td>{user.id}td>
                  <td>{user.name}td>
                  <td>{user.email}td>
                tr>
              ))}
            tbody>
          table>
        );
      }
      
      // Usage in App.js
      function App() {
        const myUsers = [
          { id: 201, name: 'Alice Smith', email: 'alice.s@example.com' },
          { id: 202, name: 'Bob Johnson', email: 'bob.j@example.com' },
          { id: 203, name: 'Charlie Brown', email: 'charlie.b@example.com' },
          { id: 204, name: 'Diana Prince', email: 'diana.p@example.com' },
        ];
      
        return (
          <div>
            <h1>User Directoryh1>
            <UserTable users={myUsers} />
          div>
        );
      }
      

      تفاوت کلیدی با data-index:

      • به جای product.id، ما استفاده می کنیم index (استدلال دوم از map).
      • ما استفاده می کنیم parseInt() چون مقادیر از dataset همیشه رشته ها هستند.
      • ما می توانیم با استفاده از شیء مستقیم به شی دسترسی پیدا کنیم users[userIndex] از آنجا که شاخص آرایه را ذخیره کردیم. این به طور کلی سریعتر از find() اما اگر سفارش آرایه پس از ارائه تغییر کند ، مقاومت کمتری دارد.

      مثال 3: رسیدگی به اقدامات خاص در یک ردیف

      اگر چندین عنصر قابل کلیک در یک ردیف واحد داشته باشید (به عنوان مثال ، “ویرایش” و “حذف دکمه ها)؟ هنوز هم می توانید از نمایندگی رویداد استفاده کنید!

      function ActionList({ items }) {
        const handleItemAction = (event) => {
          const actionButton = event.target.closest('button[data-action]');
      
          if (actionButton) {
            const itemId = actionButton.dataset.itemId; // Get item ID from button
            const actionType = actionButton.dataset.action; // Get action type (e.g., 'edit', 'delete')
      
            const targetItem = items.find(item => item.id === itemId);
      
            if (targetItem) {
              console.log(`Action: ${actionType} on item:`, targetItem);
              // Perform specific action based on actionType
              if (actionType === 'edit') {
                alert(`Editing ${targetItem.name}`);
              } else if (actionType === 'delete') {
                const confirmDelete = window.confirm(`Are you sure you want to delete ${targetItem.name}?`);
                if (confirmDelete) {
                  alert(`${targetItem.name} deleted! (simulated)`);
                }
              }
            }
          }
        };
      
        return (
          <ul onClick={handleItemAction} style={{ listStyle: 'none', padding: 0 }}>
            {items.map(item => (
              <li key={item.id} style={{ border: '1px solid #ccc', margin: '10px 0', padding: '10px' }}>
                <span>{item.name} - Status: {item.status}span>
                <div style={{ float: 'right' }}>
                  {/* Attach item ID to buttons */}
                  <button data-item-id={item.id} data-action="edit" style={{ marginRight: '5px' }}>Editbutton>
                  <button data-item-id={item.id} data-action="delete">Deletebutton>
                div>
              li>
            ))}
          ul>
        );
      }
      
      // Usage in App.js
      function App() {
        const myItems = [
          { id: 'task1', name: 'Create Blog Post', status: 'In Progress' },
          { id: 'task2', name: 'Schedule Meeting', status: 'Pending' },
          { id: 'task3', name: 'Review PR', status: 'Done' },
        ];
      
        return (
          <div>
            <h1>Task Managementh1>
            <ActionList items={myItems} />
          div>
        );
      }
      

      کلیدی از این مثال:

      • در onClick هنوز والدین است .
      • Now, the data-item-id خود دکمه ها است ، و اطمینان می دهیم که می دانیم این عمل متعلق به کدام است.
      • جدید data-action ویژگی به ما می گوید چه نوع اقدامی را باید انجام دهیم.
      • ما استفاده می کنیم event.target.closest('button[data-action]') برای اطمینان از اینکه دکمه ای را برای یک عمل در نظر گرفته ایم.
      • سپس کنترل کننده از هر دو استفاده می کند itemId وت actionType برای انجام منطق صحیح.

      افکار نهایی

      نمایندگی رویداد یک مفهوم اساسی در توسعه وب مدرن است و React آن را از طریق سیستم رویداد مصنوعی خود به زیبایی پذیرفته است. با درک چگونگی حباب وقایع و نحوه استفاده مؤثر event.target وت data-* ویژگی ها ، شما می توانید برنامه های واکنش دهنده ، قابل حفظ و ظریف تر را بنویسید ، به خصوص هنگام برخورد با لیست های بزرگ و پویا.

      بنابراین پیش بروید ، آن لیست ها را مجدداً بازپرداخت کنید و از مزایای یک تجربه کاربر نرم و صاف تر و کارآمدتر لذت ببرید!

      برنامه نویسی مبارک!

  • نوشته های مشابه

    دیدگاهتان را بنویسید

    نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

    دکمه بازگشت به بالا