Vue.js Frontend with a Spring Boot Backend – 带有Spring Boot后端的Vue.js前台

最后修改: 2018年 7月 27日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

In this tutorial, we’ll go over an example application that renders a single page with a Vue.js frontend, while using Spring Boot as a backend.

在本教程中,我们将讨论一个示例应用程序,它用Vue.js的前端渲染一个单页,同时使用Spring Boot作为后端。

We’ll also utilize Thymeleaf to pass information to the template.

我们还将利用Thymeleaf来向模板传递信息。

2. Spring Boot Setup

2.Spring Boot设置

The application pom.xml uses the spring-boot-starter-thymeleaf dependency for template rendering along with the usual spring-boot-starter-web:

应用程序pom.xml使用spring-boot-starter-thymeleaf依赖关系,与通常的spring-boot-starter-web一起进行模板渲染。

<dependency> 
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId> 
    <version>2.4.0</version>
</dependency> 
<dependency> 
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId> 
    <version>2.4.0</version>
</dependency>

Thymeleaf by default looks for view templates at templates/, we’ll add an empty index.html to src/main/resources/templates/index.html. We’ll update its contents in the next section.

Thymeleaf默认在templates/寻找视图模板,我们将在src/main/resources/templates/index.html中添加一个空的index.html。我们将在下一节中更新其内容。

Finally, our Spring Boot controller will be in src/main/java:

最后,我们的Spring Boot控制器将在src/main/java

@Controller
public class MainController {
    @GetMapping("/")
    public String index(Model model) {
        model.addAttribute("eventName", "FIFA 2018");
        return "index";
    }
}

This controller renders a single template with data passed to the view via the Spring Web Model object using model.addAttribute.

这个控制器渲染了一个单一的模板,数据通过Spring Web模型对象使用model.addAttribute传递给视图。

Let’s run the application using:

让我们用以下方法运行该应用程序。

mvn spring-boot:run

Browse to http://localhost:8080 to see the index page. It’ll be empty at this point, of course.

浏览到http://localhost:8080,查看索引页。当然,这时它将是空的。

Our goal is to make the page print out something like this:

我们的目标是使页面打印出这样的内容。

Name of Event: FIFA 2018

Lionel Messi
Argentina's superstar

Christiano Ronaldo
Portugal top-ranked player

3. Rendering Data Using a Vue.Js Component

3.使用Vue.Js组件渲染数据

3.1. Basic Setup of Template

3.1.模板的基本设置

In the template, let’s load Vue.js and Bootstrap (optional) to render the User Interface:

在模板中,让我们加载Vue.js和Bootstrap(可选)来渲染用户界面。

// in head tag

<!-- Include Bootstrap -->

//  other markup

// at end of body tag
<script 
  src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js">
</script>
<script 
  src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.21.1/babel.min.js">
</script>

Here we load Vue.js from a CDN, but you can host it too if that’s preferable.

这里我们从CDN加载Vue.js,但如果你喜欢的话,也可以托管它。

We load Babel in-browser so that we can write some ES6-compliant code in the page without having to run transpilation steps.

我们在浏览器中加载Babel,这样我们就可以在页面中写一些符合ES6标准的代码,而不需要运行转译步骤。

In a real-world application, you’ll likely use a build process using a tool such as Webpack and Babel transpiler, instead of using in-browser Babel.

在现实世界的应用中,你可能会使用Webpack和Babel转译器等工具的构建过程,而不是使用浏览器内的Babel。

Now let’s save the page and restart using the mvn spring-boot:run command. We refresh the browser to see our updates; nothing interesting yet.

现在让我们保存页面并使用mvn spring-boot:run命令重新启动。我们刷新浏览器以查看我们的更新;还没有什么有趣的东西。

Next, let’s set up an empty div element to which we’ll attach our User Interface:

接下来,让我们设置一个空的div元素,我们将把我们的用户界面附在上面。

<div id="contents"></div>

Next, we set up a Vue application on the page:

接下来,我们在页面上设置了一个Vue应用程序。

<script type="text/babel">
    var app = new Vue({
        el: '#contents'
    });
</script>

What just happened? This code creates a Vue application on the page. We attach it to the element with CSS selector #contents.

刚刚发生了什么?这段代码在页面上创建了一个Vue应用程序。我们用CSS选择器#contents将其附加到元素上。

That refers to the empty div element on the page. The application is now set up to use Vue.js!

这指的是页面上的空div元素。现在,该应用程序已被设置为使用Vue.js!

