چرا InnerBlocks در وردپرس کلید ساخت بلاک‌های حرفه‌ای است؟ پاسخ در این حقیقت نهفته است که InnerBlocks به یک بلاک اجازه می‌دهد بلاک‌های دیگر را درون خود جای دهد و یک ساختار درختی از محتوا بسازد، دقیقاً همان چیزی که بلاک‌های هسته‌ای مانند Columns، Group و Cover از آن استفاده می‌کنند. بدون InnerBlocks، هر بلاک تنها یک واحد ایزوله باقی می‌ماند و ساخت ترکیب‌های پیچیده غیرممکن می‌شود. این API با ارائه template، allowedBlocks و useInnerBlocksProps، معماری بلاک‌های تودرتو (Nested Blocks) را ممکن می‌سازد. در این مقاله معماری، کاربردها، الگوهای طراحی، اشتباهات رایج و نکات پیشرفته InnerBlocks را با مثال‌های عملی بررسی می‌کنیم.

InnerBlocks در وردپرس یک API بومی برای ساخت بلاک‌هایی است که می‌توانند بلاک‌های دیگر را درون خود جای دهند، و همین ویژگی آن را به کلید ساخت بلاک‌های حرفه‌ای و ترکیبی تبدیل کرده است.

این API با ارائه پراپ‌هایی مانند template، allowedBlocks و templateLock، کنترل کامل روی ساختار درونی بلاک را در اختیار توسعه‌دهنده قرار می‌دهد.

بلاک‌های هسته‌ای وردپرس مانند Columns، Group، Cover و Media & Text همگی بر پایه InnerBlocks ساخته شده‌اند و درک آن‌ها بدون تسلط بر این API ممکن نیست.

در این مقاله معماری InnerBlocks، تفاوت آن با بلاک‌های ساده، الگوهای طراحی حرفه‌ای، اشتباهات رایج و نکات پیشرفته را با مثال‌های واقعی بررسی می‌کنیم.

هدف این است که پس از مطالعه، بتوانید بلاک‌هایی بسازید که به‌اندازه بلاک‌های هسته‌ای منعطف، پایدار و قابل نگهداری باشند.

نخستین باری که یک بلاک ترکیبی بدون InnerBlocks ساختم، به یک بن‌بست معماری رسیدم: هر بلاک فقط می‌توانست یک واحد ثابت باشد و امکان ترکیب دلخواه محتوا درون آن وجود نداشت. آن تجربه باعث شد که به‌سراغ InnerBlocks بروم و از آن زمان، این API به یکی از ابزارهای اصلی در ساخت بلاک‌های سفارشی تبدیل شده است. آنچه در ادامه می‌خوانید حاصل کار عملی با این API در پروژه‌های واقعی و بررسی کد منبع گوتنبرگ است.

InnerBlocks چیست و چرا بدون آن بلاک حرفه‌ای وجود ندارد؟

InnerBlocks یک کامپوننت React است که در پکیج @wordpress/block-editor قرار دارد و به یک بلاک اجازه می‌دهد بلاک‌های دیگر را درون خود جای دهد. این کامپوننت دقیقاً همان چیزی است که بلاک‌های هسته‌ای مانند Columns، Group، Cover و Media & Text از آن استفاده می‌کنند. بدون InnerBlocks، یک بلاک تنها می‌تواند محتوای ثابت خود را نمایش دهد و امکان ترکیب با سایر بلاک‌ها را ندارد. برای آشنایی با مبانی ساخت بلاک، مقاله آموزش ساخت بلوک سفارشی گوتنبرگ را مطالعه کنید.

تفاوت اصلی میان یک بلاک ساده و یک بلاک دارای InnerBlocks در مدل داده آن‌هاست. یک بلاک ساده تمام محتوای خود را در ویژگی‌های (Attributes) خود ذخیره می‌کند، در حالی که یک بلاک دارای InnerBlocks محتوای درونی خود را به‌صورت بلاک‌های جداگانه در ساختار HTML نگه می‌دارد. این ساختار درخت‌گونه (Tree Structure) به کاربر اجازه می‌دهد تا درون یک بلاک، بلاک‌های دیگر را درج، جابه‌جا یا حذف کند، دقیقاً همان‌طور که در ویرایشگر اصلی این کار را انجام می‌دهد.

InnerBlocks یک بلاک را از یک واحد ثابت به یک ظرف (Container) تبدیل می‌کند که کاربر می‌تواند محتوای درون آن را آزادانه شکل دهد.

نکته مهمی که در بررسی‌های خود به آن پی بردم این است که InnerBlocks تنها یک کامپوننت ظاهری نیست؛ بلکه یک قرارداد معماری است که تعیین می‌کند چگونه محتوای یک بلاک در پایگاه داده ذخیره شود. برخلاف بلاک‌های ساده که محتوای خود را در Attributes نگه می‌دارند، بلاک‌های دارای InnerBlocks محتوای درونی خود را به‌صورت HTML سریالایز شده در تگ‌های والد ذخیره می‌کنند. این تفاوت در نحوه ذخیره‌سازی، پیامدهای مهمی برای مهاجرت، اعتبارسنجی و بهینه‌سازی دارد.

