【发布时间】:2023-03-11 12:28:01
【问题描述】:
我有一个脚本标签 (type="module"),它由 PHP 根据一些参数动态填充 import 语句。填充过程由站点的授权系统控制,它可以从脚本中删除一些imports,这取决于当前用户的权限。
页面上最终呈现的脚本标签示例:
<script type="module">
import ui from 'path_to_ui_module';
import read from 'path_to_read_module';
import edit from 'path_to_edit_module'; // Could be omitted by the authorization
import create from 'path_to_create_module'; // Could be omitted by the authorization
import delete from 'path_to_delete_module'; // Could be omitted by the authorization
ui.init();
</script>
保证所有的导入都只是对象。
现在,问题出在ui.init 方法中,我想将已加载模块(及其子模块)的某些属性的一些引用分配给ui 中的属性,但我不知道,哪些模块实际加载,因为授权系统可能已经从脚本中删除了一些模块。例如,所有加载的模块都有一个包含各种方法的cmd 对象,我想将这些方法的引用分配给ui.cmd 对象。如何遍历导入模块的所有命名空间,包括脚本中加载的模块可能导入的子模块?
目前我已经修改了授权系统,创建了ui.init调用,它将真正加载的模块的引用传递给ui.init方法,但是子模块自然不包括在内。
ui.init({modules: {read: read, edit: edit, create: create, delete: delete});
(授权系统丢弃的模块不包含在modules对象中。)
使用传递的modules 对象,简化的ui.init 方法如下所示(cmets 中的“主模块”是ui,“子模块”是指通过参数传递的模块):
init (options) {
for (const module in options.modules) {
this[module] = options.modules[module]; // Add submodule reference to the main object
this[module].main = this; // Add main module reference to submodule
Object.assign(this.cmd, this[module].cmd); // Assign the cmd methods of the submodule to the main module's cmd object
this[module].init(); // Initialize the submodule
}
}
修改后的问题:是否有所有导入模块的本机“列表”,包括导入模块已导入的子模块,可用,我可以在for .. in 循环中使用它来代替options.modules?或者,有没有办法让子模块在加载后以某种方式“暴露”自己,以便它们可以创建加载模块的列表?
【问题讨论】:
-
现在,我最终在所有导入模块的本地代码中维护了一个已加载子模块的列表对象。导入模块的
init方法检查列表是否存在,并将列表作为属性分配给导入的对象。主模块的init方法检查子模块的列表,并以列表作为参数递归调用自身。这个解决方案的一个缺陷是,主模块本身不能包含列表。因此,我仍然对提供所有已加载模块列表的答案感兴趣,最好不要向子模块添加任何代码。