3.2. Displaying Data in the Template

3.2.显示模板中的数据

Next, let’s create a header which shows the ‘eventName‘ attribute we passed from Spring controller, and render it using Thymeleaf’s features:

接下来,让我们创建一个头,显示我们从Spring控制器传来的’eventName‘属性,并使用Thymeleaf的功能渲染它。

<div class="lead">
    <strong>Name of Event:>
    <span th:text="${eventName}"></span>
</div>

Now let’s attach a ‘data’ attribute to the Vue application to hold our array of player data, which is a simple JSON array.

现在让我们给Vue应用程序附加一个’data’属性,以保存我们的播放器数据数组,这是一个简单的JSON数组。

Our Vue app now looks like this:

我们的Vue应用程序现在看起来像这样。

<script type="text/babel">
    var app = new Vue({
        el: '#contents',
        data: {
            players: [
                { id: "1", 
                  name: "Lionel Messi", 
                  description: "Argentina's superstar" },
                { id: "2", 
                  name: "Christiano Ronaldo", 
                  description: "World #1-ranked player from Portugal" }
            ]
        }
    });
</script>

Now Vue.js knows about a data attribute called players.

现在Vue.js知道了一个叫做players的数据属性。

3.3. Rendering Data with a Vue.js Component

3.3.用Vue.js组件渲染数据

Next, let’s create a Vue.js component named player-card which renders just one player. Remember to register this component before creating the Vue app.

接下来,让我们创建一个名为player-card的Vue.js组件,只渲染一个player记得在创建Vue应用程序之前注册这个组件。

Otherwise, Vue won’t find it:

否则,Vue不会找到它。

Vue.component('player-card', {
    props: ['player'],
    template: `<div class="card">
        <div class="card-body">
            <h6 class="card-title">
                {{ player.name }}
            </h6>
            <p class="card-text">
                <div>
                    {{ player.description }}
                </div>
            </p>
        </div>
        </div>`
});

Finally, let’s loop over the set of players in the app object and render a player-card component for each player:

最后,让我们循环浏览应用程序对象中的玩家集合,为每个玩家渲染一个player-card组件。

<ul>
    <li style="list-style-type:none" v-for="player in players">
        <player-card
          v-bind:player="player" 
          v-bind:key="player.id">
        </player-card>
    </li>
</ul>

The logic here is the Vue directive called v-for, which will loop over each player in the players data attribute and render a player-card for each player entry inside a <li> element.

这里的逻辑是名为v-for,的Vue指令,它将循环处理players数据属性中的每个球员,并为player元素内的每个player条目渲染一个player-card

v-bind:player means that the player-card component will be given a property called player whose value will be the player loop variable currently being worked with. v-bind:key is required to make each <li> element unique.

v-bind:player意味着player-card组件将被赋予一个名为player的属性,其值将是当前正在处理的player循环变量。v-bind:key需要使每个<li>元素独一无二。

Generally, player.id is a good choice since it is already unique.

一般来说,player.id是一个不错的选择,因为它已经是唯一的。

Now if you reload this page, observe the generated HTML markup in devtools, and it will look similar to this:

现在,如果你重新加载这个页面,观察devtools中生成的HTML标记,它将看起来类似于这样。

<ul>
    <li style="list-style-type: none;">
        <div class="card">
            // contents
        </div>
    </li>
    <li style="list-style-type: none;">
        <div class="card">
            // contents
        </div>
    </li>
</ul>

A workflow improvement note: it’ll quickly become cumbersome to have to restart the application and refresh the browser each time you make a change to the code.

一个工作流程的改进说明:每次对代码进行修改都要重新启动应用程序并刷新浏览器,这将很快变得很麻烦。

Therefore, to make life easier, please refer to this article on how to use Spring Boot devtools and automatic restart.

因此,为了方便生活,请参考这篇文章,了解如何使用Spring Boot devtools和自动重新启动。

4. Conclusion

4.总结

In this quick article, we went over how to set up a web application using Spring Boot for backend and Vue.js for the frontend. This recipe can form the basis for more powerful and scalable applications, and this is just a starting point for most such applications.

在这篇快速文章中,我们介绍了如何在后台使用Spring Boot,在前端使用Vue.js来设置一个网络应用。这个配方可以构成更强大和可扩展的应用程序的基础,而这只是大多数此类应用程序的一个起点。

As usual, code samples can be found over on GitHub.

像往常一样,可以在GitHub上找到代码样本