برای درک بهتر جایگاه InnerBlocks در اکوسیستم گوتنبرگ، مقاله گوتنبرگ و آینده ویرایش محتوا در وردپرس را ببینید.

چرا InnerBlocks ستون فقرات بلاک‌های ترکیبی است؟

بلاک‌های ترکیبی (Composite Blocks) بلاک‌هایی هستند که از ترکیب چند بلاک ساده ساخته می‌شوند. برای مثال، یک بلاک Hero معمولاً شامل یک تصویر پس‌زمینه، یک عنوان، یک پاراگراف توضیحی و یک دکمه فراخوانی به اقدام است. اگر این بلاک بدون InnerBlocks ساخته شود، هر یک از این اجزا باید در Attributes جداگانه ذخیره شوند و امکان ویرایش مستقل آن‌ها وجود نخواهد داشت. اما با InnerBlocks، هر یک از این اجزا یک بلاک مستقل است که کاربر می‌تواند آن را ویرایش، جابه‌جا یا حتی حذف کند.

این انعطاف‌پذیری برای تجربه کاربری ویرایشگر حیاتی است. کاربری که با ویرایشگر بلوک کار می‌کند، انتظار دارد که بتواند درون یک بلاک، بلاک‌های دیگر را درج کند و رفتار ویرایشگر را دقیقاً مشابه سطح بالایی داشته باشد. InnerBlocks این انتظار را برآورده می‌کند و به کاربر امکان می‌دهد تا درون یک بلاک، از تمام قابلیت‌های ویرایشگر بلوک استفاده کند.

از منظر معماری نرم‌افزار، InnerBlocks یک پیاده‌سازی از الگوی Composite است. در این الگو، یک شیء (بلاک والد) می‌تواند مجموعه‌ای از اشیاء مشابه (بلاک‌های فرزند) را در خود جای دهد و همان رابط را با آن‌ها به اشتراک بگذارد. این الگو به‌طور طبیعی با ساختار درختی DOM سازگاری دارد و در ویرایشگر بلوک به‌صورت کامل پیاده‌سازی شده است. برای مطالعه بیشتر درباره ری‌اکت و کامپوننت‌ها، مقاله React از صفر: ساخت رابط‌های کاربری تعاملی را ببینید.

علاوه بر این، InnerBlocks امکان ساخت بلاک‌هایی را فراهم می‌کند که به‌اندازه بلاک‌های هسته‌ای وردپرس منعطف و قدرتمند باشند. توسعه‌دهندگانی که می‌خواهند یک افزونه حرفه‌ای بسازند، معمولاً به InnerBlocks نیاز پیدا می‌کنند. مقاله چگونه یک افزونه حرفه‌ای وردپرس بسازیم؟ به این موضوع می‌پردازد.

معماری InnerBlocks و مدل داده

برای درک عمیق InnerBlocks، باید معماری و مدل داده آن را بررسی کنیم. این API بر پایه چند مفهوم بنیادین بنا شده است که درک هر یک برای کار حرفه‌ای با آن ضروری است.

ساختار سریالایز شده

هنگامی که یک بلاک دارای InnerBlocks در ویرایشگر ذخیره می‌شود، محتوای درونی آن به‌صورت یک رشته HTML سریالایز شده ذخیره می‌گردد. این ساختار مشابه ساختار بلاک‌های هسته‌ای است و از همان قواعد سریالایز کردن بلاک‌ها پیروی می‌کند.

<!-- wp:my-plugin/hero -->
<div class="wp-block-my-plugin-hero">
  <!-- wp:image {"id":123} /-->
  <!-- wp:heading {"level":1} -->
  <h1>عنوان نمونه</h1>
  <!-- /wp:heading -->
  <!-- wp:paragraph -->
  <p>متن توضیحی</p>
  <!-- /wp:paragraph -->
</div>
<!-- /wp:my-plugin/hero -->

در این ساختار، بلاک والد (my-plugin/hero) محتوای درونی خود را به‌صورت تگ‌های HTML نگه می‌دارد. هر بلاک فرزند نیز به‌صورت یک کامنت HTML با نام بلاک و ویژگی‌های آن نمایش داده می‌شود. این ساختار در واقع یک درخت از بلاک‌ها را تشکیل می‌دهد که ویرایشگر می‌تواند آن را به‌درستی بازخوانی کند.

Block Context و دسترسی فرزندان به والد

