使用InnerBlock序列化自定义块

时间:2021-01-08 作者:user9

我有一个自定义的gutenberg块和任意的内部块。由于使用自定义javascript库的原因,我无法使用<InnerBlocks> 组件,但希望迭代所有块,并在我的块的编辑函数中显示块及其内部块。

我想用swiper 图书馆我努力使InnerBlocks(带有工具栏和其他UI)真正工作,但效果不佳。首先,swiper需要一个特殊的DOM结构,这是我无法使用的InnerBlocks 组件,因为它具有预先定义的包装器和div结构。其次,swiper克隆在循环时会滑动,这最终会在克隆整个gutenberg块ui时导致react错误。所以我发现最有效的方法是在我的区块中有一个按钮,可以在;“编辑模式”;和;预览模式“;,在那里您可以看到InnerBlocks 具有所有用于添加、在编辑中移动以及在预览模式下查看滑块的UI。

我正在使用代码(简化):

{ innerBlocks.map( ( block ) => {
    return (
        <div
            key={ block.clientId }
            dangerouslySetInnerHTML={ { __html: wp.blocks.getBlockContent( block ) } }
        >
        </div>
    );
} ) }
这适用于大多数内部块,如core/heading, core/paragraph, ... 但对于嵌入,例如,它只显示嵌入的url,而不显示嵌入的媒体内容,例如来自Youtube的内容。我发现wp.blocks.serializewp.blocks.rawHandler 但也无法让它发挥作用。我做错了什么。

我正在寻找让嵌入在没有<InnerBlocks> 或者对于使用swiper(启用循环)的解决方案<InnerBlocks>.

1 个回复
SO网友:Tom J Nowell

对于依赖前端javascript的块,您所要求的是不可能的,这包括嵌入。

也不可能使用Swiper react库。Swiper库选择手动检查SwiperSlide 组件名称,防止其与子块一起使用。

Edit: Actually maybe it is! 自从写了这篇文章,a PR was merged that may fix this and allow the code below to work as desired

jQuery也不可能与内部块一起使用,因为它与React的工作方式冲突,并且会导致虚拟DOM问题。

如果我们使用React-Swiper库,您可以获得最接近的,useBlockProps, 和useInnerBlocksProps, 我们可以实现这一点,并拥有可编辑的幻灯片,同时保留滑块。

但是,Swiper将看不到所需组件的具体排列,并将它们放置在滑块容器之后,而不是包装内。

重要的是要注意以下片段:

        const blockProps = useBlockProps();
        const innerBlocksProps = useInnerBlocksProps( blockProps, {
            allowedBlocks: [ \'tomjn/swiper-slide\' ],
            template: TEMPLATE,
        });
        const params = {...};
        return (
            <div { ...innerBlocksProps }>
                <Swiper { ...params }>
                    { innerBlocksProps.children }
                </Swiper>
            </div>
        );
通过使用innerBlocksProps.children 我们消除了包含<div> 标签。

这是我的演示:

src/index.js

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

import SwiperCore, { Navigation, Pagination, Scrollbar, A11y } from \'swiper\';
import { Swiper, SwiperSlide } from \'swiper/react\';

// Import Swiper styles
import \'swiper/swiper-bundle.css\';

// install Swiper components
SwiperCore.use([Navigation, Pagination, Scrollbar, A11y]);

const TEMPLATE = [
    [ \'tomjn/swiper-slide\', {}, [
        [ \'core/paragraph\', { placeholder: \'Enter slide content...\' } ],
    ] ],
    [ \'tomjn/swiper-slide\', {}, [
        [ \'core/paragraph\', { placeholder: \'Enter slide content...\' } ],
    ] ]
];

registerBlockType( \'tomjn/swiper\', {
    apiVersion: 2,
    title: \'Swiper\',
    category: \'layout\',
    edit: () => {
        const blockProps = useBlockProps();
        const innerBlocksProps = useInnerBlocksProps( blockProps, {
            allowedBlocks: [ \'tomjn/swiper-slide\' ],
            template: TEMPLATE,
        });
        const params = {
            init: true,
            paceBetween: 50,
            slidesPerView: 2,
            loop: true,
            navigation: {
                clickable: true,
            },
            spaceBetween: 30,
            pagination: {
                clickable: true,
            }
        };
        return (
            <div { ...innerBlocksProps }>
                <Swiper { ...params }>
                    { innerBlocksProps.children }
                </Swiper>
            </div>
        );
    },
    save: () => {
        return (
            <div className="swiper-container">
                <div className="swiper-wrapper">
                    <InnerBlocks.Content />
                </div>
                <div className="swiper-pagination"></div>
                <div className="swiper-button-prev"></div>
                <div className="swiper-button-next"></div>
            </div>
        );
    },
} );

registerBlockType( \'tomjn/swiper-slide\', {
    apiVersion: 2,
    title: \'Swiper Slide\',
    category: \'layout\',
    edit: () => {
        const blockProps = useBlockProps();
        return (
            <SwiperSlide>
                <div {...blockProps}>
                    <InnerBlocks />
                </div>
            </SwiperSlide>
        );
    },
    save: () => {
        return (
            <div class="swiper-slide">
                <InnerBlocks.Content />
            </div>
        );
    },
} );

