使用 ESNEXT 的古腾堡中继器块

Yuk*_*uki 4 javascript wordpress jsx wordpress-gutenberg gutenberg-blocks

我一直致力于创建自己的自定义古腾堡中继器块,其中包含文本和链接输入字段。我只见过这样ES5示例。我已经花了近 8 个小时来创建这些示例的我自己的版本,但我陷入了困境。

\n\n

我来这里是因为我希望有人指出正确的方向(非常需要帮助)。

\n\n

这是我目前拥有的代码。我不知道从哪里开始 ES5 -> ESNEXT 转换。

\n\n

编辑:我忘了说我正在尝试避免使用 ACF

\n\n
// Importing code libraries for this block\nimport { __ } from \'@wordpress/i18n\';\nimport { registerBlockType } from \'@wordpress/blocks\';\nimport { RichText, MediaUpload, InspectorControls } from \'@wordpress/block-editor\';\nimport { Button, ColorPicker, ColorPalette, Panel, PanelBody, PanelRow } from \'@wordpress/components\';\n\nregisterBlockType(\'ccm-block/banner-block\', {\n    title: __(\'Banner Block\'),\n    icon: \'format-image\', // from Dashicons \xe2\x86\x92 https://developer.wordpress.org/resource/dashicons/.\n    category: \'layout\', // E.g. common, formatting, layout widgets, embed.\n    keywords: [\n        __(\'Banner Block\'),\n        __(\'CCM Blocks\'),\n    ],\n    attributes: {\n        mediaID: {\n            type: \'number\'\n        },\n        mediaURL: {\n            type: \'string\'\n        },\n        title: {\n            type: \'array\',\n            source: \'children\',\n            selector: \'h1\'\n        },\n        content: {\n            type: \'array\',\n            source: \'children\',\n            selector: \'p\'\n        },\n        bannerButtons: {\n            type: \'array\',\n            source: \'children\',\n            selector: \'.banner-buttons\',\n        },\n        items: {\n            type: \'array\',\n            default: []\n        }\n    },\n\n    /**\n     * The edit function relates to the structure of the block when viewed in the editor.\n     *\n     * @link https://wordpress.org/gutenberg/handbook/block-api/block-edit-save/\n     *\n     * @param {Object} props Props.\n     * @returns {Mixed} JSX Component.\n     */\n    edit: (props) => {\n\n        const {\n            attributes: { mediaID, mediaURL, title, content, bannerButtons },\n            setAttributes, className\n        } = props;\n\n        const onSelectImage = (media) => {\n            setAttributes({\n                mediaURL: media.url,\n                mediaID: media.id,\n            });\n        };\n\n        const onChangeTitle = (value) => {\n            setAttributes({ title: value });\n        };\n\n        const onChangeContent = (value) => {\n            setAttributes({ content: value });\n        };\n\n        const onChangeBannerButtons = (value) => {\n            setAttributes({ bannerButtons: value });\n        };\n\n        // console.log(items);\n        // var itemList = items.sort\n\n        return (\n            <div className={className}>\n                <div id="#home-banner">\n                    <MediaUpload\n                        onSelect={onSelectImage}\n                        allowedTypes="image"\n                        value={mediaID}\n                        render={({ open }) => (\n                            <Button className={mediaID ? \'image-button\' : \'button button-large\'} onClick={open}>\n                                {!mediaID ? __(\'Upload Image\', \'ccm-blocks\') : <img src={mediaURL} alt={__(\'Featured Image\', \'ccm-blocks\')} />}\n                            </Button>\n                        )}\n                    />\n\n                    <RichText\n                        tagName="h1"\n                        placeholder={__(\'Insert Title Here\', \'ccm-blocks\')}\n                        className={className}\n                        onChange={onChangeTitle}\n                        value={title}\n                    />\n\n                    <RichText\n                        tagName="p"\n                        placeholder={__(\'Insert your short description here...\', \'ccm-blocks\')}\n                        className={className}\n                        onChange={onChangeContent}\n                        value={content}\n                    />\n\n                    <RichText\n                        tagName="ul"\n                        multiline="li"\n                        className="banner-buttons"\n                        placeholder={ __(\'Add a banner button link (max of 2)\', \'ccm-blocks\') }\n                        onChange={ onChangeBannerButtons }\n                        value={ bannerButtons }\n                    />\n                </div>\n            </div>\n\n        );\n    },\n\n    /**\n     * The save function determines how the different attributes should be combined into the final markup.\n     * Which is then serialised into the post_content.\n     *\n     * @link https://wordpress.org/gutenberg/handbook/block-api/block-edit-save/\n     *\n     * @param {Object} props Props.\n     * @returns {Mixed} JSX Frontend HTML.\n     */\n    save: (props) => {\n        return (\n            <div className={ props.className }>\n                <div id="home-banner" style={{backgroundImage: `url(${ props.attributes.mediaURL })`}}>\n                    <div class="container">\n                        <div class="row">\n                            <div class="col-12">\n                                <div class="content-inner">\n                                    <RichText.Content tagName="h1" className={ props.className } value={ props.attributes.title } />\n                                    <RichText.Content tagName="p" className={ props.className } value={ props.attributes.content } />\n                                    <RichText.Content tagName="ul" className="banner-buttons" value={ props.attributes.bannerButtons } />\n                                </div>\n                            </div>\n                        </div>\n                    </div>\n                </div>\n            </div>\n        );\n    },\n});\n
Run Code Online (Sandbox Code Playgroud)\n\n

