如何检测Gutenberg块选中状态以控制AJAX调用?
解决Gutenberg块仅在选中时执行AJAX调用的问题
核心思路
利用Gutenberg内置的useSelect钩子获取块的选中状态,结合React的useEffect控制AJAX调用的触发时机,确保仅在块被选中且播放列表ID有效时执行getPlaylistMedia。
具体修改步骤
1. 引入必要的模块与钩子
在代码顶部添加React钩子和Gutenberg数据模块:
const { useSelect, useEffect, useState } = wp.element;
2. 修改Edit组件,实现选中状态判断
在edit函数中接收clientId参数(Gutenberg会自动传入),并通过useSelect判断当前块是否处于选中状态:
edit({ attributes, setAttributes, clientId }) { // 获取当前块的选中状态 const isSelected = useSelect( ( select ) => { const selectedBlockId = select('core/editor').getSelectedBlockClientId(); return selectedBlockId === clientId; }, [clientId]); // 用React状态维护媒体列表,替代直接操作DOM const [mediaOptions, setMediaOptions] = useState([{label:'Loading..', value:''}]); // 播放列表选择变更处理 function onChangePlaylistId(v) { setAttributes({ playlist_id: v }); } // 媒体项选择变更处理 function onChangeMediaId(v) { setAttributes({ media_id: v }); } // 仅在块选中且播放列表ID存在时触发AJAX useEffect(() => { if (isSelected && attributes.playlist_id) { getPlaylistMedia(attributes, setMediaOptions); } }, [isSelected, attributes.playlist_id]); // 保留原有渲染逻辑,仅替换媒体选择器的options return [ el( 'div', { className: 'test-block-container'}, el(IconBlock, {}), el("span", {}, "Test Player") ), el( wp.element.Fragment, {}, el( wp.blockEditor.InspectorControls, {}, el( wp.components.PanelBody, { title: 'Select source', initialOpen: true }, playlistArr.length == 1 ? el(Button, { href: "playlist_manager&action=add_playlist", className: "components-button is-button is-default is-large aptean-block-panel-button", text: __("Create new playlist") }) : el( wp.components.SelectControl, { label: 'Select playlist', value: attributes.playlist_id, options: playlistArr, onChange: onChangePlaylistId } ), el( wp.components.SelectControl, { label: 'Select media', value: attributes.media_id, options: mediaOptions, // 替换为状态管理的列表 onChange: onChangeMediaId, className: "test-media-id-select", } ), ), ), ), ] },
3. 重构getPlaylistMedia函数,通过状态更新DOM
移除直接操作DOM的逻辑,改为通过React状态更新媒体选择器:
function getPlaylistMedia(atts, setMediaOptions){ var postData = [ {name: 'action', value: 'test_get_media'}, {name: 'playlist_id', value: atts.playlist_id} ]; if(ajaxForMedia){ ajaxForMedia.abort() ajaxForMedia = null; } ajaxForMedia = $.ajax({ url: test_block_data.ajax_url, type: 'post', data: postData, dataType: 'json', }).done(function(response){ // 转换为SelectControl所需的格式 const options = [{label:'None', value:''}].concat( response.map(obj => ({ label: `${obj.title} - ID #${obj.id}`, value: obj.id })) ); setMediaOptions(options); }).fail(function(jqXHR, textStatus, errorThrown) { console.log(jqXHR.responseText, textStatus, errorThrown); }); }
关键说明
useSelect:从Gutenberg的core/editor数据仓库中获取当前选中的块ID,与当前块的clientId对比,得到准确的选中状态。useEffect:将依赖设置为isSelected和attributes.playlist_id,仅当块选中且播放列表ID变化时才触发AJAX,彻底避免取消选中时的无效请求。- 状态管理替代DOM操作:符合Gutenberg的React架构,避免直接操作DOM导致的状态不一致问题。
内容的提问来源于stack exchange,提问作者Toniq
相关产品推荐
相关产品推荐

