WordPress registerBlockType自定义块保存后预览数据未拉取问题
问题根本原因
古腾堡块的save方法最终输出的是静态HTML内容,不会在前端预览/公开页面中运行React组件的生命周期逻辑,你在save中引入的<PnImage/>组件只会在保存时执行一次静态渲染,此时没有运行componentDidMount、componentDidUpdate的环境,也拿不到pnRest的运行时对象,自然无法拉取图片数据,只能渲染出加载失败的提示文本。
最优解决方案:将图片数据存入块属性,保存时直接输出静态标签
这个方案的优势是前端页面加载更快、SEO友好,不需要额外加载前端脚本。
第一步:扩展块的属性配置
在registerBlockType的attributes中新增图片相关存储字段:
attributes: { pid: { type: "number", default: 8 }, // 新增图片存储字段 imageUrl: { type: "string", default: "" }, imageAlt: { type: "string", default: "" } },
第二步:修改edit逻辑,拉取到图片后同步存入属性
修改edit方法,给<PnImage/>添加数据回调,拉取到图片数据后存入块属性:
edit: ( {attributes, setAttributes} ) => { console.log( "Edit", attributes ) return ( <p { ...useBlockProps() }> {"Editoor " + attributes.pid} <PnImage pid={attributes.pid} // 新增回调,拉取到数据后存入属性 onImageFetched={(imageData) => { setAttributes({ imageUrl: imageData.URL, imageAlt: imageData.alt || `图片-${attributes.pid}` }) }} /> <NumberControl label="PID" isShiftStepEnabled={ true } onChange={ value => { setAttributes( {pid: value})} } shiftStep={ 10 } value={ attributes.pid } /> </p> ) },
第三步:修改PnImage组件,拉取到数据后触发回调
在PnImage的Fetch方法中,拿到返回数据后调用传入的回调:
Fetch() { // fetch wrapper if (this.props.pid != this.state.pid && this.props.pid ) { console.log( "fetching: pid=", this.props.pid ) pnRest.Fetch('image/get', { pid: this.props.pid, size: this.props.size }) .then(data => { if ( data ) { // image not found returns undefined this.setState({ image: data, pid: data.id }) // 触发回调传递数据 this.props.onImageFetched?.(data) } else { console.log( "Couldn't find image for pid " + this.props.pid ) } }); } }
第四步:重写save方法,直接输出静态图片标签
不要在save中使用<PnImage/>组件,直接用已经存储的图片属性输出静态HTML:
save: ({ attributes }) => { return ( <p { ...useBlockProps.save() }> { "Saved " + attributes.pid} {attributes.imageUrl && <img src={attributes.imageUrl} alt={attributes.imageAlt} />} </p> ) }
可选方案:前端动态渲染(仅适合需要实时更新图片的场景)
如果你确实需要前端页面每次加载时都实时拉取最新的图片数据,你需要额外做以下操作:
- 将
PnImage组件的代码打包为独立的前端JS脚本,在公开页面/预览页中入队加载 - 给save方法输出的图片占位标签添加自定义标识,比如
data-pid={attributes.pid}的自定义属性 - 前端脚本加载完成后,遍历页面上的自定义标识标签,初始化
PnImage组件替换占位标签即可。
内容的提问来源于stack exchange,提问作者Kim Aldis
相关产品推荐
相关产品推荐

