You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AEM6.5单页加载多Swagger-UI组件仅渲染一个的问题

多Swagger-UI组件在AEM6.5页面渲染失败的问题与解决

问题场景

在AEM6.5的单个页面中加载多个Swagger-UI组件时,页面仅能渲染一个组件,其余组件已正确加载到DOM但无法显示。即便每个组件使用了唯一ID,仍只有最后一个组件能正常渲染。

原组件模板代码

<sly data-sly-use.model="xxx.aem.component.content.SwaggerModel"
     data-sly-use.template="core/wcm/components/commons/v1/templates.html"
     data-sly-use.clientlib="/libs/granite/sightly/templates/clientlib.html">
</sly>

<sly data-sly-call="${clientlib.all @ categories='xxx.ui.swagger-ui'}"/>

<sly data-sly-call="${template.placeholder @ isEmpty=!model.defined}"></sly>

<div data-sly-test="${model.defined}">
    <h1 class="t-title">
        ${model.title}
    </h1>
    <div id="${model.uniqueId}"></div>
    <sly data-sly-test="${model.defined}" data-sly-call="${swaggerScript @ path=model.swaggerYamlPath, name=model.swaggerYamlName, dom_id=model.uniqueId}"></sly>

</div>
<template data-sly-template.swaggerScript="${ @ path, name, dom_id}">
    <script>
        window.onload = function () {

            window.ui = SwaggerUIBundle({
                urls: [
                    {url: "${path @ context='text'}", name: "${name @ context='text'}"},
                ],
                dom_id: '#${dom_id @ context='text'}',
                deepLinking: true,
                filter: true,
                presets: [
                    SwaggerUIBundle.presets.apis,
                    SwaggerUIStandalonePreset
                ],
                plugins: [
                    SwaggerUIBundle.plugins.DownloadUrl
                ],
                layout: 'StandaloneLayout'
            });

        };
    </script>
</template>

页面DOM示例(问题表现)

<div class="swagger">
    
    
    
        
    <link rel="stylesheet" href="/etc.clientlibs/xxx/clientlibs/static/swagger-ui.min.css" type="text/css">
    <script src="/etc.clientlibs/xxx/clientlibs/static/swagger-ui.min.js"></script>
    
    
    
    
    
        
    
    <div>
        <h1 class="t-title">
            Here goes the optional title for the Swagger component
        </h1>
        <div id="swagger-ui-1671020283"></div>
        
        <script>
            window.onload = function () {
    
                window.ui = SwaggerUIBundle({
                    urls: [
                        {url: "/content/dam/yaml-files/account-information-service-api-v2-of-fi.yaml", name: "account-information-service-api-v2-of-fi"},
                    ],
                    dom_id: '#swagger-ui-1671020283',
                    deepLinking: true,
                    filter: true,
                    presets: [
                        SwaggerUIBundle.presets.apis,
                        SwaggerUIStandalonePreset
                    ],
                    plugins: [
                        SwaggerUIBundle.plugins.DownloadUrl
                    ],
                    layout: 'StandaloneLayout'
                });
    
            };
        </script>
    
    
    </div>
    </div>
   
        
            
<div class="swagger">
    
    
    
        
    
    
    
    
    
        
    
    <div>
        <h1 class="t-title">
            
        </h1>
        <div id="swagger-ui-1110306185"></div>
        
        <script>
            window.onload = function () {
    
                window.ui = SwaggerUIBundle({
                    urls: [
                        {url: "/content/dam/yaml-files/consent-flow-api-v2-of-fi.yaml", name: "consent-flow-api-v2-of-fi"},
                    ],
                    dom_id: '#swagger-ui-1110306185',
                    deepLinking: true,
                    filter: true,
                    presets: [
                        SwaggerUIBundle.presets.apis,
                        SwaggerUIStandalonePreset
                    ],
                    plugins: [
                        SwaggerUIBundle.plugins.DownloadUrl
                    ],
                    layout: 'StandaloneLayout'
                });
    
            };
        </script>
    
    
    </div>

</div>

问题原因与解决方案

核心问题

  1. window.onload被覆盖:每个组件的脚本都直接赋值window.onload,而这个事件只能绑定一个回调,后面的赋值会完全覆盖前面的,导致只有最后一个组件的初始化逻辑执行。
  2. ClientLib重复加载:每个组件都调用clientlib.all,导致Swagger的CSS和JS被重复引入,可能引发资源冲突。
  3. 全局变量污染:window.ui被重复赋值,会覆盖之前的Swagger实例引用,同时可能干扰实例正常运行。

修复步骤

1. 移除组件内的ClientLib调用

将<sly data-sly-call="${clientlib.all @ categories='xxx.ui.swagger-ui'}"/>移到页面级模板(比如页面的head或footer区域),确保Swagger资源只加载一次。

2. 替换window.onload为事件监听

使用window.addEventListener('load', ...)代替直接赋值,这样多个回调会被依次执行,不会互相覆盖。

3. 避免全局变量冲突

不要将Swagger实例赋值给全局的window.ui,改用局部变量存储;如果需要全局访问所有实例,可以存入一个全局数组。

修复后的组件模板代码

<sly data-sly-use.model="xxx.aem.component.content.SwaggerModel"
     data-sly-use.template="core/wcm/components/commons/v1/templates.html">
</sly>

<sly data-sly-call="${template.placeholder @ isEmpty=!model.defined}"></sly>

<div data-sly-test="${model.defined}">
    <h1 class="t-title">
        ${model.title}
    </h1>
    <div id="${model.uniqueId}"></div>
    <sly data-sly-test="${model.defined}" data-sly-call="${swaggerScript @ path=model.swaggerYamlPath, name=model.swaggerYamlName, dom_id=model.uniqueId}"></sly>
</div>

<template data-sly-template.swaggerScript="${ @ path, name, dom_id}">
    <script>
        // 使用addEventListener保证多个回调都能执行
        window.addEventListener('load', function () {
            // 局部变量存储实例,不污染全局作用域
            const swaggerInstance = SwaggerUIBundle({
                urls: [
                    {url: "${path @ context='text'}", name: "${name @ context='text'}"},
                ],
                dom_id: '#${dom_id @ context='text'}',
                deepLinking: true,
                filter: true,
                presets: [
                    SwaggerUIBundle.presets.apis,
                    SwaggerUIStandalonePreset
                ],
                plugins: [
                    SwaggerUIBundle.plugins.DownloadUrl
                ],
                layout: 'StandaloneLayout'
            });

            // 可选:全局存储所有实例,方便后续操作
            if (!window.swaggerInstances) {
                window.swaggerInstances = [];
            }
            window.swaggerInstances.push(swaggerInstance);
        });
    </script>
</template>

额外优化建议

  • 确认使用的Swagger-UI版本支持多实例渲染(官方标准版本支持该特性)
  • 可将Swagger初始化逻辑封装为全局函数,组件仅传递参数调用,提升代码可维护性

内容的提问来源于stack exchange,提问作者scura s

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 02:45:31