یکی از ویژگی‌های مهم InnerBlocks، امکان دسترسی بلاک‌های فرزند به اطلاعات بلاک والد است. این کار از طریق مفهوم Block Context انجام می‌شود. برای مثال، بلاک Image درون یک بلاک Cover می‌تواند از Context استفاده کند تا اندازه بلاک والد را بفهمد. این مکانیزم به بلاک‌های فرزند اجازه می‌دهد که رفتار خود را بر اساس موقعیتشان تنظیم کنند. برای مطالعه بیشتر درباره مدیریت state در گوتنبرگ، مقاله Data API در وردپرس چیست و چطور state بلاک‌ها را مدیریت می‌کند؟ را ببینید.

رابطه با Synced Patterns

InnerBlocks و Synced Patterns دو مفهوم مکمل در گوتنبرگ هستند. InnerBlocks امکان ساخت بلاک‌های ترکیبی را فراهم می‌کند، در حالی که Synced Patterns امکان اشتراک یک الگو در چندین صفحه را ممکن می‌سازد. ترکیب این دو می‌تواند به ساخت بلاک‌هایی منجر شود که هم منعطف و هم همگام باشند. مقاله Synced Patterns در وردپرس چطور محتوا را در چند صفحه هماهنگ می‌کند؟ به این موضوع می‌پردازد.

استفاده پایه از InnerBlocks در یک بلاک سفارشی

برای شروع کار با InnerBlocks، ابتدا باید یک بلاک سفارشی تعریف کنید. در ادامه، یک بلاک ساده را بررسی می‌کنیم که از InnerBlocks برای جای دادن بلاک‌های درونی استفاده می‌کند.

import { registerBlockType } from '@wordpress/blocks';
import { InnerBlocks, useBlockProps } from '@wordpress/block-editor';

registerBlockType( 'my-plugin/simple-container', {
  title: 'Simple Container',
  icon: 'layout',
  category: 'design',
  edit: () => {
    const blockProps = useBlockProps( {
      className: 'my-simple-container',
    } );
    return (
      <div { ...blockProps }>
        <InnerBlocks />
      </div>
    );
  },
  save: () => {
    const blockProps = useBlockProps.save( {
      className: 'my-simple-container',
    } );
    return (
      <div { ...blockProps }>
        <InnerBlocks.Content />
      </div>
    );
  },
} );

در این کد، دو نکته مهم وجود دارد. اول، در تابع edit از کامپوننت <InnerBlocks /> استفاده می‌شود که به کاربر اجازه می‌دهد در ویرایشگر، بلاک‌های درونی را اضافه یا ویرایش کند. دوم، در تابع save از <InnerBlocks.Content /> استفاده می‌شود که محتوای سریالایز شده بلاک‌های درونی را در خروجی ذخیره می‌کند. این تفکیک میان ویرایش و ذخیره‌سازی، یکی از اصول بنیادین کار با InnerBlocks است.

InnerBlocks در ویرایشگر نمایش داده می‌شود، اما InnerBlocks.Content آن است که در پایگاه داده ذخیره می‌گردد.

نکته مهم دیگر، استفاده از useBlockProps است. این هوک وظیفه دارد کلاس‌ها، استایل‌ها و ویژگی‌های لازم بلاک را فراهم کند. بدون استفاده از این هوک، بلاک شما ممکن است در ویرایشگر به‌درستی نمایش داده نشود یا در فرانت‌اند کلاس‌های لازم را نداشته باشد. برای آشنایی با هوک‌ها در ری‌اکت، مقاله چرا React Hooks نحوه نوشتن کامپوننت‌ها را متحول کرد؟ را ببینید.

پراپ template: تعریف ساختار اولیه

یکی از قدرتمندترین ویژگی‌های InnerBlocks، پراپ template است که به شما اجازه می‌دهد یک ساختار اولیه برای بلاک‌های درونی تعریف کنید. این پراپ یک آرایه از آرایه‌هاست که هر آرایه نشان‌دهنده یک بلاک با نام و ویژگی‌های آن است.

const TEMPLATE = [
  [ 'core/image', { align: 'wide' } ],
  [ 'core/heading', { level: 2, placeholder: 'عنوان را وارد کنید' } ],
  [ 'core/paragraph', { placeholder: 'توضیحات...' } ],
  [ 'core/buttons', {},
    [
      [ 'core/button', { text: 'بیشتر بدانید' } ],
    ],
  ],
];

<InnerBlocks
  template={ TEMPLATE }
  templateLock="all"
/>

در این کد، یک ساختار اولیه شامل تصویر، عنوان، پاراگراف و یک دکمه تعریف شده است. هرگاه کاربر یک بلاک از این نوع درج کند، این ساختار به‌طور خودکار در ویرایشگر ظاهر می‌شود و کاربر می‌تواند محتوای هر بلاک را ویرایش کند. توجه کنید که آرایه چهارم شامل یک بلاک Buttons است که خودش دارای InnerBlocks است. این نمونه‌ای از بلاک‌های تودرتو است که در ادامه به آن می‌پردازیم.

