Vaadin 14 Springboot JavaScript 不起作用。

3

我正在开发自己的第一个Vaadin 14应用程序,并使用Spring Boot框架。 我创建了一个名为teams.js的JavaScript文件,将其放置在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"),当页面加载时我会收到此错误:“> unexpected character”。 如果我试图在可完成的future上调用join()get(),则浏览器会冻结。 如果我使用@Javascript("frontend://src/teams.js"),则会出现一些CORS错误,就好像它正在尝试从“frontend”主机下载某些内容。 我已经尝试将@JsModule放在组件而不是我的视图上...它不起作用。 我已经尝试将我的js文件放到根目录和资源文件夹中。
我找不到其他导入js文件到vaadin14 with spring boot并使用它的解决方案。 而且,我不确定为什么在completable future上调用“join()”会冻结浏览器,即使我在浏览器日志中看到了控制台日志,sentToBrowser的结果也返回false...
请问有人能解释一下我应该如何进行javascript导入,为什么我的当前代码不起作用以及为什么“join()”会冻结浏览器吗?
提前感谢您的回答!
@Edit
我也尝试过使用这个注释@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() 一样,两者都可以正常工作。尽管下面的 Completable Future 仍然从未执行过,并且 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");那样,它找不到文件。

有人知道为什么CompletableFuture从未被执行吗?

1个回答

3
问题在于以下代码重新定义了 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(...) 进行定义。


4
最后一部分的澄清:在“常规”的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.jsresources/static/src/teams.js中,并尝试调用它作为window.initTeams()initTeams()...但是这些都没有起作用...我不确定在vaadin14的情况下哪一个是正确的,以及我做错了什么... - Viktor Korai

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接