编辑2:这是我失败的尝试

\n\n
// Importing code libraries for this block\nimport { __ } from \'@wordpress/i18n\';\nimport { registerBlockType } from \'@wordpress/blocks\';\nimport { RichText, MediaUpload, InspectorControls } from \'@wordpress/block-editor\';\nimport { Button, ColorPicker, ColorPalette, Panel, PanelBody, PanelRow } from \'@wordpress/components\';\n\n/**\n * Register the Block\n * \n * @link https://wordpress.org/gutenberg/handbook/block-api/\n * @param  {string}   name     name.\n * @param  {Object}   settings settings.\n * @return {?WPBlock}          The block, otherwise `undefined`.\n */\nregisterBlockType(\'ccm-block/banner-block\', {\n    title: __(\'Banner Block\'),\n    icon: \'format-image\', // from Dashicons \xe2\x86\x92 https://developer.wordpress.org/resource/dashicons/.\n    category: \'layout\', // E.g. common, formatting, layout widgets, embed.\n    keywords: [\n        __(\'Banner Block\'),\n        __(\'CCM Blocks\'),\n    ],\n    attributes: {\n        mediaID: {\n            type: \'number\'\n        },\n        mediaURL: {\n            type: \'string\'\n        },\n        title: {\n            type: \'array\',\n            source: \'children\',\n            selector: \'h1\'\n        },\n        content: {\n            type: \'array\',\n            source: \'children\',\n            selector: \'p\'\n        },\n        bannerButtons: {\n            type: \'array\',\n            source: \'children\',\n            selector: \'.banner-buttons\',\n        },\n        items: {\n            source: \'query\',\n            default: [],\n            selector: \'.item\',\n            query: {\n                title: {\n                    type: \'string\',\n                    source: \'text\',\n                    selector: \'.title\'\n                },\n                index: {            \n                    type: \'number\',\n                    source: \'attribute\',\n                    attribute: \'data-index\'            \n                }           \n            }\n        }\n    },\n\n    /**\n     * The edit function relates to the structure of the block when viewed in the editor.\n     *\n     * @link https://wordpress.org/gutenberg/handbook/block-api/block-edit-save/\n     *\n     * @param {Object} props Props.\n     * @returns {Mixed} JSX Component.\n     */\n    edit: (props) => {\n\n        const {\n            attributes: { mediaID, mediaURL, title, content, bannerButtons, items },\n            setAttributes, className\n        } = props;\n\n        const onSelectImage = (media) => {\n            setAttributes({\n                mediaURL: media.url,\n                mediaID: media.id,\n            });\n        };\n\n        const onChangeTitle = (value) => {\n            setAttributes({ title: value });\n        };\n\n        const onChangeContent = (value) => {\n            setAttributes({ content: value });\n        };\n\n        const onChangeBannerButtons = (value) => {\n            setAttributes({ bannerButtons: value });\n        };\n\n        // Clone an array of objects\n        function _cloneArray(arr) {\n            if (Array.isArray(arr)) {\n              for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) {\n                arr2[i] = arr[i];\n              }\n              return arr2;\n            } else {\n              return Array.from(arr);\n            }\n        }\n        // return repeater items\n        var itemList = items.sort(function(a, b){\n            return a.index - b.index;\n        }).map(function(item){\n            console.log(item);\n            return(\n                <RichText\n                    tagName="h1"\n                    placeholder={ __(\'Test\', \'ccm-blocks\') }\n                    value={ item.title }\n                    onChange={ function(value){\n                        var newObject = Object.assign({}, item, {\n                            title: value\n                        });\n                        setAttributes({\n                            items: [].concat(_cloneArray(items.filter(function(itemFilter){\n                                return itemFilter.index != item.index;\n                            })), [newObject])\n                        });\n                    } }\n                />\n            );\n        });\n\n        // \n        console.log(itemList);\n\n        return (\n            <div className={className}>\n                <div id="#home-banner">\n                    <RichText\n                        className="item-list"\n                        tagName="h1"\n                        value={ itemList }\n                    />\n\n                    <Button\n                        className="button add-row"\n                        onClick={ function(){\n                            setAttributes({\n                                items: [].concat(_cloneArray(items), [{\n                                    index: items.length,\n                                    title: ""\n                                }])\n                            });\n                        } }\n                    >\n                        Add a button\n                    </Button>\n\n                    <MediaUpload\n                        onSelect={onSelectImage}\n                        allowedTypes="image"\n                        value={mediaID}\n                        render={({ open }) => (\n                            <Button className={mediaID ? \'image-button\' : \'button button-large\'} onClick={open}>\n                                {!mediaID ? __(\'Upload Image\', \'ccm-blocks\') : <img src={mediaURL} alt={__(\'Featured Image\', \'ccm-blocks\')} />}\n                            </Button>\n                        )}\n                    />\n\n                    <RichText\n                        tagName="h1"\n                        placeholder={__(\'Insert Title Here\', \'ccm-blocks\')}\n                        className={className}\n                        onChange={onChangeTitle}\n                        value={title}\n                    />\n\n                    <RichText\n                        tagName="p"\n                        placeholder={__(\'Insert your short description here...\', \'ccm-blocks\')}\n                        className={className}\n                        onChange={onChangeContent}\n                        value={content}\n                    />\n\n                    <RichText\n                        tagName="ul"\n                        multiline="li"\n                        className="banner-buttons"\n                        placeholder={ __(\'Add a banner button link (max of 2)\', \'ccm-blocks\') }\n                        onChange={ onChangeBannerButtons }\n                        value={ bannerButtons }\n                    />\n                </div>\n            </div>\n\n        );\n    },\n\n    /**\n     * The save function determines how the different attributes should be combined into the final markup.\n     * Which is then serialised into the post_content.\n     *\n     * @link https://wordpress.org/gutenberg/handbook/block-api/block-edit-save/\n     *\n     * @param {Object} props Props.\n     * @returns {Mixed} JSX Frontend HTML.\n     */\n    save: (props) => {\n        return (\n            <div className={ props.className }>\n                <div id="home-banner" style={{backgroundImage: `url(${ props.attributes.mediaURL })`}}>\n                    <div class="container">\n                        <div class="row">\n                            <div class="col-12">\n                                <div class="content-inner">\n                                    <RichText.Content tagName="h1" className={ props.className } value={ props.attributes.title } />\n                                    <RichText.Content tagName="p" className={ props.className } value={ props.attributes.content } />\n                                    <RichText.Content tagName="ul" className="banner-buttons" value={ props.attributes.bannerButtons } />\n                                </div>\n                            </div>\n                        </div>\n                    </div>\n                </div>\n            </div>\n        );\n    },\n});\n
Run Code Online (Sandbox Code Playgroud)\n

