25 β InnerBlocks, variations va Interactivity API¶
β¬ οΈ Oldingi: 24 β Dinamik bloklar (render_callback) Β· π README Β· Keyingi: 26 β WooCommerce tema integratsiyasi β‘οΈ
Bu bobda: 22-24 boblarda yakka bloklar yaratdik. Endi bloklarni bir-biriga ulashni va ularga harakat berishni o'rganamiz. Avval InnerBlocks β blok ichida boshqa bloklarni joylashtirish (
allowedBlocks,template,templateLock,orientation, hamda zamonaviyuseInnerBlocksProps). So'ng variations (registerBlockVariation) va styles (registerBlockStyle) β bitta blokdan ko'p variant chiqarish; ularning farqini aniq ajratamiz. Transformlarga (transforms.from/to) qisqa nazar tashlaymiz. Nihoyat WordPress 6.5 dan kelgan Interactivity API (@wordpress/interactivity,store(),data-wp-*direktivalari) bilan frontendda jonli interaktiv blok β akkordion β quramiz. Butun kod jonli WordPress 7.0 danpx wp-scripts build(webpack compiled successfully),php -lva yadro funksiyalari bilan tasdiqlangan; har bir API nomi yadro manbasidan (wp-includes) tekshirilgan, ixtiro qilinmagan.
InnerBlocks: blok ichida bloklar¶
Hozirgacha bloklarimiz "yopiq qutilar" edi β ichiga faqat o'zimiz belgilagan narsa (RichText, rasm) joylanardi. Lekin ko'p hollarda blok konteyner bo'lishi kerak: foydalanuvchi uning ichiga istalgan boshqa bloklarni (sarlavha, paragraf, rasm, tugma) tashlay olsin.
Buni core/group, core/columns, core/cover kabi yadro bloklari qiladi β ularning hammasi ichida InnerBlocks ishlatadi.
Oddiy o'xshatish: oddiy blok β bu rasm romi (faqat bitta rasmni tutadi). InnerBlocks bo'lgan blok β bu javon: siz unga turli kitoblar (bola bloklar) terib qo'yasiz, javon esa ularni saqlab, tartibga soladi.
Klassik sintaksis: <InnerBlocks />¶
Eng tushunarli usul β @wordpress/block-editor dan InnerBlocks komponentini import qilish. Editorda <InnerBlocks />, saqlashda <InnerBlocks.Content />:
import { registerBlockType } from '@wordpress/blocks';
import { useBlockProps, InnerBlocks } from '@wordpress/block-editor';
import metadata from './block.json';
registerBlockType( metadata.name, {
edit: () => {
const blockProps = useBlockProps( { className: 'kitob-karta' } );
return (
<div { ...blockProps }>
<InnerBlocks />
</div>
);
},
save: () => {
const blockProps = useBlockProps.save( { className: 'kitob-karta' } );
return (
<div { ...blockProps }>
<InnerBlocks.Content />
</div>
);
},
} );
Bu yerda ikki muhim nuqta:
edit()da<InnerBlocks />β editorda foydalanuvchi bloklar qo'shadigan "bo'sh joy" (drop zone).save()da<InnerBlocks.Content />β bola bloklar markupini o'sha joyga avtomatik joylaydi. Agar buni unutsangiz, ichki bloklar saqlanmaydi va yo'qoladi.
InnerBlocksfaqat statik blokda emas: dinamik blokdasave: () => nullbo'lsa ham InnerBlocks ishlaydi β bola bloklar markupi PHPrender.phpichida$contento'zgaruvchisi orqali keladi (24-bobda ko'rganmiz). Statik blokda esa<InnerBlocks.Content />markupni bazaga yozadi.
allowedBlocks, template, templateLock, orientation¶
<InnerBlocks /> bo'sh holicha ham ishlaydi, lekin uni boshqarish uchun props beriladi:
const ALLOWED = [ 'core/heading', 'core/paragraph', 'core/image', 'core/buttons' ];
const TEMPLATE = [
[ 'core/heading', { level: 3, placeholder: 'Karta sarlavhasi' } ],
[ 'core/paragraph', { placeholder: 'Karta matni...' } ],
];
<InnerBlocks
allowedBlocks={ ALLOWED }
template={ TEMPLATE }
templateLock={ false }
orientation="vertical"
/>
| Prop | Nima qiladi |
|---|---|
allowedBlocks |
Konteyner ichiga qaysi bloklar qo'shilishi mumkinligini cheklaydi (massiv). Bo'sh qoldirilsa β hamma bloklar ruxsat etiladi. |
template |
Blok birinchi qo'shilganda avtomatik paydo bo'ladigan bola bloklar. Har element: [ 'blok/nomi', { atributlar } ]. |
templateLock |
Foydalanuvchi bloklarni qo'sha/o'chira/ko'chira oladimi: false (erkin), 'all' (umuman qulflangan), 'insert' (ko'chirish mumkin, qo'shish/o'chirish yo'q), 'contentOnly' (faqat tarkibni tahrirlash). |
orientation |
Bloklar joylashuvi: 'vertical' (default) yoki 'horizontal' β drag-and-drop va klaviatura navigatsiyasiga ta'sir qiladi. |
template quyidagicha β yangi karta qo'shilganda ichida darhol bitta sarlavha va bitta paragraf paydo bo'ladi, foydalanuvchi bo'sh sahifaga qaramaydi.
templateLockni tushunish:'all'β foydalanuvchi blok tuzilishini umuman o'zgartira olmaydi (faqat siz bergan template).'contentOnly'β bloklar joyi qulf, lekin matn/rasm kabi tarkibni tahrirlash mumkin (landing-page patternlar uchun zo'r).falseβ to'liq erkinlik.
Zamonaviy sintaksis: useInnerBlocksProps¶
<InnerBlocks /> komponenti bitta cheklov beradi: u o'zining <div> ini yaratadi, demak siz tashqi <div> ni qo'shasiz va InnerBlocks ichiga ko'milib qoladi (ortiqcha o'rash). Zamonaviy va tavsiya etilgan usul β useInnerBlocksProps hooki. U useBlockProps natijasini olib, InnerBlocks xususiyatlarini bitta elementga birlashtiradi:
import { useBlockProps, useInnerBlocksProps } from '@wordpress/block-editor';
edit: () => {
const blockProps = useBlockProps( { className: 'kitob-karta' } );
const innerBlocksProps = useInnerBlocksProps( blockProps, {
allowedBlocks: ALLOWED,
template: TEMPLATE,
templateLock: false,
orientation: 'vertical',
} );
return <div { ...innerBlocksProps } />;
},
save: () => {
const blockProps = useBlockProps.save( { className: 'kitob-karta' } );
const innerBlocksProps = useInnerBlocksProps.save( blockProps );
return <div { ...innerBlocksProps } />;
},
Bu yerda <div> ham wrapper, ham InnerBlocks konteyneri β qo'shimcha qatlam yo'q. useInnerBlocksProps block-editor paketida mavjudligi jonli WP 7.0 yadrosida (wp-includes/js/dist/block-editor) tasdiqlandi.
Qaysi birini ishlatish? Yangi loyihada
useInnerBlocksPropsafzal β toza markup, bitta o'rov.<InnerBlocks />esa tushunarliroq va eski qo'llanmalarda ko'p uchraydi. Ikkalasi ham WP 7.0 da to'liq ishlaydi.
Block variations: bitta blok, ko'p variant¶
Tasavvur qiling, core/group blokini "Banner" sifatida sozlash kerak: to'q ko'k fon, katta padding, ichida sarlavha va tugma. Buni har safar qo'lda sozlash zerikarli. Block variation β bu blokning oldindan sozlangan nusxasi: foydalanuvchi Inserter'dan "Banner" ni tanlaydi va tayyor sozlamalar bilan group oladi.
Variation @wordpress/blocks dan registerBlockVariation bilan ro'yxatga olinadi (funksiya jonli WP 7.0 blocks bundle'ida mavjudligi tasdiqlandi):
import { registerBlockVariation } from '@wordpress/blocks';
import { __ } from '@wordpress/i18n';
registerBlockVariation( 'core/group', {
name: 'kitob-banner',
title: __( 'Banner', 'kitob' ),
description: __( 'To\'q fonli e\'lon banneri.', 'kitob' ),
icon: 'megaphone',
attributes: {
backgroundColor: 'contrast',
textColor: 'base',
layout: { type: 'constrained' },
},
innerBlocks: [
[ 'core/heading', { level: 2, content: __( 'Sarlavha', 'kitob' ) } ],
[ 'core/buttons', {}, [
[ 'core/button', { text: __( 'Batafsil', 'kitob' ) } ],
] ],
],
scope: [ 'inserter' ],
} );
| Kalit | Nima |
|---|---|
name |
Variation noyob identifikatori (blok ichida). |
title / description / icon |
Inserter'da ko'rinadigan nom, izoh, ikonka. |
attributes |
Variation faollashganda blokka qo'llanadigan default atributlar. |
innerBlocks |
Variation ichida darhol paydo bo'ladigan bola bloklar (InnerBlocks template formati). |
scope |
Variation qayerda ko'rinadi: 'inserter' (blok ro'yxatida), 'block' (mavjud blokni almashtirishda), 'transform' (transform menyusida). |
isActive |
WordPress qaysi variation faolligini qanday aniqlashi (pastda). |
isActive β faol variationni aniqlash¶
WordPress bir blok namunasiga qarab, "bu qaysi variation?" ni bilishi kerak (masalan blok inspector'da to'g'ri nomni ko'rsatish uchun). Buni isActive belgilaydi. Eng oddiy shakli β taqqoslanadigan atributlar ro'yxati (massiv):
Bu WordPress'ga aytadi: "agar blokning backgroundColor atributi bu variation'nikiga teng bo'lsa, demak bu variation faol". Murakkabroq mantiq kerak bo'lsa, funksiya beriladi:
isActive: ( blockAttributes, variationAttributes ) =>
blockAttributes.backgroundColor === variationAttributes.backgroundColor,
isActiveni unutmang: uni bermasangiz, editor inspector'da variation nomini ko'rsata olmaydi (oddiy "Group" deb qoladi) va bir blokda bir nechta variation chalkashishi mumkin.scope: ['inserter']faqat ro'yxatda ko'rsatish uchun,isActiveesa tanib olish uchun.
Block styles: faqat ko'rinish varianti¶
Block style β variationdan butunlay boshqa narsa. U blokning tuzilishini yoki atributlarini emas, faqat KO'RINISHINI (CSS) o'zgartiradi. Masalan, core/quote blokiga "Katta tirnoq" yoki "Chiziqli" uslublarini qo'shasiz β tarkib bir xil, faqat CSS boshqacha.
registerBlockStyle (@wordpress/blocks, jonli WP 7.0 da tasdiqlangan) blokga uslub qo'shadi:
import { registerBlockStyle } from '@wordpress/blocks';
import { __ } from '@wordpress/i18n';
registerBlockStyle( 'core/quote', {
name: 'pushka',
label: __( 'Katta tirnoq', 'kitob' ),
} );
Bu ikki narsa qiladi:
- Blok inspector'idagi "Styles" panelida "Katta tirnoq" tugmasi paydo bo'ladi.
- Foydalanuvchi uni tanlasa, blokning tashqi elementiga
is-style-pushkaCSS klassi qo'shiladi (is-style-{name}qoidasi).
So'ng siz shu klassga CSS yozasiz (tema style.css yoki blokning style faylida):
.wp-block-quote.is-style-pushka {
border-left: none;
font-size: 1.6rem;
font-style: italic;
quotes: '\201C' '\201D';
}
.wp-block-quote.is-style-pushka::before {
content: open-quote;
font-size: 3rem;
color: var( --wp--preset--color--primary );
}
Default uslub va uslubni o'chirish¶
isDefault: true bersangiz, uslub blokning standart ko'rinishi bo'ladi:
registerBlockStyle( 'core/quote', {
name: 'oddiy',
label: __( 'Oddiy', 'kitob' ),
isDefault: true,
} );
Yadro uslubini olib tashlash uchun unregisterBlockStyle (masalan core/button ning "Outline" uslubini yashirish):
import { unregisterBlockStyle } from '@wordpress/blocks';
// MUHIM: domReady ichida chaqiring (blok ro'yxatdan o'tib bo'lgach).
import domReady from '@wordpress/dom-ready';
domReady( () => {
unregisterBlockStyle( 'core/button', 'outline' );
} );
Variation va style β qachon qaysi? - Style = faqat ko'rinish (rang, ramka, shrift) o'zgaradi, tarkib va atribut o'zgarmaydi. Bir blok, ko'p "tema". Misol: tirnoq uslubi, tugma uslubi. - Variation = atributlar va/yoki ichki bloklar oldindan to'ldiriladi. Inserter'da go'yo alohida blokdek ko'rinadi. Misol: "Banner" (group), "Ikki ustun" (columns). - Qoidaga: "faqat CSS kerakmi?" β style. "Tayyor sozlama/tarkib kerakmi?" β variation.
block.json orqali style (build shart emas)¶
Oddiy holatlar uchun uslubni JS'siz, to'g'ridan-to'g'ri o'z blokingiz block.json da e'lon qilish mumkin:
"styles": [
{ "name": "oddiy", "label": "Oddiy", "isDefault": true },
{ "name": "pushka", "label": "Katta tirnoq" }
]
Bu faqat o'zingiz yaratayotgan blok uchun ishlaydi. Yadro yoki boshqa blokga uslub qo'shish uchun esa registerBlockStyle JS chaqiruvi kerak.
Transforms: bloklarni bir-biriga aylantirish (qisqacha)¶
Transforms foydalanuvchiga bir blokni boshqasiga aylantirishga ruxsat beradi β masalan paragrafni iqtibosga, yoki sizning blokni core/group ga. Bu registerBlockType ning transforms kalitida e'lon qilinadi (transforms blocks bundle'ida mavjudligi tasdiqlangan):
import { createBlock } from '@wordpress/blocks';
transforms: {
from: [
{
type: 'block',
blocks: [ 'core/paragraph' ],
transform: ( attributes ) =>
createBlock( 'kitob/akkordion', {
sarlavha: 'Savol',
matn: attributes.content,
} ),
},
],
to: [
{
type: 'block',
blocks: [ 'core/paragraph' ],
transform: ( attributes ) =>
createBlock( 'core/paragraph', { content: attributes.matn } ),
},
],
},
fromβ boshqa blokdan sizning blokingizga aylantirish.toβ sizning blokingizdan boshqasiga.createBlock( 'blok/nomi', { atributlar } )β yangi blok namunasini yaratadi.
Transforms type: 'block' dan tashqari 'text', 'raw', 'shortcode' turlarini ham qo'llab-quvvatlaydi, lekin ular kamroq kerak bo'ladi. Bu bobda asosini bilish yetarli.
Interactivity API: frontendda jonli bloklar¶
Hozirgacha frontend bloklar statik edi β bosilganda hech narsa o'zgarmaydi. Akkordion, tab, "ko'proq ko'rish" tugmasi, savatcha hisoblagichi kabi interaktiv bloklar uchun JavaScript kerak. WordPress 6.5 dan beri buning rasmiy, yengil va standart yo'li bor β Interactivity API (@wordpress/interactivity).
Nega yangi API? Avval har bir interaktiv blok o'zicha jQuery yoki React yozardi β natijada sahifada bir nechta framework, og'irlik va mosliksizlik. Interactivity API esa:
- Deklarativ β HTML atributlarida (
data-wp-*) "nima qilish" ni belgilaysiz, "qanday" ni emas. - Yengil β kichik runtime, server-render bilan to'liq mos (SSR).
- Standart β yadro bloklari (
core/search,core/navigation,core/imagelightbox) shu API'da yozilgan.
Ikki tomon: data-wp-* direktivalar va store()¶
Interactivity API ikki qismdan iborat:
- HTML tomon (
render.php) β elementlargadata-wp-*direktivalari qo'yiladi. Ular HTML'ga "bu element interaktiv, mana qanday" deb aytadi. - JS tomon (
view.jsβ script module) βstore()bilanstate,actions,callbackse'lon qilinadi.
WordPress yadro manbasidan (wp-includes/interactivity-api/class-wp-interactivity-api.php) tasdiqlangan asosiy direktivalar:
| Direktiva | Nima qiladi |
|---|---|
data-wp-interactive="namespace" |
Elementni store'ga ulaydi (interaktivlik ildizi). |
data-wp-context='{...}' |
Element va uning ichi uchun lokal holat (JSON). |
data-wp-bind--ATRIBUT="state.x" |
HTML atributini (masalan hidden, aria-expanded) state'ga bog'laydi. |
data-wp-on--HODISA="actions.y" |
Hodisani (masalan click) action'ga ulaydi. |
data-wp-class--KLASS="state.z" |
CSS klassini shartli qo'shadi/olib tashlaydi. |
data-wp-style--XOSSA="state.w" |
Inline CSS xossasini bog'laydi. |
data-wp-text="state.t" |
Elementning matn tarkibini bog'laydi. |
data-wp-each="state.list" |
Ro'yxat (massiv) bo'yicha shablonni takrorlaydi. |
data-wp-init="callbacks.i" |
Element birinchi render bo'lganda callback ishga tushadi. |
data-wp-watch="callbacks.c" |
Bog'liq state o'zgarganda callback qayta ishlaydi. |
Direktiva nomlari β ixtiro qilinmagan: yuqoridagi
data-wp-bind,data-wp-context,data-wp-on,data-wp-class,data-wp-style,data-wp-text,data-wp-eachserver tomonidaclass-wp-interactivity-api.phpda ro'yxatdan o'tgan.data-wp-on--*,data-wp-init,data-wp-watchesa client tomonda (@wordpress/interactivityruntime) ishlaydi β server ularni HTML'da o'zgarishsiz qoldiradi, brauzerda runtime hayotga keltiradi. Suffiks sintaksisi (data-wp-on--click) ham yadro koddan tasdiqlangan.
block.json da Interactivity'ni yoqish¶
Interaktiv blok block.json da ikki narsani talab qiladi (ikkalasi ham jonli WP 7.0 wp-includes/blocks.php da tasdiqlangan):
{
"apiVersion": 3,
"name": "kitob/akkordion",
"supports": {
"interactivity": true
},
"viewScriptModule": "file:./view.js",
"render": "file:./render.php"
}
supports.interactivity: trueβ blokga Interactivity API runtime'ni yuklash kerakligini bildiradi (@sinceyadro logikasida$is_interactivetekshiruvi).viewScriptModuleβ frontend uchun script module (oddiyviewScriptemas!). Bu kalit@since 6.5.0(yadroblocks.phpda'viewScriptModule' => 'view-script-module'). Interactivity API ES modullar (import) bilan ishlagani uchun aynanviewScriptModulekerak.
viewScriptvaviewScriptModulefarqi: eskiviewScriptβ oddiy<script>(global o'zgaruvchilar).viewScriptModuleβ<script type="module">(ESimport/export). Interactivity API@wordpress/interactivitydanstore,getContextniimportqiladi, shuning uchun albattaviewScriptModule.
store(): state, actions, callbacks¶
view.js faylida @wordpress/interactivity dan store va getContext import qilinadi:
import { store, getContext } from '@wordpress/interactivity';
store( 'kitob/akkordion', {
state: {
// "computed" β kontekstdan hisoblanadigan qiymat (getter).
get ochiqMi() {
return getContext().ochiq;
},
},
actions: {
// data-wp-on--click shu yerga ulanadi.
almashtir() {
const context = getContext();
context.ochiq = ! context.ochiq;
},
},
callbacks: {
// data-wp-init / data-wp-watch shu yerga ulanadi.
init() {
const context = getContext();
if ( typeof context.ochiq === 'undefined' ) {
context.ochiq = false;
}
},
},
} );
| Bo'lim | Nima uchun |
|---|---|
state |
Umumiy holat va hisoblanadigan (getter) qiymatlar. data-wp-bind, data-wp-text shularga murojaat qiladi. |
actions |
Foydalanuvchi hodisalariga javob (data-wp-on--click). State yoki context ni o'zgartiradi. |
callbacks |
Yon ta'sirlar (data-wp-init, data-wp-watch) β state o'zgarishiga reaktiv javob. |
getContext() β joriy elementning eng yaqin data-wp-context ma'lumotiga kiradi. Context o'zgartirilsa (context.ochiq = true), unga bog'langan barcha direktivalar (data-wp-bind--hidden va h.k.) avtomatik yangilanadi β bu reaktivlik.
PHP yordamida context yozish¶
render.php da context'ni qo'lda JSON yozish o'rniga WordPress'ning xavfsiz yordamchisi bor β wp_interactivity_data_wp_context() (jonli WP 7.0 interactivity-api.php da tasdiqlangan):
<div
<?php echo get_block_wrapper_attributes(); ?>
data-wp-interactive="kitob/akkordion"
<?php echo wp_interactivity_data_wp_context( array( 'ochiq' => false ) ); ?>
>
Bu funksiya data-wp-context='{"ochiq":false}' atributini xavfsiz (to'g'ri kodlangan) qaytaradi. Massiv β JSON ni o'zingiz yozib, escape qilishdan ko'ra ishonchli.
Server tomonidan global state/config berish uchun wp_interactivity_state() va wp_interactivity_config() ham mavjud (ikkalasi ham yadroda tasdiqlangan) β masalan tarjima qatorlari yoki sayt sozlamalarini JS'ga uzatish.
Amaliy: interaktiv akkordion bloki¶
Endi hammasini birlashtirib, akkordion quramiz β sarlavhaga bosilganda javob ochiladi/yopiladi. Bu blok InnerBlocks ishlatmaydi (sodda matnli), lekin Interactivity API'ni to'liq ko'rsatadi. Bobning oxirida InnerBlocks bilan konteyner blokni ham qo'shamiz.
Fayl strukturasi¶
akkordion/
βββ package.json
βββ src/
βββ block.json
βββ index.js <- editor (registerBlockType, edit)
βββ view.js <- frontend store (script module)
βββ render.php <- server markup + data-wp-* direktivalar
src/block.json¶
{
"$schema": "https://schemas.wp.org/trunk/block.json",
"apiVersion": 3,
"name": "kitob/akkordion",
"title": "Akkordion",
"category": "design",
"icon": "list-view",
"description": "Interactivity API bilan ochiladigan akkordion.",
"textdomain": "kitob",
"supports": {
"interactivity": true,
"html": false
},
"attributes": {
"sarlavha": { "type": "string", "default": "Savol" },
"matn": { "type": "string", "default": "Javob matni." }
},
"editorScript": "file:./index.js",
"viewScriptModule": "file:./view.js",
"render": "file:./render.php"
}
src/index.js (editor)¶
import { registerBlockType } from '@wordpress/blocks';
import { useBlockProps, RichText } from '@wordpress/block-editor';
import { __ } from '@wordpress/i18n';
import metadata from './block.json';
registerBlockType( metadata.name, {
edit: ( { attributes, setAttributes } ) => {
const blockProps = useBlockProps();
return (
<div { ...blockProps }>
<RichText
tagName="strong"
value={ attributes.sarlavha }
onChange={ ( sarlavha ) => setAttributes( { sarlavha } ) }
placeholder={ __( 'Savol', 'kitob' ) }
/>
<RichText
tagName="p"
value={ attributes.matn }
onChange={ ( matn ) => setAttributes( { matn } ) }
placeholder={ __( 'Javob...', 'kitob' ) }
/>
</div>
);
},
save: () => null,
} );
save: () => null β blok dinamik (24-bob), markupni render.php beradi. Editorda foydalanuvchi sarlavha va matnni RichText bilan tahrirlaydi; interaktivlik faqat frontendda kerak.
src/view.js (frontend store, script module)¶
import { store, getContext } from '@wordpress/interactivity';
store( 'kitob/akkordion', {
state: {
get ochiqMi() {
return getContext().ochiq;
},
},
actions: {
almashtir() {
const context = getContext();
context.ochiq = ! context.ochiq;
},
},
callbacks: {
init() {
const context = getContext();
if ( typeof context.ochiq === 'undefined' ) {
context.ochiq = false;
}
},
},
} );
src/render.php (server markup + direktivalar)¶
<?php
/**
* Akkordion bloki server render (Interactivity API).
*
* @var array $attributes
* @var string $content
* @var WP_Block $block
*/
$sarlavha = isset( $attributes['sarlavha'] ) ? $attributes['sarlavha'] : '';
$matn = isset( $attributes['matn'] ) ? $attributes['matn'] : '';
$wrapper = get_block_wrapper_attributes( array( 'class' => 'kitob-akkordion' ) );
?>
<div
<?php echo $wrapper; ?>
data-wp-interactive="kitob/akkordion"
<?php echo wp_interactivity_data_wp_context( array( 'ochiq' => false ) ); ?>
data-wp-init="callbacks.init"
>
<button
type="button"
class="kitob-akkordion__tugma"
data-wp-on--click="actions.almashtir"
data-wp-bind--aria-expanded="state.ochiqMi"
>
<?php echo esc_html( $sarlavha ); ?>
</button>
<div
class="kitob-akkordion__panel"
data-wp-bind--hidden="!state.ochiqMi"
>
<p><?php echo esc_html( $matn ); ?></p>
</div>
</div>
Mantiq:
data-wp-interactive="kitob/akkordion"βstore()namespace'iga ulaydi.wp_interactivity_data_wp_context(...)βochiq: falselokal holatni xavfsiz yozadi.- Tugma bosilsa
actions.almashtircontext.ochiqni teskari qiladi. data-wp-bind--aria-expanded="state.ochiqMi"β accessibility uchun ARIA holatini state'ga bog'laydi.data-wp-bind--hidden="!state.ochiqMi"β panelochiqbo'lmasahiddenatributi qo'shiladi (yopiq).- Har bir foydalanuvchi qiymati (
$sarlavha,$matn)esc_htmlbilan escape qilingan (27-bob).
PHP ulanishi (functions.php yoki plagin)¶
block.json dagi render, viewScriptModule va supports.interactivity kalitlari tufayli WordPress render.php ni, view modulni va Interactivity runtime'ni avtomatik ulaydi.
Qurish (build)¶
Interactivity API script modullari --experimental-modules bayrog'ini talab qiladi (script module sifatida emit qilish uchun):
Tasdiqlangan natija (illustrativ emas): bu bobning bloklari (
akkordioninteraktiv +karta-konteynerInnerBlocks) jonli WordPress 7.0 muhitida (@wordpress/scripts@^32) quyidagicha tekshirildi: -npx wp-scripts build --experimental-modulesβwebpack compiled successfully; -build/akkordion/view.js[javascript module]sifatida emit qilindi,build/akkordion/view.asset.phpda bog'liqlik:array('@wordpress/interactivity'), 'type' => 'module'β bustore/getContextning@wordpress/interactivitydan to'g'ri import qilinganini va script module ekanini isbotlaydi; -build/akkordion/render.phpβphp -lbilan: No syntax errors detected; - ikkalablock.jsonβ yaroqli JSON (json_decodemuvaffaqiyatli); -karta-konteynerbuild/container/index.asset.phpbog'liqliklari:wp-block-editor, wp-blocksβuseInnerBlocksPropsning@wordpress/block-editordan kelganini tasdiqlaydi; - API nomlari yadro manbasidan tekshirildi:data-wp-*direktivalar vadata-wp-on--clicksuffiksiwp-includes/interactivity-api/class-wp-interactivity-api.phpda;viewScriptModule(@since 6.5.0) vasupports.interactivitywp-includes/blocks.phpda;wp_interactivity_data_wp_context/_state/_configwp-includes/interactivity-api/interactivity-api.phpda;registerBlockVariation/registerBlockStyle/unregisterBlockStylevauseInnerBlocksPropsyadro JS bundle'larida (wp-includes/js/dist/blocks,block-editor).
Amaliy: InnerBlocks konteyner bloki¶
Endi InnerBlocks bilan karta-konteyner blokini quramiz β foydalanuvchi ichiga sarlavha, matn, rasm, tugma joylaydi.
src/block.json¶
{
"$schema": "https://schemas.wp.org/trunk/block.json",
"apiVersion": 3,
"name": "kitob/karta-konteyner",
"title": "Karta konteyner",
"category": "design",
"icon": "layout",
"description": "InnerBlocks bilan karta konteyner.",
"textdomain": "kitob",
"supports": {
"html": false,
"color": { "background": true, "text": true },
"spacing": { "padding": true }
},
"editorScript": "file:./index.js",
"style": "file:./style-index.css"
}
src/index.js¶
import { registerBlockType } from '@wordpress/blocks';
import { useBlockProps, useInnerBlocksProps } from '@wordpress/block-editor';
import metadata from './block.json';
const ALLOWED = [ 'core/heading', 'core/paragraph', 'core/image', 'core/buttons' ];
const TEMPLATE = [
[ 'core/heading', { level: 3, placeholder: 'Karta sarlavhasi' } ],
[ 'core/paragraph', { placeholder: 'Karta matni...' } ],
];
registerBlockType( metadata.name, {
edit: () => {
const blockProps = useBlockProps( { className: 'kitob-karta' } );
const innerBlocksProps = useInnerBlocksProps( blockProps, {
allowedBlocks: ALLOWED,
template: TEMPLATE,
templateLock: false,
orientation: 'vertical',
} );
return <div { ...innerBlocksProps } />;
},
save: () => {
const blockProps = useBlockProps.save( { className: 'kitob-karta' } );
const innerBlocksProps = useInnerBlocksProps.save( blockProps );
return <div { ...innerBlocksProps } />;
},
} );
Bu blok statik (save markup qaytaradi) β InnerBlocks markupi useInnerBlocksProps.save orqali bazaga yoziladi. color/spacing supports foydalanuvchiga fon va padding sozlashga imkon beradi. Build natijasi yuqoridagi "Tasdiqlangan natija" da hujjatlangan.
Mashqlar¶
Oson¶
- InnerBlocks save'ni tuzating. Quyidagi blokda muammo bor β bola bloklar saqlanmaydi. Toping va tuzating:
allowedBlockscheklash.<InnerBlocks />ni shunday yozing: ichiga faqatcore/headingvacore/paragraphqo'shilsin.- Block style ro'yxatga olish.
core/buttonblokiganame: 'yumaloq', label "Yumaloq" uslubiniregisterBlockStylebilan qo'shing va unga mos.is-style-yumaloqCSS klassini (yumaloq burchaklar) yozing. block.jsonda style. O'z blokingizblock.jsonga ikki uslub e'lon qiling: "Oddiy" (default) va "Soyali". JS chaqiruvsiz, faqatstylesmassivi orqali.
O'rta¶
useInnerBlocksPropsga o'tkazing. 1-mashqdagi<InnerBlocks />li blokniuseInnerBlocksPropshookiga aylantiring (edit va save) β qo'shimcha<div>o'rovisiz, bitta element bo'lsin.template+templateLock. InnerBlocks shunday sozlang: birinchi qo'shilganda ichidacore/imagevacore/heading(h4) paydo bo'lsin, foydalanuvchi blok qo'sha/o'chira olmasin (faqat tarkibni tahrirlasin).templateLockning qaysi qiymatini tanladingiz va nega?- Block variation.
core/columnsblokiga "Ikki ustun karta" variationini ro'yxatga oling (name,title,icon,scope: ['inserter']): ikki ustun ichida har birida bittacore/groupbo'lsin (innerBlocks). isActiveqo'shish. 7-mashqdagi variationgaisActiveqo'shing, uverticalAlignmentatributi bo'yicha faolligini aniqlasin (massiv shaklida). NegaisActivekerakligini bir jumlada tushuntiring.
Qiyin¶
- To'liq interaktiv "ko'proq ko'rish" bloki.
block.json+view.js+render.phpto'liq yozing: matn boshida qisqargan, "Ko'proq ko'rish" tugmasi bosilsa to'liq matn ochilsin.data-wp-contextdakengaytirilgan: false,data-wp-on--clickactionalmashtir,data-wp-bind--hiddenpanelda.supports.interactivity: truevaviewScriptModulebo'lsin.render.phpniphp -lbilan tekshiring. - Tab (yorliq) bloki β
data-wp-class. Interaktiv "tab" blokiningrender.phpvaview.jsini yozing: ikki tugma, faol tugmagadata-wp-class--faolorqaliis-faolklassi qo'shilsin, faol kontentdata-wp-bind--hiddenbilan boshqarilsin. Context'dafaolTab: 0.php -lbilan tekshiring. - InnerBlocks dinamik blokda. Konteyner blokni dinamik qiling:
save: () => null,block.jsongarender: "file:./render.php"qo'shing.render.phpda InnerBlocks markupini ($content)wp_kses_postbilan, blokniget_block_wrapper_attributes()bilan o'rab chiqaring.php -lbilan tekshiring. - Transform: paragraf β akkordion. Akkordion blokiga
transforms.fromqo'shing:core/paragraphni akkordionga aylantirsin, paragraf matni akkordionmatnatributiga, sarlavhaga esa "Savol" qo'yilsin.createBlockto'g'ri import qilinsin. - Hisoblagich bloki β to'liq Interactivity API. "Like" hisoblagich blok quring: tugma bosilsa son ortsin.
view.jsdastate(computed son matni),actions.qoshish,data-wp-textbilan sonni ko'rsatish,data-wp-contextdason: 0.render.phpdadata-wp-text="state.sonMatni". Build qaysi bayroq bilan qilinishini ayting va negaviewScriptModule(viewScriptemas) kerakligini tushuntiring.
Yechimlar¶
Yechim β 1
<InnerBlocks.Content /> unutilgan β bola bloklar markupi joylanmaydi, shuning uchun saqlanmaydi:
save: () => {
const blockProps = useBlockProps.save();
return (
<div { ...blockProps }>
<InnerBlocks.Content />
</div>
);
},
InnerBlocks ni import qilishni unutmang: import { useBlockProps, InnerBlocks } from '@wordpress/block-editor';. Bu eng ko'p uchraydigan InnerBlocks xatosi.
Yechim β 2
import { InnerBlocks } from '@wordpress/block-editor';
<InnerBlocks
allowedBlocks={ [ 'core/heading', 'core/paragraph' ] }
/>
allowedBlocks bergan massiv konteyner ichiga qo'shiladigan bloklarni cheklaydi. Boshqa bloklar (rasm, tugma) Inserter'da ko'rinmaydi.
Yechim β 3
JS (masalan editor.js yoki blokning index.js):
import { registerBlockStyle } from '@wordpress/blocks';
import { __ } from '@wordpress/i18n';
registerBlockStyle( 'core/button', {
name: 'yumaloq',
label: __( 'Yumaloq', 'kitob' ),
} );
CSS (style.css yoki blok style fayli):
registerBlockStyle "Styles" panelida "Yumaloq" tugmasini qo'shadi va tanlanganda is-style-yumaloq klassi paydo bo'ladi (is-style-{name} qoidasi).
Yechim β 4
block.json:
"styles": [
{ "name": "oddiy", "label": "Oddiy", "isDefault": true },
{ "name": "soyali", "label": "Soyali" }
]
CSS:
block.json styles massivi faqat o'z blokingiz uchun ishlaydi β JS chaqiruvi shart emas. isDefault: true "Oddiy" ni standart uslub qiladi.
Yechim β 5
import { useBlockProps, useInnerBlocksProps } from '@wordpress/block-editor';
edit: () => {
const blockProps = useBlockProps();
const innerBlocksProps = useInnerBlocksProps( blockProps );
return <div { ...innerBlocksProps } />;
},
save: () => {
const blockProps = useBlockProps.save();
const innerBlocksProps = useInnerBlocksProps.save( blockProps );
return <div { ...innerBlocksProps } />;
},
Endi <div> bir vaqtning o'zida ham wrapper, ham InnerBlocks konteyneri β ortiqcha o'rov yo'q. useInnerBlocksProps block-editor paketida (WP 7.0 yadrosida tasdiqlangan).
Yechim β 6
const TEMPLATE = [
[ 'core/image', {} ],
[ 'core/heading', { level: 4, placeholder: 'Sarlavha' } ],
];
<InnerBlocks
template={ TEMPLATE }
templateLock="contentOnly"
/>
templateLock="contentOnly" ni tanladim, chunki shart "blok qo'sha/o'chira olmasin, faqat tarkibni (rasm/matn) tahrirlasin" edi β bu aynan contentOnly ning vazifasi. 'all' bo'lsa tarkib ham qulflanardi (matnni ham o'zgartirib bo'lmasdi).
Yechim β 7
import { registerBlockVariation } from '@wordpress/blocks';
import { __ } from '@wordpress/i18n';
registerBlockVariation( 'core/columns', {
name: 'ikki-ustun-karta',
title: __( 'Ikki ustun karta', 'kitob' ),
icon: 'columns',
scope: [ 'inserter' ],
attributes: {},
innerBlocks: [
[ 'core/column', {}, [ [ 'core/group', {} ] ] ],
[ 'core/column', {}, [ [ 'core/group', {} ] ] ],
],
} );
innerBlocks har element [ 'blok/nomi', { atributlar }, [ bola bloklar ] ] formatida β bu yerda ikki ustun, har birida bitta group.
Yechim β 8
registerBlockVariation( 'core/columns', {
name: 'ikki-ustun-karta',
title: __( 'Ikki ustun karta', 'kitob' ),
icon: 'columns',
scope: [ 'inserter' ],
isActive: [ 'verticalAlignment' ],
attributes: { verticalAlignment: 'center' },
innerBlocks: [
[ 'core/column', {}, [ [ 'core/group', {} ] ] ],
[ 'core/column', {}, [ [ 'core/group', {} ] ] ],
],
} );
isActive kerak, chunki usiz editor blok inspector'ida qaysi variation tanlanganini aniqlay olmaydi va variation nomini ko'rsata olmaydi (oddiy "Columns" deb qoladi). [ 'verticalAlignment' ] β WordPress shu atributni taqqoslab variationni tanib oladi.
Yechim β 9
block.json (asosiy qismlar):
{
"apiVersion": 3,
"name": "kitob/koproq",
"title": "Ko'proq ko'rish",
"category": "design",
"supports": { "interactivity": true, "html": false },
"attributes": {
"qisqa": { "type": "string", "default": "" },
"toliq": { "type": "string", "default": "" }
},
"editorScript": "file:./index.js",
"viewScriptModule": "file:./view.js",
"render": "file:./render.php"
}
view.js:
import { store, getContext } from '@wordpress/interactivity';
store( 'kitob/koproq', {
state: {
get kengaytirilganMi() {
return getContext().kengaytirilgan;
},
},
actions: {
almashtir() {
const context = getContext();
context.kengaytirilgan = ! context.kengaytirilgan;
},
},
} );
render.php:
<?php
/** @var array $attributes */
$qisqa = isset( $attributes['qisqa'] ) ? $attributes['qisqa'] : '';
$toliq = isset( $attributes['toliq'] ) ? $attributes['toliq'] : '';
?>
<div
<?php echo get_block_wrapper_attributes(); ?>
data-wp-interactive="kitob/koproq"
<?php echo wp_interactivity_data_wp_context( array( 'kengaytirilgan' => false ) ); ?>
>
<p><?php echo esc_html( $qisqa ); ?></p>
<p data-wp-bind--hidden="!state.kengaytirilganMi">
<?php echo esc_html( $toliq ); ?>
</p>
<button type="button" data-wp-on--click="actions.almashtir">
<?php echo esc_html__( 'Ko\'proq ko\'rish', 'kitob' ); ?>
</button>
</div>
php -l render.php β No syntax errors detected. To'liq matn data-wp-bind--hidden orqali yashirin, tugma bosilsa context'dagi kengaytirilgan teskari bo'ladi va panel ochiladi.
Yechim β 10
view.js:
import { store, getContext } from '@wordpress/interactivity';
store( 'kitob/tab', {
actions: {
tanla() {
const context = getContext();
context.faolTab = context.tabRaqam;
},
},
} );
render.php (soddalashtirilgan, ikki tab):
<?php $wrapper = get_block_wrapper_attributes( array( 'class' => 'kitob-tab' ) ); ?>
<div
<?php echo $wrapper; ?>
data-wp-interactive="kitob/tab"
<?php echo wp_interactivity_data_wp_context( array( 'faolTab' => 0 ) ); ?>
>
<div class="kitob-tab__tugmalar">
<button type="button"
data-wp-context='{"tabRaqam":0}'
data-wp-on--click="actions.tanla"
data-wp-class--is-faol="state.birinchiFaol">
<?php echo esc_html__( 'Birinchi', 'kitob' ); ?>
</button>
<button type="button"
data-wp-context='{"tabRaqam":1}'
data-wp-on--click="actions.tanla"
data-wp-class--is-faol="state.ikkinchiFaol">
<?php echo esc_html__( 'Ikkinchi', 'kitob' ); ?>
</button>
</div>
<div data-wp-bind--hidden="state.ikkinchiFaol"><p>Birinchi kontent</p></div>
<div data-wp-bind--hidden="state.birinchiFaol"><p>Ikkinchi kontent</p></div>
</div>
view.js da computed state'lar (ota context'dagi faolTab ni taqqoslab):
state: {
get birinchiFaol() { return getContext().faolTab === 0; },
get ikkinchiFaol() { return getContext().faolTab === 1; },
},
php -l render.php β No syntax errors detected. Har tugmada o'z data-wp-context (tabRaqam) bor; tanla ota faolTab ni o'rnatadi; data-wp-class--is-faol faol tugmaga klass qo'shadi. (Eslatma: ichki context ota kontekstni meros qiladi, shuning uchun faolTab ham ko'rinadi.)
Yechim β 11
index.js:
block.json:
render.php:
<?php
/** @var string $content */
$wrapper = get_block_wrapper_attributes( array( 'class' => 'kitob-karta' ) );
?>
<div <?php echo $wrapper; ?>>
<?php echo wp_kses_post( $content ); ?>
</div>
php -l render.php β No syntax errors detected. Dinamik blokda InnerBlocks markupi $content orqali keladi (24-bob); uni wp_kses_post bilan xavfsiz chiqaramiz. useInnerBlocksProps.save o'rniga PHP'da get_block_wrapper_attributes() ishlatamiz.
Yechim β 12
import { createBlock } from '@wordpress/blocks';
// registerBlockType( metadata.name, { ... }) ichidagi obyektga:
transforms: {
from: [
{
type: 'block',
blocks: [ 'core/paragraph' ],
transform: ( attributes ) =>
createBlock( 'kitob/akkordion', {
sarlavha: 'Savol',
matn: attributes.content,
} ),
},
],
},
type: 'block' + blocks: ['core/paragraph'] β paragrafni tanlab "Akkordion" ga aylantirish mumkinligini bildiradi. transform callback yangi blokni createBlock bilan yaratadi: paragraf content β akkordion matn, sarlavha statik "Savol". createBlock @wordpress/blocks dan import qilinadi.
Yechim β 13
block.json (asosiy): supports.interactivity: true, viewScriptModule: "file:./view.js", render: "file:./render.php".
view.js:
import { store, getContext } from '@wordpress/interactivity';
store( 'kitob/hisoblagich', {
state: {
get sonMatni() {
return String( getContext().son );
},
},
actions: {
qoshish() {
getContext().son += 1;
},
},
} );
render.php:
<?php $wrapper = get_block_wrapper_attributes( array( 'class' => 'kitob-hisoblagich' ) ); ?>
<div
<?php echo $wrapper; ?>
data-wp-interactive="kitob/hisoblagich"
<?php echo wp_interactivity_data_wp_context( array( 'son' => 0 ) ); ?>
>
<button type="button" data-wp-on--click="actions.qoshish">
<?php echo esc_html__( 'Like', 'kitob' ); ?>
</button>
<span data-wp-text="state.sonMatni"></span>
</div>
php -l render.php β No syntax errors detected.
Build: npx wp-scripts build --experimental-modules. --experimental-modules kerak, chunki Interactivity API script module (ES import/export) bilan ishlaydi β bu bayroqsiz wp-scripts view.js ni module sifatida emit qilmaydi.
Nega viewScriptModule (viewScript emas): Interactivity API view.js da import { store, getContext } from '@wordpress/interactivity' qatorini ishlatadi β bu ES module sintaksisi. viewScript oddiy <script> (global) yuklaydi va import ni qo'llab-quvvatlamaydi; viewScriptModule esa <script type="module"> sifatida yuklaydi va @wordpress/interactivity ni module bog'liqligi sifatida to'g'ri ulaydi (build natijasidagi view.asset.php da 'type' => 'module' shuni tasdiqlaydi).
β¬ οΈ Oldingi: 24 β Dinamik bloklar (render_callback) Β· π README Β· Keyingi: 26 β WooCommerce tema integratsiyasi β‘οΈ