You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义Gutenberg块重载编辑器后出现内容验证错误求助

自定义Gutenberg块验证失败问题修复

问题

自定义Gutenberg块包含两张图片,运行正常,但重载编辑器页面或重新打开时,会提示“此块包含意外或无效内容”,点击“解决”按钮时,系统标记img标签的闭合标签。

错误原因

  1. img标签写法不符合规范:save函数中第二个img使用了<img></img>的闭合写法,HTML里img是自闭合标签,这种写法会触发Gutenberg的块验证机制报错。
  2. block.json属性选择器不匹配:softwareName和softwareDescription的selector设为div,但实际渲染时这两个内容分别在h4和p标签内,导致Gutenberg无法正确解析属性值,引发验证失败。
  3. 硬编码图片未作为块属性存储:save函数里的bannerImg是硬编码资源,未加入块属性,编辑器重新加载时无法匹配静态内容,导致验证不通过。

修复方案

1. 统一img标签写法

将所有img标签改为自闭合格式<img />,符合HTML规范。

2. 修正block.json属性选择器

调整softwareName和softwareDescription的selector,匹配实际渲染的标签:

  • softwareName的selector改为h4
  • softwareDescription的selector改为p

3. 将banner图片转为块属性

添加bannerMediaID和bannerMediaURL属性,在Edit组件中加入MediaUpload控件让用户上传banner图,代替硬编码的bannerImg。

修改后的代码

save函数

export default function save({ attributes}) {
    const blockProps = useBlockProps.save();
    return (
        <div { ...blockProps }>
            <div className='col-text col'>
                <div className='name-icon'>
                    <figure className='icon'>
                        <a href={attributes.customUrl}>
                            <img
                                className="icon-app"
                                src={ attributes.mediaURL }
                                alt="icono app"
                            />
                        </a>
                    </figure>
                    <h4>{attributes.softwareName}</h4>
                </div>
                <p>{attributes.softwareDescription}</p>
            </div>
            <figure className='col col-image'>
                <a href={attributes.customUrl}>
                    <img 
                        src={ attributes.bannerMediaURL } 
                        alt='imagen banner descarga' 
                        style={{ width: '100%' }} 
                    />
                </a>
            </figure>
        </div>
    );
}

Edit组件

export default function Edit({attributes, setAttributes}) {
    return (
        <div className='banner-bsc' { ...useBlockProps() }>
            <div className='col-text col'>
                <div className='col-icon'>
                    <MediaUpload
                        onSelect={ ( media ) => setAttributes( { 
                            mediaURL: media.url,
                            mediaID: media.id 
                        }) }
                        allowedTypes="image"
                        value={ attributes.mediaID }
                        render={ ( { open } ) => (
                            <Button
                                className={ attributes.mediaID ? 'image-button' : 'button button-large' }
                                onClick={ open }
                            >
                                { ! attributes.mediaID ? (
                                    __( 'Sube el icono de la app', 'bsc-blocks' )
                                ) : (
                                    <img
                                        className='icon-app'
                                        src={ attributes.mediaURL }
                                        alt={ __( 'Sube el icono de la app' ) }
                                    />
                                ) }
                            </Button>
                        ) }
                    />
                </div>
                <RichText
                    tagName="h4"
                    placeholder={ __( 'CYPE Architecture' ) }
                    value={ attributes.softwareName }
                    onChange={( val ) => setAttributes( { softwareName: val }) }
                    className="nombre-programa"
                />
                <RichText
                    tagName="p"
                    placeholder={ __( '3D architectural modelling program, specifically designed for multidisciplinary collaboration.' ) }
                    value={ attributes.softwareDescription }
                    onChange={( val ) => setAttributes( { softwareDescription: val }) }
                    className="descripcion-programa"
                />
            </div>
            <figure className='col col-image'>
                <TextControl
                    label="Url banner"
                    value={ attributes.customUrl }
                    onChange={ ( val ) => setAttributes( {customUrl: val} ) }
                />
                <MediaUpload
                    onSelect={ ( media ) => setAttributes( { 
                        bannerMediaURL: media.url,
                        bannerMediaID: media.id 
                    }) }
                    allowedTypes="image"
                    value={ attributes.bannerMediaID }
                    render={ ( { open } ) => (
                        <Button
                            className={ attributes.bannerMediaID ? 'image-button' : 'button button-large' }
                            onClick={ open }
                        >
                            { ! attributes.bannerMediaID ? (
                                __( 'Sube el banner de descarga', 'bsc-blocks' )
                            ) : (
                                <img
                                    src={ attributes.bannerMediaURL }
                                    alt={ __( 'Banner de descarga' ) }
                                    style={{ width: '100%' }}
                                />
                            ) }
                        </Button>
                    ) }
                />
            </figure>
        </div>
    );
}

block.json

{
    "$schema": "https://schemas.wp.org/trunk/block.json",
    "apiVersion": 2,
    "name": "create-block/banner-descarga",
    "version": "0.1.0",
    "title": "Banner descarga",
    "category": "bimservercenter-categories",
    "icon": "smiley",
    "description": "Example block scaffolded with Create Block tool.",
    "supports": {
        "html": false
    },
    "textdomain": "banner-descarga",
    "editorScript": "file:./index.js",
    "editorStyle": "file:./index.css",
    "style": "file:./style-index.css", 
    "attributes": {
        "softwareName": {
            "type": "string",
            "source": "text",
            "selector": "h4",
            "default": "CYPE Architecture"
        },
        "softwareDescription": {
            "type": "string",
            "source": "text",
            "selector": "p",
            "default": "3D architectural modelling program, specifically designed for multidisciplinary collaboration."
        }, 
        "customUrl" : {
            "type": "string",
            "source": "attribute",
            "selector": "a",
            "attribute": "href",
            "default": "https://store.bimserver.center/en/"
        },
        "mediaID": {
            "type": "number"
        },
        "mediaURL": {
            "type": "string",
            "source": "attribute",
            "selector": ".icon-app",
            "attribute": "src"
        },
        "bannerMediaID": {
            "type": "number"
        },
        "bannerMediaURL": {
            "type": "string",
            "source": "attribute",
            "selector": ".col-image img",
            "attribute": "src"
        }
    }
}

内容的提问来源于stack exchange,提问作者lauselfe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 14:41:33