پراپ template می‌تواند به‌صورت داینامیک نیز تولید شود. برای مثال، اگر بلاکی دارید که بر اساس ویژگی‌های خود، ساختار درونی متفاوتی نیاز دارد، می‌توانید template را در تابع edit محاسبه کنید. این انعطاف‌پذیری به شما امکان می‌دهد بلاک‌هایی بسازید که رفتارشان بر اساس context تغییر می‌کند.

پراپ allowedBlocks: کنترل بلاک‌های مجاز

پراپ allowedBlocks به شما اجازه می‌دهد تعیین کنید که کاربر تنها مجاز به درج چه بلاک‌هایی درون بلاک والد است. این پراپ یک آرایه از نام بلاک‌ها را دریافت می‌کند و هر بلاکی که در این آرایه نباشد، در پنجره درج بلاک نمایش داده نمی‌شود.

<InnerBlocks
  allowedBlocks={ [
    'core/heading',
    'core/paragraph',
    'core/image',
    'core/list',
  ] }
/>

این پراپ به‌ویژه برای بلاک‌هایی مفید است که ساختار مشخصی دارند و نباید با بلاک‌های نامرتبط پر شوند. برای مثال، یک بلاک Hero نباید اجازه دهد کاربر یک بلاک Gallery درون آن درج کند. با استفاده از allowedBlocks، می‌توانید تجربه کاربری را بهبود بخشید و از خطاهای احتمالی جلوگیری کنید.

نکته مهم این است که allowedBlocks تنها بر ویرایشگر تأثیر می‌گذارد. اگر بلاکی که در allowedBlocks تعریف نشده باشد، به‌صورت برنامه‌نویسی در محتوای سریالایز شده وجود داشته باشد، همچنان در فرانت‌اند نمایش داده می‌شود. بنابراین، این پراپ یک محدودیت ویرایشی است، نه یک محدودیت امنیتی. برای مطالعه بیشتر درباره اعتبارسنجی و امنیت، مقاله چرا HTML API در وردپرس امن‌ترین راه پردازش HTML است؟ را ببینید.

templateLock و انواع قفل ساختار

پراپ templateLock کنترل می‌کند که کاربر تا چه حد می‌تواند ساختار بلاک‌های درونی را تغییر دهد. این پراپ سه مقدار ممکن دارد:

  • false: بدون قفل. کاربر می‌تواند بلاک‌ها را اضافه، حذف یا جابه‌جا کند.
  • all: قفل کامل. ساختار template قابل تغییر نیست و کاربر نمی‌تواند بلاک اضافه یا حذف کند.
  • insert: قفل درج. کاربر می‌تواند بلاک‌های موجود را جابه‌جا یا حذف کند، اما نمی‌تواند بلاک جدید اضافه کند.

انتخاب مقدار مناسب templateLock به ماهیت بلاک بستگی دارد. برای بلاک‌هایی که ساختارشان باید ثابت باشد (مانند یک بلاک Hero با ساختار مشخص)، all انتخاب مناسبی است. برای بلاک‌هایی که باید انعطاف‌پذیری داشته باشند، false انتخاب بهتری است.

توجه داشته باشید که templateLock تنها بر ویرایشگر تأثیر می‌گذارد. اگر محتوای بلاک به‌صورت برنامه‌نویسی تغییر کند، این قفل اعمال نمی‌شود. بنابراین، این پراپ یک محدودیت ویرایشی است، نه یک محدودیت امنیتی. برای مطالعه بیشتر درباره اصول کدنویسی امن، مقاله هوک‌های وردپرس: قلب تپنده توسعه را ببینید.

useInnerBlocksProps و رندر سفارشی

در بسیاری از مواقع، ممکن است بخواهید بلاک‌های درونی را درون یک عنصر HTML خاص رندر کنید یا ویژگی‌های خاصی به آن اضافه کنید. برای این کار، وردپرس هوک useInnerBlocksProps را در اختیار قرار می‌دهد.

import { useBlockProps, useInnerBlocksProps } from '@wordpress/block-editor';

const Edit = () => {
  const blockProps = useBlockProps();
  const innerBlocksProps = useInnerBlocksProps( blockProps, {
    allowedBlocks: [ 'core/paragraph', 'core/heading' ],
  } );

  return <div { ...innerBlocksProps } />;
};

در این کد، useInnerBlocksProps ویژگی‌های بلاک والد و InnerBlocks را در یک شیء ادغام می‌کند و آن را به یک عنصر HTML اعمال می‌نماید. این رویکرد باعث می‌شود که کد تمیزتر و خواناتر باشد و از تکرار ویژگی‌ها جلوگیری شود.

