قم بإنشاء تجربة رائعة لتحرير WordPress ووفر الوقت مع Gutenberg InnerBlocks

نشرت: 2023-02-12

لا تكرر نفسك

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

أحدث WordPress ضجيجًا كبيرًا مع إصدار محرر كتلة Gutenberg ، المعروف الآن باسم "المحرر". بالنسبة لتحرير المحتوى وصياغته ونشره ، فإنه يوفر تجربة ممتازة ، أفضل بكثير من WYSIWYGs الأقدم. بصفتي مطورًا ، أرغب في تقديم أفضل تجربة تحرير لعملائي ، وأريد الاستفادة من الوظائف الأساسية ، ولا أريد إعادة اختراع العجلة. لحسن الحظ ، يتيح لنا WordPress القيام بكل هذه الأشياء باستخدام كتل مخصصة.

أدخل InnerBlocks

تعد InnerBlocks ميزة رائعة في محرر WordPress. يمكن للمطورين استخدام الكتل الأساسية مثل الفقرة والعناوين والأزرار لإنشاء تجربة متسقة للعميل. بدلاً من إعادة كتابة أقسام نصية وإعادة تعريف الحقول ، يحصل العميل على تجربة أصبحوا على دراية بها ؛ التحرير والجمع بين نفس الكتل. دعنا نلقي نظرة على الكتلة التي قد نحتاج إلى إنشائها للعميل ، ونرى كيف يمكن لـ InnerBlocks مساعدتنا في تحقيق ذلك.

بناء كتلة مع InnerBlocks

مثال على كتلة الحث على اتخاذ إجراء مع روابط العنوان والفقرة والأزرار
الشكل: مثال على كتلة الحث على اتخاذ إجراء. يتضمن هذا العنوان والفقرة وبعض روابط الأزرار.

دعونا نفحص هذه الكتلة ونفكر في كيفية بنائها. من الأدوات الشائعة التي نستخدمها عند إنشاء الكتل الحقول المخصصة المتقدمة (ACF). يضيف ACF Pro دعمًا مخصصًا للكتل ، والذي يتيح للمطورين كتابة كتل في PHP للمحرر والواجهة الأمامية. كما يتيح لنا استخدام الحقول المخصصة - وهو نموذج مألوف لدى العديد من مطوري WordPress. يدعم ACF InnerBlocks ، مما يعني أنه يمكننا إنشاء كتلة مخصصة ، ولكننا لن نحتاج حتى إلى كتابة رمز مخصص لهذا العنوان أو الفقرة أو الأزرار.

باستخدام ACF Blocks ، يمكننا الاستفادة من الكتل الأساسية لتقديم تجربة تحرير رائعة لكل النص الذي نراه في هذه المجموعة. هناك خيار آخر محتمل وهو استخدام أنماط الحظر ، ولكن كمطورين ومنسقين لتجربة WordPress رائعة ، فإن إنشاء كتلة مخصصة يحقق الهدف المنشود.

كود التسجيل بلوك

