如何用GrapesJS Block Manager实现双标签页滑块面板(各含独立区块)
GrapesJS双标签页区块面板解决方案
核心结论
将.myblocks类应用到两个互斥显示的div不可行。因为GrapesJS的Block Manager在初始化阶段只会绑定第一个匹配该类的元素,切换标签页后新渲染的.myblocks容器不会被自动识别,导致第二个标签页无法加载区块。
推荐方案:使用GrapesJS原生Panel系统构建标签页
GrapesJS内置了面板和命令系统,更适合实现这类标签切换需求,无需依赖DOM显隐逻辑:
1. 初始化配置自定义标签面板
修改GrapesJS初始化代码,添加自定义标签页面板:
const editor = grapesjs.init({ container: containerId, fromElement: true, height: height, width: width, styleManager: { clearProperties: true }, storageManager: false, panels: disablePanel ? { defaults: [] } : { defaults: [ { id: 'block-tabs', el: '.block-tabs-container', buttons: [ { id: 'tab-standard', active: true, label: '标准控件', command: 'show-standard-blocks', }, { id: 'tab-custom', label: '自定义控件', command: 'show-custom-blocks', }, ], }, ], }, blockManager: { appendTo: '.myblocks', blocks: [], // 初始不加载任何区块 }, });
2. 注册标签切换命令
分别注册两个命令,用于加载对应标签页的区块:
// 定义标准区块数据 const standardBlocks = [ { id: 'basic-section', label: '基础区块', content: '<section style="padding:20px;"></section>' }, // 补充更多标准控件... ]; // 定义自定义区块数据 const customBlocks = [ { id: 'custom-button', label: '自定义按钮', content: '<button class="custom-btn" style="background:#2196F3;color:white;padding:8px 16px;"></button>' }, // 补充更多自定义控件... ]; // 注册显示标准区块的命令 editor.Commands.add('show-standard-blocks', { run(editor) { // 清空现有所有区块 editor.BlockManager.getAll().forEach(block => block.remove()); // 添加标准区块集合 standardBlocks.forEach(block => editor.BlockManager.add(block.id, block)); // 更新标签激活状态 editor.Panels.getButton('block-tabs', 'tab-standard').set('active', true); editor.Panels.getButton('block-tabs', 'tab-custom').set('active', false); } }); // 注册显示自定义区块的命令 editor.Commands.add('show-custom-blocks', { run(editor) { editor.BlockManager.getAll().forEach(block => block.remove()); customBlocks.forEach(block => editor.BlockManager.add(block.id, block)); editor.Panels.getButton('block-tabs', 'tab-standard').set('active', false); editor.Panels.getButton('block-tabs', 'tab-custom').set('active', true); } });
3. 调整页面DOM结构
替换原有标签页DOM,只保留面板容器和区块容器:
<div class="block-tabs-container"></div> <div class="myblocks"></div>
备选方案:手动重新绑定DOM(不推荐)
如果必须保留原有DOM显隐逻辑,需要在标签切换后手动触发Block Manager的容器重新绑定:
// 调整showhide方法 showhide() { this.value = !this.value; // 等待DOM更新完成后执行 setTimeout(() => { const targetContainer = document.querySelector('.myblocks'); if (targetContainer && editor) { // 重置Block Manager的目标容器 editor.BlockManager.set('appendTo', targetContainer); // 根据当前标签加载对应区块 editor.BlockManager.getAll().forEach(block => block.remove()); if (this.value) { standardBlocks.forEach(block => editor.BlockManager.add(block.id, block)); } else { customBlocks.forEach(block => editor.BlockManager.add(block.id, block)); } } }, 0); }
这种方式需要处理DOM更新的异步时机,容易出现兼容性问题,稳定性不如原生面板方案。
内容的提问来源于stack exchange,提问作者chetan s
相关产品推荐
相关产品推荐