استفاده از useInnerBlocksProps به‌ویژه زمانی مفید است که بخواهید بلاک والد را با یک عنصر HTML خاص (مانند section یا article) رندر کنید. این رویکرد با اصول HTML معنایی (Semantic HTML) سازگاری کامل دارد. برای آشنایی با مبانی HTML، مقاله تگ های پرکاربرد HTML: نقشه‌ای که هر توسعه‌دهنده باید روی دیوار ذهنش داشته باشد را ببینید.

بلاک‌های تودرتو و ساختارهای چندسطحی

یکی از قدرتمندترین ویژگی‌های InnerBlocks، امکان تودرتو کردن بلاک‌ها در چند سطح است. برای مثال، یک بلاک Columns می‌تواند شامل چند بلاک Column باشد و هر Column نیز خودش می‌تواند شامل InnerBlocks باشد. این ساختار چندسطحی به شما امکان می‌دهد تا ترکیب‌های پیچیده‌ای بسازید که با بلاک‌های ساده غیرممکن است.

برای ساخت بلاک‌های تودرتو، کافی است که در بلاک فرزند نیز از InnerBlocks استفاده کنید. ویرایشگر به‌طور خودکار این ساختار را تشخیص داده و امکان ویرایش هر سطح را فراهم می‌کند. توجه داشته باشید که هر سطح از تودرتویی، پیچیدگی ویرایشگر را افزایش می‌دهد و باید با احتیاط از آن استفاده کرد.

// بلاک والد
registerBlockType( 'my-plugin/outer', {
  edit: () => (
    <div { ...useBlockProps() }>
      <InnerBlocks
        allowedBlocks={ [ 'my-plugin/inner' ] }
        template={ [ [ 'my-plugin/inner' ] ] }
      />
    </div>
  ),
  save: () => (
    <div { ...useBlockProps.save() }>
      <InnerBlocks.Content />
    </div>
  ),
} );

در این مثال، بلاک my-plugin/outer تنها مجاز به درج بلاک my-plugin/inner است و بلاک inner نیز خودش می‌تواند InnerBlocks داشته باشد. این ساختار برای بلاک‌هایی مانند Columns، Accordion و Tab مناسب است.

مثال عملی: ساخت بلاک Hero حرفه‌ای

برای درک عملی InnerBlocks، بیایید یک بلاک Hero حرفه‌ای بسازیم که شامل تصویر پس‌زمینه، عنوان، توضیحات و دکمه فراخوانی به اقدام باشد. این بلاک از template و allowedBlocks استفاده می‌کند تا ساختار مشخصی داشته باشد.

import { registerBlockType } from '@wordpress/blocks';
import { useBlockProps, useInnerBlocksProps } from '@wordpress/block-editor';
import { __ } from '@wordpress/i18n';
import metadata from './block.json';

const TEMPLATE = [
  [ 'core/heading', {
    level: 1,
    placeholder: __( 'عنوان اصلی را وارد کنید', 'my-plugin' ),
  } ],
  [ 'core/paragraph', {
    placeholder: __( 'توضیح کوتاه...', 'my-plugin' ),
  } ],
  [ 'core/buttons', {},
    [
      [ 'core/button', { text: __( 'بیشتر بدانید', 'my-plugin' ) } ],
    ],
  ],
];

registerBlockType( metadata.name, {
  edit: () => {
    const blockProps = useBlockProps( {
      className: 'my-plugin-hero',
    } );

    const innerBlocksProps = useInnerBlocksProps(
      { className: 'my-plugin-hero__content' },
      {
        template: TEMPLATE,
        allowedBlocks: [
          'core/heading',
          'core/paragraph',
          'core/buttons',
        ],
        templateLock: false,
      }
    );

    return (
      <section { ...blockProps }>
        <div { ...innerBlocksProps } />
      </section>
    );
  },
  save: () => {
    const blockProps = useBlockProps.save( {
      className: 'my-plugin-hero',
    } );

    return (
      <section { ...blockProps }>
        <div className="my-plugin-hero__content">
          <InnerBlocks.Content />
        </div>
      </section>
    );
  },
} );

این بلاک یک ساختار حرفه‌ای دارد: از یک عنصر section برای ریشه استفاده می‌کند، یک div برای محتوای درونی، و template مشخصی برای شروع کار کاربر. با استفاده از allowedBlocks، کاربر تنها مجاز به درج عنوان، پاراگراف و دکمه است. این ساختار برای یک بلاک Hero مناسب است و تجربه کاربری خوبی فراهم می‌کند.

یک بلاک حرفه‌ای، نه‌تنها از InnerBlocks استفاده می‌کند، بلکه ساختار HTML آن نیز معنایی و قابل نگهداری است.

برای مطالعه بیشتر درباره طراحی صفحات فرود، مقاله ساخت صفحه فرود حرفه‌ای با المنتور را ببینید. اگرچه این مقاله درباره المنتور است، اما اصول طراحی مشابهی در آن به کار رفته است.

