自定义Gutenberg块重载编辑器后出现内容验证错误求助
自定义Gutenberg块验证失败问题修复
问题
自定义Gutenberg块包含两张图片,运行正常,但重载编辑器页面或重新打开时,会提示“此块包含意外或无效内容”,点击“解决”按钮时,系统标记img标签的闭合标签。
错误原因
- img标签写法不符合规范:
save函数中第二个img使用了<img></img>的闭合写法,HTML里img是自闭合标签,这种写法会触发Gutenberg的块验证机制报错。 - block.json属性选择器不匹配:
softwareName和softwareDescription的selector设为div,但实际渲染时这两个内容分别在h4和p标签内,导致Gutenberg无法正确解析属性值,引发验证失败。 - 硬编码图片未作为块属性存储:
save函数里的bannerImg是硬编码资源,未加入块属性,编辑器重新加载时无法匹配静态内容,导致验证不通过。
修复方案
1. 统一img标签写法
将所有img标签改为自闭合格式<img />,符合HTML规范。
2. 修正block.json属性选择器
调整softwareName和softwareDescription的selector,匹配实际渲染的标签:
softwareName的selector改为h4softwareDescription的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
相关产品推荐
相关产品推荐