إليك الكود لتسجيل كتلة ACF المخصصة الخاصة بنا. اقرأ المزيد حول استخدام وظيفة acf_register_block_type هنا.

 <?php /** * Template for registering an ACF powered custom block. * * More info: https://www.advancedcustomfields.com/resources/blocks/ */ /** * Register the block. */ add_action( 'acf/init', function() { /** * ACF block registration options here: https://www.advancedcustomfields.com/resources/acf_register_block_type/ */ acf_register_block_type( array( 'name' => 'call-to-action-demo', // JS will register as: acf/{block-name}. 'title' => __( 'Call to Action ACF Demo', 'locale' ), 'description' => __( 'A custom ACF Call to Action block.', 'locale' ), 'render_template' => 'partials/blocks/call-to-action-demo.php', // Change to block template. 'category' => 'design', // Category in the block inserter. 'keywords' => array( 'action', 'buttons', 'cta' ), // Searchable keywords. 'supports' => array( 'align' => false, // Disable support for align. 'anchor' => true, // Enable support for anchor. 'jsx' => true, // Enable support for JSX. 'mode' => false, // Disable ACF block edit/preview mode switching as we are only using InnerBlocks for editable content. ), ) ); } );

دعونا نكسر الكود. نحن نستخدم وظيفة acf_register_block_type لتسجيل الكتلة الخاصة بنا ، ونقوم بتمرير مجموعة من الوسائط التي تحدد الكتلة الخاصة بنا وتشغيل الوظيفة وإيقاف تشغيلها.

  • لاحظ أننا نتبع الإجراء الموصى به لإضافة اسم فريد للكتلة الخاصة بنا ، بالإضافة إلى عنوان ووصف يمكن قراءته بواسطة الإنسان. نشير إلى قالب العرض ، حيث سنقوم بإعداد نموذج PHP الخاص بنا للكتلة لاحقًا. لقد أضفنا أيضًا فئة حيث نريد تجميع الكتلة الخاصة بنا في Block Inserter.
  • لدينا كلمات رئيسية قابلة للبحث لتسهيل البحث عن الكتلة في أداة الإدخال.
  • نضيف مصفوفة "تدعم" لتمكين الوظائف مثل تعيين نقطة ارتساء HTML وقمنا بإيقاف تشغيل المحاذاة لأن هذه الكتلة ستظل دائمًا في منتصف الصفحة.
  • هذا يدعم المصفوفة حيث نقوم بتشغيل سحر InnerBlocks! يؤدي ضبط 'jsx' على true إلى إخبار ACF أننا سندعم تصيير React jsx قوالب داخل الكتلة الخاصة بنا.

دعنا نراجع المحتوى الذي نحتاجه في مجموعتنا:

  • عنوان
  • نص الفقرة
  • أزرار لاتخاذ الإجراءات!

الآن ، عادةً ما نقوم بتعيين الحقول إلى الكتلة الخاصة بنا ، كما هو موضح هنا. لكن في هذه الحالة ، لسنا بحاجة إلى - يمكننا الاستفادة من الكتل الأساسية لتحقيق كل هذا. إذا احتاجت الكتلة إلى خلفية صورة ، على سبيل المثال ، فإن إضافة حقل صورة ACF إلى الكتلة يمكن أن يكون طريقة رائعة لتحقيق ذلك. في الوقت الحالي ، على الرغم من ذلك ، دعنا نلتزم بمثال InnerBlocks الخاص بنا وننتقل إلى النموذج.

قالب الحظر

هذا هو قالب الكتلة الجديدة. تأكد من توجيه تسجيل الكتلة إلى موقع قالب الحظر. من الممارسات الشائعة وضع هذه الأجزاء في مجلد الأجزاء في السمة.

 <?php /** * ACF Call to Action example block template. * * More info: https://www.advancedcustomfields.com/resources/acf_register_block_type/ * * @param array $block The block settings and attributes. * @param string $content The block inner HTML (empty). * @param bool $is_preview True during AJAX preview. * @param (int|string) $post_id The post ID this block is saved to. * */ // Create id attribute allowing for custom "anchor" value. $block_ . $block['id']; if ( ! empty( $block['anchor'] ) ) { $block_id = $block['anchor']; } // Create class attribute allowing for custom "className" and "align" values. $class_name = 'acf-call-to-action-demo'; if ( ! empty( $block['className'] ) ) { $class_name .= ' ' . $block['className']; } if ( ! empty( $block['align'] ) ) { $class_name .= ' align' . $block['align']; } ?> <div class="<?php echo esc_html( $class_name ); ?>"> <div class="cta__inner"> <?php // Set up innerBlocks and provide a template. // Restrict InnerBlocks to allowed block list. $allowed_blocks = array( 'core/heading', 'core/paragraph', 'core/buttons' ); // Start InnerBlocks with a template. $template = array( array( 'core/heading', array( 'placeholder' => __( 'CTA Heading', 'locale' ), 'align' => 'center', 'level' => '2', ), ), array( 'core/paragraph', array( 'placeholder' => __( 'Add CTA text here', 'locale' ), 'align' => 'center', ), ), array( 'core/buttons', array( 'placeholder' => __( 'Add CTA buttons here', 'locale' ), 'align' => 'center', ), array( array( 'core/button', array( 'text' => __( 'Take action', 'locale' ), ), ), array( 'core/button', array( 'text' => __( 'Learn more', 'locale' ), ), ), ), ), ); // Echo out our JSX InnerBlocks compoennt for the editor. echo '<InnerBlocks allowedBlocks="' . esc_attr( wp_json_encode( $allowed_blocks ) ) . '" template="' . esc_attr( wp_json_encode( $template ) ) . '" templateLock="false" />'; ?> </div> </div>

دعونا نكسر هذا الكود.

  • في البداية ، لدينا نموذج كتلة عام نموذجي يوفره ACF في إرشادات الكتلة الخاصة بهم ، مثل دعم المرساة واسم الفئة المخصصة.
  • يمكن لمكون InnerBlocks تلقي الخصائص. نحن نستخدم ثلاثة في هذا القالب.
    • الكتل المسموح بها: نضيف مجموعة من الكتل المسموح بها للتنظيم. ستكون هذه الكتل فقط متاحة للاختيار داخل مساحة InnerBlocks الخاصة بنا.
    • القالب: يمكننا تمرير مجموعة من الكتل ويمكننا تمرير سمات الكتلة للكتل لتبدأ بها عند تحميلها لأول مرة في المحرر.
      • لاحظ أنه يمكننا تمرير سمات الحظر لإعداد مستخدمينا للنجاح. تم تعيين العنوان على المستوى 2 بالفعل ، وتم توسيط الفقرة.
      • ملاحظة: سيُشار دائمًا إلى المكوّنات الأساسية في JavaScript باسم {plugin} / blockname. في حالتنا ، نحن نستخدم الكتل الأساسية ، ولكن إذا أردت استخدام كتلة ACF مخصصة ، يمكنك كتابة "acf" أمام اسم الكتلة. تذكر ، عند استخدام InnerBlocks ، نقوم بتمرير هذا المكون إلى محرر WordPress ، والذي يستخدم React. لهذا السبب نفكر هنا في JS.
      • ملاحظة أخرى: لاحظ أن الكتلة الأساسية / الأزرار تستخدم InnerBlocks نفسها! نحن في الواقع نمرر مجموعة من كتلتين أساسيتين / زر داخل!
    • تأمين القالب: تم ​​تعيين templateLock على مكون InnerBlocks. إذا قمنا بتعيينه على "الكل" ، فلن يمكن نقل أو إزالة أي من الكتل الموجودة في نموذجنا المقدم إلى InnerBlocks. إذا قمنا بتعيينه على "insert" ، فيمكن فقط تحريك الكتل الموجودة داخله ، ولا يمكن إزالة أي كتل ، ولا يمكن إضافة كتل جديدة. إذا قمنا بتعيينه على "خطأ" ، فسيتم إلغاء قفل مثيل InnerBlocks وسيتم إلغاء قفله بغض النظر عن أي أقفال للقالب الأصل (المزيد حول هذا الأمر في الأسفل). اقرأ المزيد عن قوالب القوالب في دليل محرر قوالب WordPress. سنتحدث عن قفل الحظر أكثر.

لدينا كتلة جديدة! بعد كل ذلك ، وبعض الأنماط ، بالطبع ، تبدو كتلة المثال كما يلي في المحرر:

مجموعة الحث على اتخاذ إجراء مع تحديد كتلة العنوان.
الشكل: كتلة الحث على اتخاذ إجراء في المحرر. تم تحديد كتلة العنوان.

التعشيش بشكل أعمق: تنظيم التجربة بشكل أكبر باستخدام الكتل الداخلية المتداخلة

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

دعنا نفكر في بعض القواعد عند العمل مع InnerBlocks:

  • قد تحتوي الكتلة الواحدة على مثيل واحد فقط من InnerBlocks بداخلها.
  • قد تستخدم الكتل المتعددة داخل InnerBlocks مكونات InnerBlocks الخاصة بها.
  • قد يتم قفل InnerBlocks عبر خاصية templateLock ، ولكن قد يتم إلغاء قفل مثيلات InnerBlocks الأعمق داخل بنية كتلة متداخلة مرة أخرى عن طريق تعيين templateLock إلى false.

يتمثل أحد الحلول في إنشاء كتلة جديدة تعمل كغلاف لـ InnerBlocks. سنقوم بتضمين هذه الكتلة في قالب الكتلة الأصلي الخاص بنا وقمنا بتأمينها ، لكننا نقوم بإلغاء تأمين كتلة الغلاف الخاصة بنا بشكل صريح من خلال تعيين "templateLock" على false. قد نرغب أيضًا في التأكد من توفر كتلة الغلاف الخاصة هذه فقط داخل الكتلة الأصلية التي نختارها ، عن طريق تعيين أحد الوالدين للحظر الخاص بنا. يمكننا السماح بأنواع كتل متعددة داخل تلك المساحة لتقديم قوائم المحررين والمزيد ، مع الاستمرار في السماح فقط بالعنوان والأزرار وحظر الغلاف الخاص بنا في كتلة Call to Action الأصلية.

قفل كتلة فردي

ميزة جديدة في WordPress 5.9 هي القدرة على قفل الكتل الفردية في قالب. هذا حل آخر ممكن لمشكلتنا المرنة والمتسقة.

إليك ما يبدو عليه نموذجنا مع بعض الكتل الفردية المقفلة:

 <?php /** * ACF Call to Action example block template. * * More info: https://www.advancedcustomfields.com/resources/acf_register_block_type/ * * @param array $block The block settings and attributes. * @param string $content The block inner HTML (empty). * @param bool $is_preview True during AJAX preview. * @param (int|string) $post_id The post ID this block is saved to. * */ // Create id attribute allowing for custom "anchor" value. $block_ . $block['id']; if ( ! empty( $block['anchor'] ) ) { $block_id = $block['anchor']; } // Create class attribute allowing for custom "className" and "align" values. $class_name = 'acf-call-to-action-demo'; if ( ! empty( $block['className'] ) ) { $class_name .= ' ' . $block['className']; } if ( ! empty( $block['align'] ) ) { $class_name .= ' align' . $block['align']; } ?> <div class="<?php echo esc_html( $class_name ); ?>"> <div class="cta__inner"> <?php // Set up innerBlocks and provide a template. // Restrict InnerBlocks to allowed block list. $allowed_blocks = array( 'core/heading', 'core/paragraph', 'core/buttons' ); // Start InnerBlocks with a template. $template = array( array( 'core/heading', array( 'placeholder' => __( 'Heading', 'locale' ), 'align' => 'center', 'level' => '2', 'lock' => array( 'move' => true, // Block may nto be moved. 'remove' => true, // Block may not be removed. ), ), ), array( 'core/paragraph', array( 'placeholder' => __( 'Add CTA text here', 'locale' ), 'align' => 'center', ), ), array( 'core/buttons', array( 'placeholder' => __( 'Add CTA buttons here', 'locale' ), 'align' => 'center', 'lock' => array( 'move' => true, // Block may not be moved. 'remove' => true, // Block may not be removed. ), ), array( array( 'core/button', array( 'text' => __( 'Take action', 'locale' ), ), ), array( 'core/button', array( 'text' => __( 'Learn more', 'locale' ), ), ), ), ), ); // Echo out our JSX InnerBlocks compoennt for the editor. echo '<InnerBlocks allowedBlocks="' . esc_attr( wp_json_encode( $allowed_blocks ) ) . '" template="' . esc_attr( wp_json_encode( $template ) ) . '" />'; ?> </div> </div>

يجب ألا يتم نقل أو إزالة كتل العنوان والأزرار. تأكد من تحديث المحرر وإزالته ثم إضافته مرة أخرى للحصول على تغييرات النموذج.

المكافأة: صنع نفس الكتلة محليًا

بمجرد أن تكون لديك عملية بناء في مكانها الصحيح ، فإن إنشاء كتل WordPress الأصلية باستخدام React سيكون أمرًا سهلاً بشكل مدهش ولا يختلف كثيرًا عن قالب قالب في php. يعد إعداد بيئة تطوير الكتل خارج نطاق هذه المقالة ، ولكن هناك عددًا من الموارد للبدء ، مثل دليل WordPress Block Editor Handbook. بمجرد أن تتمكن من تضمين الكتل المخصصة ، يمكنك إنشاء الكتل بسرعة باستخدام InnerBlocks.

فيما يلي مثال على index.js لكتلة الحث على اتخاذ إجراء في React. سترى نفس الإستراتيجية التي ناقشناها أعلاه مع ACF المطبقة هنا.

 import { __ } from '@wordpress/i18n'; import { registerBlockType } from '@wordpress/blocks'; import { InnerBlocks } from '@wordpress/block-editor'; import { useBlockProps } from '@wordpress/block-editor'; /** * Block Name. * Create an example Call to Action Block * Uses InnerBlocks for editable content within. */ export const blockName = 'call-to-action'; /** * Block Config. * Set basic params for controlling the editor. */ export const BLOCK_CONFIG = { // Set up the block template. CTA_TEMPLATE: [ [ 'core/heading', { placeholder: __('CTA Headline', 'locale'), align: 'center', level: 2, lock: { move: true, remove: true, }, }, ], [ 'core/paragraph', { placeholder: 'Optional CTA text', align: 'center', lock: { move: true, }, }, ], [ 'core/buttons', { lock: { move: true, remove: true, }, className: 'is-content-justification-center', align: 'center', // __experimentalLayout - https://github.com/WordPress/gutenberg/blob/trunk/packages/block-library/src/buttons/block.json layout: { type: 'flex', justifyContent: 'center', }, }, [ [ 'core/button', { text: 'Apply now', lock: { move: true, remove: true, }, }, ], ['core/button', { text: 'Learn more' }], ], ], ], // Set up the allowed blocks. ALLOWED_BLOCKS: ['core/paragraph', 'core/heading', 'core/buttons'], }; // Register the block via WP func. Change 'myplugin' to your plugin or theme. registerBlockType(`myplugin/${blockName}`, { title: __('Call to Action', 'locale'), // Change 'locale' to your locale for internationalization. description: __( 'Call to action block with headline and buttons', 'locale' ), keywords: [__('call'), __('action'), __('cta')], category: 'design', supports: { anchor: true, defaultStylePicker: false, html: false, align: false, }, attributes: { anchor: { type: 'string', default: '', }, }, transforms: {}, variations: [], edit: (props) => { const blockProps = useBlockProps({ className: `wp-block-myplugin-${blockName}`, }); return ( <div {...blockProps}> <div className="cta__inner"> <div className="cta__inner-blocks-wrapper"> <InnerBlocks template={BLOCK_CONFIG.CTA_TEMPLATE} allowedBlocks={BLOCK_CONFIG.ALLOWED_BLOCKS} renderAppender={false} /> </div> </div> </div> ); }, save: () => { return ( <div> <div className="cta__inner"> <InnerBlocks.Content /> </div> </div> ); }, });

انطلق وابني!

مصادر إضافية

  • مقالة بيل إريكسون على InnerBlocks
  • مقالات بيل إريكسون على Block Editor
  • دليل كتل ACF
  • توثيق نوع كتلة سجل ACF
  • دليل محرر قوالب ووردبريس
  • دليل محرر قوالب WordPress: إنشاء برنامج تعليمي للكتل