如何从Gutenberg子块更新父块属性?
问题:为Gutenberg Tab子块添加图标并同步到父块属性
我克隆了一款基础Tab块插件,现在要给每个Tab子块添加选择图标的功能。目前已经能通过MediaUpload组件选择文件,且能在activeTab对象中看到选中的文件,但无法更新父块的属性,导致在父块中引用icon_url时该属性不存在。
当前代码情况
tab/edit.js 代码
const Edit = ({ attributes, setAttributes, clientId }) => { const { uid, activeTab } = attributes; useEffect(() => { if (!uid) { setAttributes({ uid: clientId }); } }, []); const display = activeTab === uid ? "block" : "none"; const ALLOWED_MEDIA_TYPES = ["image", "svg"]; const setTabIcon = (icon_url) => { const parentBlock = select("core/block-editor").getBlock(clientId); dispatch("core/block-editor").updateBlockAttributes( parentBlock.clientId, { ...attributes, icon_url, } ); }; return ( <div {...useBlockProps()}> <InspectorControls> <div> <MediaUpload allowedTypes={ALLOWED_MEDIA_TYPES} onSelect={(media) => setTabIcon(media.url)} render={({ open }) => ( <button onClick={open}>Open Media Library</button> )} /> </div> </InspectorControls> <div className="guten-tab-panel" style={{ display }}> <InnerBlocks allowedBlocks={["core/heading", "core/paragraph"]} renderAppender={() => <InnerBlocks.ButtonBlockAppender />} /> </div> </div> ); }; export default Edit;
tabs/tabs.js 代码
const Edit = ({ attributes, setAttributes, clientId }) => { const { tabs, activeTab } = attributes; const blockProps = useBlockProps({ className: `${useBlockProps().className} guten-tab-wrapper`, }); const setActiveTab = (uid) => { setAttributes({ activeTab: uid }); const parentBlock = select("core/block-editor").getBlock(clientId); parentBlock.innerBlocks.forEach((innerBlock) => { dispatch("core/block-editor").updateBlockAttributes( innerBlock.clientId, { activeTab: uid, } ); }); }; const addNewTab = () => { const tab = createBlock("ahsan03/tab"); const position = tabs.length; dispatch("core/block-editor").insertBlock(tab, position, clientId); setAttributes({ tabs: [ ...tabs, { uid: tab.clientId, title: `Tab ${tabs.length + 1}`, icon_url: "", }, ], }); setActiveTab(tab.clientId); }; const tabTitleChange = (newValue) => { setAttributes({ tabs: [ ...tabs.map((tab) => { return tab.uid === activeTab ? { ...tab, title: newValue, } : tab; }), ], }); }; useEffect(() => { if (tabs.length && !activeTab) { setActiveTab(tabs[0].uid); } }, [tabs]); return ( <> <div {...blockProps}> <div className="guten-tabs-nav"> {tabs.map((tab) => { return ( <div key={tab.uid} className="guten-tab-item" role="tab" tabIndex="0" onClick={() => setActiveTab(tab.uid)} > <div className={`guten-tab-link${ tab.uid === activeTab ? " is-active" : "" }`} > <img src={tab.icon_url} alt="" /> {console.log("tabs tab", { tab, })} <RichText tagName="div" value={tab.title} onChange={tabTitleChange} /> </div> </div> ); })} <Button variant="primary" icon="plus" onClick={addNewTab} > {__("", "gtt")} </Button> </div> <div className="guten-tab-content"> <InnerBlocks allowedBlocks={["ahsan03/tab"]} renderAppender={false} /> </div> </div> </> ); }; export default Edit;
我尝试的setTabIcon函数
const setTabIcon = (icon_url) => { const parentBlockIds = select("core/block-editor").getBlockParents(clientId); parentBlockIds.forEach((parentBlockId) => { const parentBlock = select("core/block-editor").getBlock(parentBlockId); console.log({ parentBlock }); }); };
请问如何修改才能让上传的图片路径存入父块属性中?
解决方案
1. 修正Tab子块的setTabIcon函数
替换原来的setTabIcon函数,实现正确更新父块的tabs属性:
const setTabIcon = (icon_url) => { // 获取当前子块的直接父块ID const parentBlockIds = select("core/block-editor").getBlockParents(clientId); if (!parentBlockIds.length) return; const parentBlockId = parentBlockIds[0]; const parentBlock = select("core/block-editor").getBlock(parentBlockId); const { tabs: parentTabs } = parentBlock.attributes; // 遍历父块tabs数组,匹配当前子块的uid并更新icon_url const updatedTabs = parentTabs.map(tabItem => { if (tabItem.uid === uid) { return { ...tabItem, icon_url }; } return tabItem; }); // 更新父块的属性 dispatch("core/block-editor").updateBlockAttributes(parentBlockId, { tabs: updatedTabs }); // 可选:同步更新子块自身的icon_url属性,方便子块内部使用 setAttributes({ icon_url }); };
2. 确保Tab子块的属性定义包含icon_url
在Tab子块的block.json文件中,添加icon_url属性:
"attributes": { "uid": { "type": "string", "default": "" }, "activeTab": { "type": "string", "default": "" }, "icon_url": { "type": "string", "default": "" } }
3. 验证父块渲染逻辑
父块(tabs.js)中已经存在<img src={tab.icon_url} alt="" />的渲染代码,只要父块的tabs数组里的项正确更新了icon_url,就能正常显示图标。
内容的提问来源于stack exchange,提问作者user15396919
相关产品推荐
相关产品推荐