اعتبارسنجی و ذخیره‌سازی محتوا

یکی از چالش‌های مهم در کار با InnerBlocks، اعتبارسنجی محتوا هنگام ذخیره‌سازی است. برخلاف بلاک‌های ساده که اعتبارسنجی آن‌ها بر پایه مقایسه Attributes و خروجی save انجام می‌شود، بلاک‌های دارای InnerBlocks نیازمند رویکرد متفاوتی هستند.

وردپرس از یک مکانیزم به نام Block Validation استفاده می‌کند که در آن، خروجی تابع save با محتوای ذخیره‌شده مقایسه می‌شود. اگر این دو یکسان نباشند، وردپرس بلاک را به‌عنوان نامعتبر علامت‌گذاری کرده و پیام هشداری نمایش می‌دهد. برای بلاک‌های دارای InnerBlocks، این مکانیزم پیچیده‌تر است زیرا محتوای درونی نیز باید با ساختار template و allowedBlocks سازگار باشد.

برای جلوگیری از مشکلات اعتبارسنجی، توصیه می‌شود که توابع edit و save را به‌صورت دقیق و هماهنگ بنویسید. هر تغییری که در edit اعمال می‌کنید، باید در save نیز منعکس شود، مگر آن‌که از ویژگی‌های مخصوص ویرایشگر استفاده کنید. برای مطالعه بیشتر درباره ساختار بلاک‌ها، مقاله ساختار استاندارد افزونه وردپرس چیست و چطور یک پلاگین حرفه‌ای بسازیم؟ را ببینید.

اشتباهات رایج در استفاده از InnerBlocks

در کار با InnerBlocks، توسعه‌دهندگان اغلب مرتکب اشتباهاتی می‌شوند که منجر به کد شکننده یا تجربه کاربری ضعیف می‌شود. در ادامه به برخی از مهم‌ترین این اشتباهات اشاره می‌کنیم.

عدم استفاده از useBlockProps

یکی از رایج‌ترین اشتباهات، عدم استفاده از useBlockProps در تابع edit است. بدون این هوک، بلاک شما ممکن است در ویرایشگر به‌درستی نمایش داده نشود و ویژگی‌های لازم را نداشته باشد. useBlockProps وظیفه دارد کلاس‌ها، استایل‌ها و ویژگی‌های ARIA را فراهم کند که برای دسترس‌پذیری و نمایش صحیح ضروری هستند.

نادیده گرفتن allowedBlocks

بسیاری از توسعه‌دهندگان از پراپ allowedBlocks غافل می‌شوند و به کاربر اجازه می‌دهند هر بلاکی را درون بلاک والد درج کند. این کار می‌تواند به ساختارهای نامنظم و تجربه کاربری ضعیف منجر شود. تعریف allowedBlocks به‌عنوان یک قرارداد معماری، کیفیت خروجی را بهبود می‌بخشد.

استفاده نادرست از templateLock

انتخاب مقدار نامناسب templateLock می‌تواند به تجربه کاربری ضعیف منجر شود. اگر templateLock روی all تنظیم شود، کاربر نمی‌تواند محتوای درونی را سفارشی کند و این ممکن است برای بلاک‌هایی که باید انعطاف‌پذیر باشند، محدودکننده باشد. از سوی دیگر، اگر templateLock روی false تنظیم شود، ممکن است ساختار بلاک به‌هم بریزد.

عدم سازگاری edit و save

اگر توابع edit و save با یکدیگر هماهنگ نباشند، بلاک ممکن است هنگام بازخوانی محتوا نامعتبر شود. همیشه اطمینان حاصل کنید که ساختار HTML تولیدشده در edit و save یکسان است، مگر آن‌که از ویژگی‌های مخصوص ویرایشگر استفاده کنید.

یک بلاک نامعتبر، نه‌تنها تجربه کاربری را خراب می‌کند، بلکه می‌تواند به از دست رفتن محتوا منجر شود.

عیب‌یابی و رفع مشکلات InnerBlocks

عیب‌یابی مسائل مربوط به InnerBlocks نیازمند رویکردی سیستماتیک است. در ادامه به بررسی برخی از مشکلات رایج و راه‌حل‌های آن‌ها می‌پردازیم.

بلاک نامعتبر (Invalid Block)

اگر بلاک شما با پیام «This block contains unexpected or invalid content» مواجه می‌شود، احتمالاً ساختار HTML تولیدشده در save با محتوای ذخیره‌شده مطابقت ندارد. برای رفع این مشکل، ابتدا محتوای ذخیره‌شده را در ویرایشگر کد بررسی کنید و آن را با خروجی save مقایسه نمایید. سپس هر تغییری که لازم است در یکی از این دو اعمال کنید.

بلاک‌های درونی نمایش داده نمی‌شوند

