Vaadin 14 Springboot javascript不起作用

Posted

技术标签:

【中文标题】Vaadin 14 Springboot javascript不起作用【英文标题】:Vaadin 14 Springboot javascript does not work 【发布时间】:2021-12-10 13:25:57 【问题描述】:

我正在尝试开发我的第一个 Vaadin 14 应用程序,我也在使用 Spring Boot 框架。 我创建了一个 javascript 文件,我将其放入名为 teams.js 的文件夹 frontend/src 中,并尝试使用 @JsModule("src/teams.js") 导入它。我的根视图类如下所示:

@Route("")
@PageTitle("Teams organization store init")
@Slf4j
@JsModule("src/teams.js")
@Tag("TeamsEntry")
public class TeamsEntryView extends VerticalLayout implements BeforeEnterObserver 

    public TeamsEntryView() 
        initTeams();
    

    private void initTeams() 
        var ui = UI.getCurrent();
        var page = ui.getPage();
        log.info("Teams initialization...");
        page.executeJs(getTeamsConfig()).toCompletableFuture().whenComplete(((jsonValue, throwable) ->
                log.info("Teams initialization completed:  with throwable ", jsonValue.toJson(), throwable.getMessage())
        ));

    

    private String getTeamsConfig() 
        return """
                console.log('ss');
                window.initTeams();
                console.log('xx');
                return true;
                """;
    
...

我的 js 文件如下所示:

window = 
    initTeams: function () 
        console.log('initTeams...');
    

在这种情况下,我在浏览器的控制台中看到“ss”,但仅此而已。 如果我删除window.initTeams(); 行,我也会得到“ss”和“xx”。 如果我在 js 文件中声明一个简单函数并在没有“window”类的情况下调用它,我会得到类似的结果。 如果我使用 @Javascriptpage.addJavascript("src/teams.js") 在页面加载时出现此错误:"> 意外字符" 如果我尝试在可完成的未来调用join()get(),浏览器会冻结。 如果我使用 @Javascript("frontend://src/teams.js") 我会收到一些 CORS 错误,例如它试图从“前端”主机下载某些东西。 我试图将@JsModule 放在一个组件上而不是我的视图上。它不起作用。 我尝试将我的 js 文件放到根目录和资源文件夹中。

我找不到任何其他解决方案来通过 Spring Boot 将我的 js 文件导入并使用到 vaadin14。 另外,如果我在可完成的未来调用“join()”,我不确定为什么浏览器会冻结,即使我在浏览器日志中看到控制台日志,sentToBrowser 的结果也会返回 false...

有人可以向我解释一下我应该如何进行 javascript 导入,为什么我当前的代码不起作用,以及为什么“join()”会冻结浏览器吗?

提前谢谢你!

@编辑

我也试过这个注解@JavaScript("./src/teams.js") 和这样的js:

    function initTeams ()   
        console.log('initTeams...');  
        console.log("Teams initialized!")  
    

@编辑

好的,我终于让它工作了。 js 文件必须在root/src/main/webapp/src 文件夹下。 @JavaScript@JsModule 也不适合我,所以我必须将我的 js 文件导入为:

        var ui = UI.getCurrent();
        var page = ui.getPage();
        page.addJavaScript("src/teams.js");

然后我可以将其称为window.initTeams()initTeams(),两者都可以正常工作。尽管下面可完成的未来仍然永远不会执行,isSentToBrowser() 总是返回 false。

page.executeJs(getTeamsConfig()).toCompletableFuture().whenComplete(((jsonValue, throwable) ->
                log.info("Teams initialization completed:  with throwable ", jsonValue.toJson(), throwable.getMessage())
        ));

如果我以 '.' 开始路径,我必须提及。像page.addJavaScript(".src/teams.js"); 这样就找不到文件了。

有人有答案吗,为什么可完成的未来永远不会执行?

【问题讨论】:

【参考方案1】:

问题是下面的代码重新定义了window对象:

window = 
    initTeams: function () 
        console.log('initTeams...');
    

您是否打算向window 对象添加一个函数?像这样:

window.initTeams = function () 
    console.log('initTeams...');
;

如果您想让代码在视觉上与您的代码相似:

window = 
    ...window,
    
        initTeams: function() 
            console.log('initTeams...');
        
    

其他选项:

window['initTeams'] = function() ...
Object.assign(window, initTeams: function() ...)
Object.defineProperty(window, 'initTeams', value: function() console.log('foo'));

一定喜欢 JavaScript...

此外,为了了解更多信息,您的@Edit 部分中提到的代码无法调用。调用initTeams() 等价于window.initTeams()。该函数必须存在于window 对象中。这就是为什么,例如,您会看到一些自定义元素,例如 customElements.define(...)window.customElements.define(...)

【讨论】:

最后一部分的说明。在“常规”JS 文件中,不合格的function 定义被添加到window。但是当 JS 文件作为 ES 模块加载时,情况并非如此。 @LeifÅstrand 谢谢。 我已将我的 js 文件内容更改为 window.initTeams = function () console.log('initTeams...'); ;并尝试像@JavaScript("./src/teams.js")@JsModule("./src/teams.js") 一样导入它我已将文件放入root/frontend/src/teams.jsresources/src/teams.js 以及resources/static/src/teams.js,我尝试将其调用为window.initTeams()initTeams().. .这些都不起作用...我不确定在vaadin14的情况下哪个是正确的,以及我做错了什么..

以上是关于Vaadin 14 Springboot javascript不起作用的主要内容,如果未能解决你的问题,请参考以下文章

在 Vaadin UI 上执行异步操作

如何使 Spring Boot 适配器中的 Keycloak 策略执行器与 vaadin 一起使用

春季启动的Vaadin登录问题

将 Vaadin/SpringBoot 部署为 WAR

如何在 Vaadin 14 中播放声音?

影子根的 Vaadin 14 登录表单 css 选择器