Yuk*_*uki 6

我已经想通了!!经过无数个小时的修改,这就是我想出的结果。这是我想要的一个粗糙版本,但它绝对有效!这是我找到的教程之一的链接链接。

// Importing code libraries for this block
import { __ } from '@wordpress/i18n';
import { registerBlockType } from '@wordpress/blocks';
import { RichText } from '@wordpress/block-editor';
import { Button } from '@wordpress/components';

// Register the block
registerBlockType( 'test-block/custom-repeater-block', {
    title: __('Repeater Block'),
    icon: 'layout',
    category: 'layout',
    keywords: [
        __('Custom Block'),
    ],
    attributes: {
        info: {
            type: 'array',
            selector: '.info-wrap'
        }
    },

    // edit function
    edit: (props) => {
        const {
            attributes: { info = [] },
            setAttributes, className
        } = props;

        const infoList = (value) => {
            return(
                value.sort((a, b) => a.index - b.index).map(infoItem => {
                    return(
                        <div className="info-item">
                            <Button
                                className="remove-item"
                                onClick={ () => {
                                    const newInfo = info.filter(item => item.index != infoItem.index).map(i => {
                                        if(i.index > infoItem.index){
                                            i.index -= 1;
                                        }
                                        return i;
                                    } );
                                    setAttributes({ info: newInfo });
                                } }
                            >&times;</Button>
                            <h3>Number {infoItem.index}</h3>
                            <RichText
                                tagName="h4"
                                className="info-item-title"
                                placeholder="Enter the title here"
                                value={infoItem.title}
                                style={{ height: 58 }}
                                onChange={ title => {
                                    const newObject = Object.assign({}, infoItem, {
                                        title: title
                                    });
                                    setAttributes({
                                        info: [...info.filter(
                                            item => item.index != infoItem.index
                                        ), newObject]
                                    });
                                } }
                            />
                            <RichText
                                tagName="p"
                                className="info-item-description"
                                placeholder="Enter description"
                                value={infoItem.description}
                                style={{ height: 58 }}
                                onChange={ description => {
                                    const newObject = Object.assign({}, infoItem, {
                                        description: description
                                    });
                                    setAttributes({
                                        info: [...info.filter(
                                            item => item.index != infoItem.index
                                        ), newObject]
                                    });
                                } }
                            />
                        </div>
                    )
                })
            )
        }

        return(
            <div className={className}>
                <div className="info-wrap">{infoList(info)}</div>
                <Button onClick={title => {
                    setAttributes({
                        info: [...info, {
                            index: info.length,
                            title: "",
                            description: ""
                        }]
                    });
                }}>Add Item</Button>
            </div>
        );
    },

    // save function
    save: (props) => {
        const info = props.attributes.info;
        const displayInfoList = (value) => {
            return(
                value.map( infoItem => {
                    return(
                        <div className="info-item">
                            <RichText.Content
                                tagName="h4"
                                className="info-item-title"
                                value={infoItem.title}
                                style={{ height: 58 }}
                            />
                        </div>
                    )
                } )
            )
        }

        return(
            <div className={props.className}>
                <div className="info-wrap">{ displayInfoList(info) }</div>
            </div>
        );
    }
} )
Run Code Online (Sandbox Code Playgroud)