اگر بلاک‌های درونی در ویرایشگر نمایش داده نمی‌شوند، ابتدا بررسی کنید که آیا <InnerBlocks /> در تابع edit قرار دارد. سپس بررسی کنید که آیا allowedBlocks به‌درستی تنظیم شده است. در نهایت، بررسی کنید که آیا template شامل بلاک‌هایی است که در allowedBlocks تعریف نشده‌اند.

محتوای درونی در فرانت‌اند نمایش داده نمی‌شود

اگر محتوای درونی در فرانت‌اند نمایش داده نمی‌شود، بررسی کنید که آیا <InnerBlocks.Content /> در تابع save قرار دارد. بدون این کامپوننت، محتوای درونی در پایگاه داده ذخیره نمی‌شود و در فرانت‌اند نمایش داده نخواهد شد.

عملکرد و بهینه‌سازی

از منظر عملکرد، استفاده از InnerBlocks می‌تواند تأثیرات قابل‌توجهی بر سرعت ویرایشگر و فرانت‌اند داشته باشد. در ادامه به بررسی این تأثیرات و راه‌های بهینه‌سازی می‌پردازیم.

تأثیر بر سرعت ویرایشگر

هر بلاک دارای InnerBlocks، یک ساختار درختی در ویرایشگر ایجاد می‌کند. با افزایش عمق تودرتویی، زمان رندر ویرایشگر افزایش می‌یابد. برای بهینه‌سازی، توصیه می‌شود که از تودرتویی بیش از حد خودداری کنید و ساختار بلاک را ساده نگه دارید.

تأثیر بر سرعت فرانت‌اند

در فرانت‌اند، محتوای InnerBlocks به‌صورت HTML سریالایز شده ذخیره می‌شود و مستقیماً در خروجی قرار می‌گیرد. این بدان معناست که InnerBlocks به‌خودی‌خود تأثیر منفی بر سرعت فرانت‌اند ندارد. با این حال، اگر بلاک والد شما استایل‌ها یا اسکریپت‌های سنگینی را بارگذاری کند، می‌تواند بر سرعت تأثیر بگذارد. برای مطالعه بیشتر درباره بهینه‌سازی، مقاله بهینه سازی جاوااسکریپت: قاتلان خاموشی که در پروژه‌ها دیده‌ام را ببینید.

کش کردن رندر بلاک

برای بلاک‌هایی که محتوای درونی پیچیده‌ای دارند، می‌توانید از مکانیزم کش استفاده کنید. وردپرس از Object Cache و Transients پشتیبانی می‌کند که برای کش کردن خروجی بلاک مناسب هستند. مقاله ترنزینت وردپرس چیست و چگونه کش هوشمند بدون افزونه بسازیم؟ به این موضوع می‌پردازد.

پرسش‌های پرتکرار درباره InnerBlocks

InnerBlocks چه تفاوتی با Reusable Blocks دارد؟

InnerBlocks یک API برای ساخت بلاک‌های ترکیبی است، در حالی که Reusable Blocks (و جایگزین آن Synced Patterns) برای اشتراک محتوا در چندین صفحه استفاده می‌شود. این دو مفهوم مکمل یکدیگرند و می‌توانند با هم ترکیب شوند.

آیا می‌توانم از InnerBlocks در بلاک‌های کلاسیک استفاده کنم؟

خیر، InnerBlocks تنها در ویرایشگر بلوک قابل استفاده است. برای آشنایی با تفاوت ویرایشگرها، مقاله ویرایشگر Classic یا Gutenberg؛ کدام برای WordPress بهتر است؟ را ببینید.

آیا InnerBlocks از بلاک‌های تودرتو پشتیبانی می‌کند؟

بله، InnerBlocks می‌تواند در چند سطح تودرتو شود. برای مثال، یک بلاک Columns می‌تواند شامل چند بلاک Column باشد و هر Column نیز خودش InnerBlocks داشته باشد.

چگونه می‌توانم بلاک‌های درونی را از کد مدیریت کنم؟

برای مدیریت بلاک‌های درونی از کد، می‌توانید از توابع پکیج @wordpress/data و store core/block-editor استفاده کنید. article Data API در وردپرس چیست و چطور state بلاک‌ها را مدیریت می‌کند؟ به این موضوع می‌پردازد.

آیا استفاده از InnerBlocks بر سئو تأثیر می‌گذارد؟

InnerBlocks به‌خودی‌خود تأثیر مستقیمی بر سئو ندارد، اما از آنجا که HTML معنایی تولید می‌کند، می‌تواند به بهبود سئو کمک کند. برای مطالعه بیشتر، مقاله سئو چیست و چگونه به رشد سایت کمک می‌کند؟ را ببینید.

چگونه می‌توانم یک بلاک دارای InnerBlocks را تست کنم؟

برای تست بلاک، می‌توانید از ابزارهای تست خودکار مانند Jest و Testing Library استفاده کنید. همچنین، تست دستی در ویرایشگر بلوک و بررسی رفتار بلاک در سناریوهای مختلف توصیه می‌شود.

