Moodle课程区块JS代码兼容问题:分页章节及Tiles格式故障
解决Moodle区块在Tiles课程格式JS导航下的DOM插入问题
问题背景
我开发的Moodle课程区块核心功能是统计学生查看活动的次数,目前存在两个问题:
- 分页式章节结构下,JS代码仅在单个页面生效(已解决)
- Tiles课程格式启用JavaScript导航时,代码无法正常执行(未解决)
最初实现代码:
$code = 'document.getElementById("module-'.$cmid.'") .insertAdjacentHTML("beforeend", "' . addslashes_js($blockdata->viewstemplate) . '");'; $this->page->requires->js_amd_inline ($code); // $this->page->requires->js_init_code($code , true);
修改后解决分页问题,但Tiles格式仍失效的代码:
$code = 'require(["jquery", "core/ajax"], function($, ajax) { $(document).ready(function() { var module = $("#module-'.$cmid.'"); module.append("'.addslashes_js($blockdata->viewstemplate).'"); }); });'; $this->page->requires->js_init_code($code , true);
问题原因
Tiles课程格式启用JS导航后,页面内容是异步加载的,$(document).ready仅在初始页面渲染完成时触发一次,后续通过JS导航加载的新模块不会触发该事件,导致插入模板的逻辑无法执行。
解决方案
使用Moodle内置的core/event/contentloaded事件,该事件会在任何异步加载内容完成后触发(包括Tiles格式的JS导航切换)。将插入逻辑封装为可复用函数,在初始加载和事件触发时都执行:
$code = 'require(["jquery", "core/event_dispatcher"], function($, EventDispatcher) { // 封装插入模板的复用函数 function insertViewCountTemplate() { var module = $("#module-'.$cmid.'"); // 检查是否已插入,避免重复添加(替换为你模板中的实际类名) if (module.find(".view-count-container").length === 0) { module.append("'.addslashes_js($blockdata->viewstemplate).'"); } } // 初始页面加载时执行 $(document).ready(insertViewCountTemplate); // 监听异步内容加载事件,适配Tiles导航场景 EventDispatcher.addEventListener("core/event/contentloaded", insertViewCountTemplate); });'; $this->page->requires->js_init_code($code, true);
关键细节
- 重复插入检查:由于
contentloaded事件可能多次触发,添加判断逻辑避免模板元素重复插入,需将.view-count-container替换为你模板中实际的容器类名。 - 依赖
core/event_dispatcher:这是Moodle官方提供的AMD事件监听模块,能可靠捕获所有异步内容加载完成的事件。 - 通用适配性:该方案不仅解决Tiles格式的问题,还能兼容其他使用Moodle异步加载机制的课程格式或插件。
额外建议
如果统计逻辑需要在模块被实际查看时触发(而非仅DOM插入),可以在模板插入后,给模块绑定可见性监听,或利用Moodle的core/log模块记录查看事件,确保统计数据的准确性。
内容的提问来源于stack exchange,提问作者Mohammad Farouk
相关产品推荐
相关产品推荐

