我正在开发一个动态块,它使用ServerSideRender
组件:
<div class="accordion">
<h3 class="accordion-title">A title</h3>
<div class="accordion-content">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</div>
</div>
要完全使用此块,需要
Accordion
来自jQuery UI的组件:
accordion-jquery-start.js
文件:
( function( $ ) {
$( function() {
$( \'.accordion\' ).accordion( {
header: \'h3\',
heightStyle: \'content\',
animate: 100,
collapsible: true,
active: false
} );
} );
} )( jQuery );
我正在使用以下方式注册动态块:
register_block_type( \'my/accordion-block\', array(
\'style\' => \'accordion-block-css\',
\'editor_script\' => \'accordion-block-js\',
\'render_callback\' => \'render_block\',
);
要在块编辑器中加载上面显示的其他脚本,我使用
enqueue_block_editor_assets
措施:
function my_enqueue_block_editor_assets() {
wp_enqueue_script( \'accordion-jquery-start\', plugins_url( \'/assets/js/accordion-jquery-start.js\', __FILE__ ), array( \'jquery\', \'jquery-ui-accordion\', \'accordion-block-js\' ), false, true );
}
add_action( \'enqueue_block_editor_assets\', \'my_enqueue_block_editor_assets\' );
几乎所有的工作都正常:块被注册并打印正确的标记,所有需要的脚本和样式都被排队。但是,出于某种原因
accordion
jQuery UI中的函数未附加到
.accordion
类,因此手风琴效果不起作用。但是,任何地方都没有控制台错误。看来
accordion-jquery-start.js
脚本在块本身完全加载之前运行。
有什么想法吗?我应该加载accordion-jquery-start.js
脚本是否不同?
SO网友:Sally CJ
但是,出于某种原因accordion
jQuery UI中的函数未附加到.accordion
类,因此手风琴效果不起作用。
这个ServerSideRender
组件使用RESTAPI获取动态块输出,因此出现上述问题,因为在DOM准备就绪时(即jQuery.ready()
\'s回调运行),REST API AJAX调用尚未解析或甚至可能尚未启动,因此accordion div尚未连接到DOM。
我应该加载accordion-jquery-start.js
脚本是否不同?
是的,有点-ServerSideRender
(尚未)提供;“加载内容时”;或“或”;关于AJAX完成/解决”;事件,因此您需要手动检查您的div是否已经在DOM中,如果已经在DOM中,请运行$( \'.accordion\' ).accordion()
.
在JS的现代世界中,一种简单的方法是使用MutationObserver
API.
请查看MDN web文档(请参见上面的链接),以了解有关突变观察者API的更多详细信息,但对于Gutenberg或块编辑器以及动态块,这里有一个可以尝试学习的工作示例。:-)
所以在我的index.js
文件,我得到了这些:console.log()
只是为了调试的目的,所以以后不要忘记删除它们)
加载WordPress依赖项:
import { registerBlockType } from \'@wordpress/blocks\';
import { useRef, useLayoutEffect } from \'@wordpress/element\';
import { useBlockProps } from \'@wordpress/block-editor\';
import ServerSideRender from \'@wordpress/server-side-render\';
MutationObserver
回调:// This function checks if the accordion div has been attached to the DOM, and
// if so, initializes jQuery accordion on that very div. So this function can be
// placed at the top in your file (before you call registerBlockType()).
function initAccordion( mutations ) {
for ( let mutation of mutations ) {
if ( \'childList\' === mutation.type && mutation.addedNodes[0] &&
// Good, the added node has an accordion div.
jQuery( \'.accordion\', mutation.addedNodes[0] ).length >= 1
) {
// Convert the div to a jQuery accordion.
jQuery( mutation.addedNodes[0] ).accordion( {
header: \'h3\',
heightStyle: \'content\',
animate: 100,
collapsible: true,
active: false
} );
console.log( \'accordion initialized\' );
}
}
}
现在这是我的方块类型:registerBlockType( \'my/accordion-block\', {
apiVersion: 2,
title: \'My Accordion Block\',
category: \'widgets\',
edit() {
// Create a ref for the block container.
const ref = useRef( null );
// Initialize the mutation observer once the block is rendered.
useLayoutEffect( () => {
let observer;
if ( ref.current ) {
observer = new MutationObserver( initAccordion );
// Observe DOM changes in our block container only.
observer.observe( ref.current, {
childList: true,
subtree: true,
} );
}
// Cleanup function which stops the mutation observer.
return () => {
if ( observer ) {
observer.disconnect();
console.log( \'observer disconnected\' );
}
};
}, [] );
// Pass the ref to the block container.
// Note: { ref } is short for { ref: ref }
const blockProps = useBlockProps( { ref } );
return (
<div { ...blockProps }>
<ServerSideRender block="my/accordion-block" />
</div>
);
}
} );