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

如何将ACF字段用作自定义Gutenberg块属性并保持数据自动更新?

核心解决思路

你当前的问题根源是把元数据作为静态属性固化到了Gutenberg块的存储内容(文章post_content字段)中,自然不会跟随ACF字段更新。对于不需要在块内编辑、需要跟随外部数据实时同步的内容,统一使用动态渲染块实现即可。

具体修改步骤

1. 修改PHP块注册逻辑

移除块注册时的固定属性传值,改用render_callback实时拉取ACF字段输出前端内容,同时将块设置为动态模式:

function registerBlocks() {
    wp_register_script(
        'domain/opening-paragraph-editor',
        asset('scripts/opening-paragraph.editor.js')->uri(),
        ['sage/vendor.js']
    );

    wp_register_style(
        'domain/opening-paragraph',
        asset('styles/opening-paragraph.css')->uri()
    );

    register_block_type(
        'domain/lead-project', [
            'api_version'     => 2,
            'editor_script'   => 'domain/opening-paragraph-editor',
            'editor_style'    => 'domain/opening-paragraph',
            'render_callback' => function($block_attributes, $content) {
                wp_enqueue_style('domain/opening-paragraph');
                // 实时拉取最新ACF值
                $post_id = get_the_ID();
                $projectClient = get_field('project_client', $post_id) ?: '';
                $projectDateStart = get_field('project_dates_start', $post_id);
                $projectDateEnd = get_field('project_dates_end', $post_id);
                $projectDate = $projectDateStart ? $projectDateStart . ($projectDateEnd ? ' – ' . $projectDateEnd : '') : '';
                $projectLocation = get_field('project_location', $post_id) ?: '';

                // 组装输出结构
                ob_start(); ?>
                <div class="wp-block-domain-lead-project">
                    <div class="wp-block-domain-lead-project__wrap">
                        <div class="wp-block-domain-lead-project__inner">
                            <?php echo $content; // 输出InnerBlocks存储的段落内容 ?>
                        </div>
                        <div class="wp-block-domain-lead-project__summary">
                            <p><?php echo esc_html($projectClient); ?></p>
                            <p><?php echo esc_html($projectDate); ?></p>
                            <p><?php echo esc_html($projectLocation); ?></p>
                        </div>
                    </div>
                </div>
                <?php return ob_get_clean();
            }
        ]
    );
}
add_action('init', 'registerBlocks');

2. 修改JS编辑器逻辑

移除元数据相关的属性定义,改为直接读取当前文章的元数据用于编辑器内预览,不需要将值存储到块属性中:

import React  from 'react';
import {__} from '@wordpress/i18n';
import {registerBlockType} from '@wordpress/blocks';
import {InnerBlocks, useBlockProps} from '@wordpress/block-editor';
import { useEntityProp } from '@wordpress/core-data';

const ALLOWED_BLOCKS = ['core/paragraph'];
const TEMPLATE = [
    ['core/paragraph', {
        className: 'lead'
    }],
    ['core/paragraph']
];

registerBlockType('domain/lead-project', {
    apiVersion: 2,
    title: __('Lead Project'),
    description: __('Opening lead paragraph with project meta block.'),
    icon: 'editor-paragraph',
    category: 'text',
    edit: () => {
        const blockProps = useBlockProps();
        // 直接读取当前文章的元数据
        const [meta] = useEntityProp('postType', 'project', 'meta');
        const projectClient = meta?.project_client || '';
        const projectDateStart = meta?.project_dates_start || '';
        const projectDateEnd = meta?.project_dates_end || '';
        const projectDate = projectDateStart ? `${projectDateStart}${projectDateEnd ? ' – ' + projectDateEnd : ''}` : '';
        const projectLocation = meta?.project_location || '';

        return (
            <div { ...blockProps }>
                <div className="wp-block-domain-lead-project__wrap">
                    <div className="wp-block-domain-lead-project__inner">
                        <InnerBlocks
                            allowedBlocks={ALLOWED_BLOCKS}
                            template={TEMPLATE}
                            templateLock="all"
                        />
                    </div>
                    <div className="wp-block-domain-lead-project__summary">
                        <p>{projectClient}</p>
                        <p>{projectDate}</p>
                        <p>{projectLocation}</p>
                    </div>
                </div>
            </div>
        );
    },
    // 仅存储可编辑的段落内容
    save: () => {
        return <InnerBlocks.Content />;
    }
});

3. 简化块模板定义

移除模板中的属性传值,避免版本不匹配提示:

function registerBlockTemplates() {
    $post_id = isset($_GET['post']) ? $_GET['post'] : null;

    if (get_post_type($post_id) == 'project') {
        $project_object   = get_post_type_object('project');
        $project_object->template = [
            ['domain/lead-project'],
            ['domain/inner-blocks']
        ];
        $project_object->template_lock = 'all';
    }
}
add_action('init', 'registerBlockTemplates', 999, 0);

方案优势

  • 前端和编辑器展示的元数据永远和ACF字段实时同步,不需要额外更新逻辑
  • 块存储内容只保留可编辑的段落内容,无冗余数据,不会出现模板不匹配提示
  • ACF字段的修改不需要同步更新块存储内容,完全解耦
  • 完全保留你需要的HTML结构自定义能力

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 12:09:00