WordPress 古腾堡块验证失败:重新编辑时属性不匹配

问题描述 投票:0回答:1

我正在使用

@wordpress/create-block
包为 WordPress 开发自定义古腾堡块。该块允许用户添加带有图像、姓名、职位和推荐文本的推荐。该块在初始创建时工作正常,但当我尝试再次编辑它时,遇到块验证错误。

错误信息:

Block validation: Block validation failed for create-block/testimonial (Object1).
Expected attributes Array(1), instead saw Array(2)

数组(1)

["class", "testimonial-image", true]

数组(2)

["class", "testimonial-image", true]

["src", "http://test-1.local/wp-content/uploads/2024/06/some_profile_picture.jpeg", true]

物体

block.json:

{
    "$schema": "https://schemas.wp.org/trunk/block.json",
    "apiVersion": 3,
    "name": "create-block/testimonial",
    "version": "0.1.0",
    "title": "Testimonial",
    "category": "widgets",
    "icon": "smiley",
    "description": "Example block scaffolded with Create Block tool.",
    "attributes": {
        "imageUrl": {
            "type": "string",
            "source": "attribute",
            "selector": "img.testimonial-image",
            "attribute": "src"
        },
        "testimonial": {
            "type": "string",
            "source": "html",
            "selector": "blockquote.testimonial-quote p"
        },
        "name": {
            "type": "string",
            "source": "html",
            "selector": "div.testimonial-name"
        },
        "position": {
            "type": "string",
            "source": "html",
            "selector": "div.testimonial-position"
        }
    },
    "supports": {
        "html": false
    },
    "textdomain": "testimonial",
    "editorScript": "file:./index.js",
    "editorStyle": "file:./index.css",
    "style": "file:./style-index.css",
    "viewScript": "file:./view.js"
}

编辑.tsx:

import { __ } from '@wordpress/i18n';
import { useBlockProps, MediaUpload, MediaUploadCheck, RichText } from '@wordpress/block-editor';
import { Button } from '@wordpress/components';
import './editor.scss';

export default function Edit({ attributes, setAttributes }) {
    const { imageUrl, testimonial, name, position } = attributes;

    const onSelectImage = (media) => {
        setAttributes({ imageUrl: media.url });
    };

    const onChangeTestimonial = (value) => {
        setAttributes({ testimonial: value });
    };

    const onChangeName = (value) => {
        setAttributes({ name: value });
    };

    const onChangePosition = (value) => {
        setAttributes({ position: value });
    };

    return (
        <div {...useBlockProps()}>
            <div className="testimonial-block">
                <div className="testimonial-inner">
                    <div className="testimonial-content">
                        <div className="testimonial-image-wrapper">
                            <div className="testimonial-image-container">
                                {imageUrl ? (
                                    <img
                                        className="testimonial-image"
                                        src={imageUrl}
                                        alt={__('Testimonial image', 'testimonial')}
                                    />
                                ) : (
                                    <div className="testimonial-image-placeholder">
                                        <MediaUploadCheck>
                                            <MediaUpload
                                                onSelect={onSelectImage}
                                                allowedTypes={['image']}
                                                render={({ open }) => (
                                                    <Button onClick={open} className="button button-large">
                                                        {__('Upload Image', 'testimonial')}
                                                    </Button>
                                                )}
                                            />
                                        </MediaUploadCheck>
                                    </div>
                                )}
                                {imageUrl && (
                                    <MediaUploadCheck>
                                        <MediaUpload
                                            onSelect={onSelectImage}
                                            allowedTypes={['image']}
                                            value={imageUrl}
                                            render={({ open }) => (
                                                <Button onClick={open} className="button button-large">
                                                    {__('Change Image', 'testimonial')}
                                                </Button>
                                            )}
                                        />
                                    </MediaUploadCheck>
                                )}
                            </div>
                        </div>
                        <div className="testimonial-text-container">
                            <figure className="testimonial-figure">
                                <blockquote className="testimonial-quote">
                                    <RichText
                                        tagName="p"
                                        value={testimonial}
                                        onChange={onChangeTestimonial}
                                        placeholder={__('Testimonial text...', 'testimonial')}
                                    />
                                </blockquote>
                                <figcaption className="testimonial-caption">
                                    <div className="testimonial-name">
                                        <RichText
                                            tagName="div"
                                            value={name}
                                            onChange={onChangeName}
                                            placeholder={__('Name', 'testimonial')}
                                        />
                                    </div>
                                    <div className="testimonial-position">
                                        <RichText
                                            tagName="div"
                                            value={position}
                                            onChange={onChangePosition}
                                            placeholder={__('Position', 'testimonial')}
                                        />
                                    </div>
                                </figcaption>
                            </figure>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    );
}

保存.tsx:

import { useBlockProps, RichText } from '@wordpress/block-editor';
import React from 'react';

export default function save({ attributes }) {
    const { imageUrl, testimonial, name, position } = attributes;

    return (
        <div {...useBlockProps.save()}>
            <div className="testimonial-block">
                <div className="testimonial-inner">
                    <div className="testimonial-content">
                        <div className="testimonial-image-wrapper">
                            <div className="testimonial-image-container">
                                <img
                                    className="testimonial-image"
                                    src={imageUrl || ''}
                                    alt=""
                                />
                            </div>
                        </div>
                        <div className="testimonial-text-container">
                            <figure className="testimonial-figure">
                                <blockquote className="testimonial-quote">
                                    <RichText.Content tagName="p" value={testimonial} />
                                </blockquote>
                                <figcaption className="testimonial-caption">
                                    <div className="testimonial-name">
                                        <RichText.Content tagName="div" value={name} />
                                    </div>
                                    <div className="testimonial-position">
                                        <RichText.Content tagName="div" value={position} />
                                    </div>
                                </figcaption>
                            </figure>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    );
}

错误描述:

  • 在初始创建时,该块按预期工作。
  • 尝试编辑块时,块验证失败并且所有保存的属性都丢失。
  • 该错误表示属性不匹配,特别是图像的
    class
    属性。

采取的步骤:

  1. 确保属性在
    block.json
    中正确定义。
  2. 验证
    save
    函数输出的HTML结构与存储的内容是否匹配。
  3. 添加了日志记录以检查属性,以确认重新编辑期间属性丢失。

问题:

如何解决此块验证错误并确保属性在重新编辑时正确保留和匹配?任何见解或建议表示赞赏。

php wordpress wordpress-gutenberg gutenberg-blocks
1个回答
0
投票

该问题是由

block.json
name
position
的属性选择器与保存的内容不匹配引起的。

如果您在浏览器控制台中查看块触发的错误,您可以将原因缩小到不匹配的额外包装器 div:

通过save函数生成的内容:

...
    <div class="testimonial-name">
        <div>
            <div>John Doe</div>
        </div>
    </div>
    <div class="testimonial-position">
        <div>
            <div>Manager</div>
        </div>
    </div>
...

从帖子正文检索的内容:

...
    <div class="testimonial-name">
        <div>John Doe</div>
    </div>
    <div class="testimonial-position">
        <div>Manager</div>
    </div>
...

解决方案:

更新

block.json
中的选择器以匹配 save() 函数生成的 div 结构:

...
        "name": {
            "type": "string",
            "source": "html",
            "selector": ".testimonial-name div",
        },
        "position": {
            "type": "string",
            "source": "html",
            "selector": ".testimonial-position div",
        }
...

注意:区别是

"div.className"
应该是
".className div"
来选择内部div包装器的html内容。

© www.soinside.com 2019 - 2024. All rights reserved.