آیا InnerBlocks از Interactivity API پشتیبانی می‌کند؟

بله، بلاک‌های دارای InnerBlocks می‌توانند از Interactivity API برای افزودن تعاملات در فرانت‌اند استفاده کنند. مقاله آیا WordPress Interactivity API جایگزین React در وردپرس می‌شود؟ به این موضوع می‌پردازد.

تحلیل معماری در سطح پیشرفته

از منظر معماری نرم‌افزار، InnerBlocks یک پیاده‌سازی کامل از الگوی Composite در سطح بلاک است. در این الگو، یک شیء (بلاک والد) می‌تواند مجموعه‌ای از اشیاء مشابه (بلاک‌های فرزند) را در خود جای دهد و همان رابط را با آن‌ها به اشتراک بگذارد. این الگو به‌طور طبیعی با ساختار درختی DOM سازگاری دارد و در ویرایشگر بلوک به‌صورت کامل پیاده‌سازی شده است. برای مطالعه بیشتر درباره ری‌اکت، می‌توانید صفحه React را در ویکی‌پدیا ببینید.

یکی از جنبه‌های کمتر شناخته‌شده InnerBlocks، نحوه مدیریت Context و Provider است. وردپرس از یک مکانیزم Context برای انتقال اطلاعات از بلاک والد به بلاک‌های فرزند استفاده می‌کند. این مکانیزم مشابه React Context API است و به بلاک‌های فرزند اجازه می‌دهد بدون دریافت مستقیم پراپ‌ها، به اطلاعات والد دسترسی داشته باشند. این رویکرد از prop drilling جلوگیری می‌کند و کد را تمیزتر نگه می‌دارد.

از منظر عملکرد، InnerBlocks یک trade-off میان حجم ذخیره‌سازی و انعطاف‌پذیری ایجاد می‌کند. بلاک‌های دارای InnerBlocks حجم بیشتری از محتوا را در پایگاه داده ذخیره می‌کنند، اما در عوض انعطاف‌پذیری بسیار بیشتری در ویرایش فراهم می‌آورند. این trade-off در پروژه‌های بزرگ که محتوای تکراری زیاد است، می‌تواند به یک چالش تبدیل شود و نیازمند بهینه‌سازی دقیق است.

از منظر قابلیت نگهداری (Maintainability)، InnerBlocks یک بهبود قابل‌توجه نسبت به بلاک‌های ساده است. هر بلاک درونی می‌تواند به‌طور مستقل تست، به‌روزرسانی و نگهداری شود. این ویژگی به‌ویژه در پروژه‌هایی با چندین توسعه‌دهنده حیاتی است و از بروز وابستگی‌های پیچیده جلوگیری می‌کند. برای مطالعه بیشتر درباره معماری وردپرس، مقاله چرا قالب WordPress از نگاه Developer یک معماری است؟ را ببینید.

آینده InnerBlocks

تیم هسته وردپرس در حال کار بر روی بهبود InnerBlocks است. از جمله قابلیت‌های مورد انتظار می‌توان به پشتیبانی از state محلی برای هر نمونه، امکان تعریف پارامترهای ورودی برای template و ادغام بهتر با الگوهای قالب اشاره کرد. این تحولات می‌توانند InnerBlocks را به یک ابزار قدرتمندتر برای ساخت بلاک‌های پویا تبدیل کنند.

نکات کلیدی

  • InnerBlocks یک API بومی وردپرس برای ساخت بلاک‌های ترکیبی است.
  • این API به یک بلاک اجازه می‌دهد بلاک‌های دیگر را درون خود جای دهد و ساختارهای درختی بسازد.
  • بلاک‌های هسته‌ای مانند Columns، Group و Cover بر پایه InnerBlocks ساخته شده‌اند.
  • پراپ‌های template، allowedBlocks و templateLock کنترل کامل روی ساختار درونی بلاک را فراهم می‌کنند.
  • استفاده از useBlockProps و useInnerBlocksProps برای رندر صحیح بلاک ضروری است.
  • اعتبارسنجی محتوا و هماهنگی توابع edit و save از بروز مشکلات جلوگیری می‌کند.
  • تودرتویی بیش از حد می‌تواند بر عملکرد ویرایشگر تأثیر بگذارد؛ ساختار را ساده نگه دارید.

اگر در پروژه‌ای از InnerBlocks استفاده کرده‌اید، برایم جالب است بدانید کدام بخش آن بیشترین چالش را برای شما ایجاد کرده است. تجربه خود را در دیدگاه‌ها بنویسید؛ به‌خصوص اگر راه‌حل خلاقانه‌ای برای مدیریت بلاک‌های تودرتو پیدا کرده‌اید که می‌تواند برای دیگران مفید باشد. 🚀