package.json

{
    "dependencies": {
        "swiper": "^6.4.5"
    },
    "devDependencies": {
        "@wordpress/scripts": "^12.6.1"
    },
    "scripts": {
        "build": "wp-scripts build",
        "check-engines": "wp-scripts check-engines",
        "check-licenses": "wp-scripts check-licenses",
        "format:js": "wp-scripts format-js",
        "lint:css": "wp-scripts lint-style",
        "lint:js": "wp-scripts lint-js",
        "lint:md:docs": "wp-scripts lint-md-docs",
        "lint:md:js": "wp-scripts lint-md-js",
        "lint:pkg-json": "wp-scripts lint-pkg-json",
        "packages-update": "wp-scripts packages-update",
        "start": "wp-scripts start",
        "test:e2e": "wp-scripts test-e2e",
        "test:unit": "wp-scripts test-unit-js"
    }
}
plugin.php

<?php
/**
 * Plugin Name: Toms Swiper Plugin
 * Plugin URI: https://tomjn.com
 * Description: Swiper no swiping.
 * Requires at least: 5.5
 * Requires PHP: 7.3
 * Version: 1.0.0
 * Author: Tom J Nowell
 */

defined( \'ABSPATH\' ) || exit;

add_action(
    \'enqueue_block_editor_assets\',
    function() {
        $asset = include plugin_dir_path( __FILE__ ) . \'build/index.asset.php\';

        wp_register_script(
            \'tomjn-swiper-block-js\',
            plugins_url( \'build/index.js\', __FILE__ ),
            $asset[\'dependencies\'],
            $asset[\'version\'],
        );
        wp_register_style(
            \'tomjn-swiper-block-css\',
            plugins_url( \'build/index.css\', __FILE__ ),
            [],
            $asset[\'version\'],
        );
    }
);

/**
 * Registers all block assets so that they can be enqueued through Gutenberg in
 * the corresponding context.
 */
function tomjn_swiper_register_block() {

    if ( ! function_exists( \'register_block_type\' ) ) {
        // Gutenberg is not active.
        return;
    }

    register_block_type(
        \'tomjn/swiper\',
        [
            \'editor_script\' => \'tomjn-swiper-block-js\',
            \'editor_style\'  => \'tomjn-swiper-block-css\',
        ]
    );
    register_block_type(
        \'tomjn/swiperslide\',
        [
            \'editor_script\' => \'tomjn-swiper-block-js\',
            \'editor_style\'  => \'tomjn-swiper-block-css\',
        ]
    );

}
add_action( \'init\', \'tomjn_swiper_register_block\' );

相关推荐