Ubuntu 20.04使用Nginx部署Vuetify应用完整教程

这是文章《如何在Ubuntu 20.04上使用Nginx发布一个Vuetify应用程序》的第1部分(共18部分)。

作为”为捐赠而写”计划的一部分,作者选择了多元技术基金作为接受捐赠的机构。

简介

组件是现代前端开发的一个重要特性。一个组件通常包括两个部分的代码:

  • 组件的逻辑:组件可以实现的功能。
  • 模板:用户如何与Web应用程序交互的方式。

将你的应用程序组织成组件有助于编写现代、稳健的网页应用。JavaScript框架,如React和Vue.js,可以帮助你开发多种类型的组件,并被开发人员广泛使用。

然而,这些框架的一个痛点是你需要创建许多组件,即使是像输入文本字段这样简单的东西。因此,更加简化的方法是使用一个组件库,它里面有预制的组件可以根据需要选择和使用。通过使用组件库,你无需担心CSS设计、颜色、大小和字体,可以专注于功能。

对于Vue.js,有一个基于Material Design原则的Vue UI库叫做Vuetify。Vuetify非常可配置和可自定义。您可以修改组件以满足自己的需求,并且可以设置自己的主题来创建一个基于自己品牌风格的一致组件库。

在这个教程中,你将基于Vuetify创建一个待办事项应用,并使用Nginx作为反向代理将其发布。这是部署Vue应用所必需的。

注意:由于Vue是一个前端框架,你在本教程中创建的应用将在浏览器中运行。然而,如果需要额外的功能,例如身份验证或数据持久化,你将需要一个后端。定义或开发这个后端功能超出了本文的范围。

先决条件

要按照这个教程,你需要以下物品:

  • 一台装有sudo非root用户的Ubuntu 20.04服务器。要开始,请遵循我们的Ubuntu 20.04初始服务器设置指南。在本教程中,非root用户是sammy。
  • 已安装Nginx,你可以按照《如何在Ubuntu 20.04上安装Nginx》教程的步骤1-3进行操作。
  • 一个完全注册的域名。本教程将全程使用your_domain。你可以在Namecheap上购买域名,在Freenom上免费获取一个,或者使用你选择的域名注册商。
  • 已安装Node.js(至少v14.0.0),你可以按照针对你的操作系统的《如何安装Node.js和创建本地开发环境》教程进行操作。
  • 熟悉Vue.js,你可以在Vue快速入门指南和我们的系列文章《如何使用Vue.js开发网站》中找到相关内容。

第一步 – 设置您的Vue应用程序

在这一步中,您将配置您的Vue.js应用程序。Vue.js有一个客户端,您可以使用它来创建项目的样板,这是一个从零开始的好方法。

你可以使用以下命令全局安装Vue.js客户端来开始操作:

sudo npm install -g @vue/cli

接下来,验证版本:

vue --version

在写这篇教程时,最新版本是5.0.8。

输出

@vue/cli 5.0.8

现在你已经安装了@vue/cli,可以用它来创建vuejs的应用程序。在这个教程中,该应用程序将被称为vuetify-meets-nginx-app,但你可以将其名称更改为任何你喜欢的名字。

要创建这个应用程序,请运行以下命令:

vue create vuetify-meets-nginx-app

这个命令是交互式的,并且有多个选项。对于这个教程,选择Vue 2的默认选项。

输出

Vue CLI v5.0.8
? Please pick a preset: (Use arrow keys)
  Default ([Vue 3] babel, eslint)
❯ Default ([Vue 2] babel, eslint)
  Manually select features

警告:在撰写本文时,Vuetify不支持Vue.js v3。如果您尝试将Vuetify添加到Vue.js v3中,您将看到以下错误:

输出错误:您无法在没有路径的集合上调用”get”。请先检查”length”属性,以验证至少存在一个路径。

如需更多信息,请参阅Vuetify路线图。

这是文章《如何在Ubuntu 20.04上使用Nginx发布一个Vuetify应用程序》的第2部分(共18部分)。

一旦应用程序创建完成,您会注意到Vue生成的文件和目录。

├── README.md
├── babel.config.js
├── jsconfig.json
├── node_modules
├── package-lock.json
├── package.json
├── public/
      ├── favicon.ico
      └── index.html
├── src
        ...
└── vue.config.js

这里有一个简要概述:

  • babel.config.js: Babel是一个JavaScript编译器,这个文件定义了它的行为。这是运行、构建和生成最终应用程序所必需的。
  • jsconfig.json: 这个文件也是编译应用程序所必需的。例如,这个文件将JavaScript代码的版本设置为ECMAScript 2009(ES5),这是默认版本。更多信息,请查看此文档。
  • node_modules: 包含所有已安装和配置的库的目录。
  • package.json: 您的应用程序的主要配置文件。您将在这里看到有关依赖项以及可用于运行或构建应用程序的命令的信息。
  • package-lock.json: 这是您的应用程序使用的所有依赖项的转储文件。如果您想使用npm在另一台笔记本电脑或服务器上安装您的应用程序,这个文件特别有用。
  • public: 在这里,您有npm run serve命令发布应用程序所需的基础代码。它是由@vue/cli命令生成的。
  • vue.config.js: Vue配置文件。

在源文件夹中,你将看到以下文件和目录:

src
├── App.vue
├── assets
│ ├── logo.png
│ └── logo.svg
├── components
│ └── HelloWorld.vue
├── main.js

这是一个简要概述:

  • App.vue: Vue.js应用程序的顶级组件。所有其他组件都将位于此处定义的组件内部。
  • assets: 所有资源,如图像、CSS文件和字体,都必须放在这里。
  • components: 这包含您创建的所有组件。@vue/cli命令生成了一个名为HelloWorld.vue的组件。
  • main.js: 应用程序主文件。如果您需要配置库或插件,就是这个文件。它还创建了Vue应用程序。

现在您可以导航到vuetify-meets-nginx-app目录。

  1. cd vuetify-meets-nginx-app

要以开发模式启动应用程序,请运行以下命令:

  1. npm run serve

你的输出将会是这样的:

输出
INFO Starting development server... DONE Compiled successfully in 27235ms App running at: - Local: http://localhost:8080/ - Network: unavailable Note that the development build is not optimized. To create a production build, run npm run build.

一旦开发服务器启动,打开 localhost:8080 即可查看应用程序。

VueJS应用程序的默认主页截图

注意:如果您是在远程服务器上执行教程,请使用端口转发在浏览器中查看应用程序。确保您的服务器上的端口8080是开放的。在开发服务器仍在运行时,打开本地计算机上的另一个终端,并输入以下命令以启动端口转发:

ssh -L 8080:localhost:8080 您的非根用户@您的服务器IP

连接到服务器后,在本地计算机的Web浏览器中导航到http://localhost:8080。在本教程的剩余部分,保持第二个终端打开。

在这一步中,你创建了自己的Vue.js应用程序。接下来,你将为项目添加Vuetify。

第二步—将Vuetify集成到Vue应用中

在这一步中,您将向您的Vue.js应用程序中添加Vuetify。

如果没有像Vuetify这样的组件库,你必须使用HTML的input元素,比如div和button,为你的网络应用设计CSS,并且自己创建组件,如果你想要一些可重复使用的块。但是有了Vuetify库,你只需要导入你想要的组件并且添加到你的模板中。

Vuetify也可以高度定制化。例如,你可以使用主题。一个主题是一个包含颜色调色板、自定义屏幕大小和字体等内容的CSS库。比如,如果你的主要颜色是蓝色,你可以配置Vuetify以这种方式,每次你使用primary CSS类时,Vuetify都会使用蓝色。你可以在Vuetify文档中找到有关主题的更多信息。有关这些和其他组件的更多信息可以在Vuetify功能指南中找到。

要开始添加Vuetify,首先要停止在前一步中启动的开发服务器,在运行开发服务器的终端中按下CTRL+C键。

接下来,在vuetify-meets-nginx-app目录中运行以下命令。

  1. vue add vuetify

使用Vue.js客户端安装Vuetify的命令是这样的。

在预设选项列表中选择默认配置。

输出

? 正在安装 vue-cli-plugin-vuetify… 已添加 38 个包,并在 2 秒内审计了 39 个包 7 个包正在寻找资金支持 运行 `npm fund` 查看详情 发现 0 个漏洞 ✔ 成功安装插件:vue-cli-plugin-vuetify ? 选择一个预设:(使用方向键) 配置 (高级) ❯ 默认 (推荐) Vite 预览 (Vuetify 3 + Vite) 原型 (快速开发) Vuetify 3 预览 (Vuetify 3)

几分钟后,您可以再次启动开发服务器。

  1. npm run serve

 

导航到 localhost:8080,在那里你可以看到一个应用程序,具有全新的’vuetified’样式。

安装了Vuetify的VueJS应用程序的默认主页截图

在这一点上,您已经创建了一个基本应用程序,并添加了Vuetify进行样式设置。接下来,您将创建一个拥有额外功能的待办事项应用程序。

第三步 — 创建一个使用Vuetify的待办事项应用

在这个步骤中,你将创建一个待办事项应用程序。待办事项应用程序是一个任务列表,需要一些基本功能。

  • 添加新任务的方法。
  • 将任务标记为已完成的方法。
  • 显示任务的方法,允许用户查看待办事项。

要将这些功能添加到您的应用程序中,您将修改App.vue文件,该文件是应用程序的顶级组件。所有其他组件都将包含在这里定义的组件中。

注意:

Vue.js 和很多其他框架一样,默认采用热加载。在你开发代码时,只要持续运行 npm run serve 命令,你保存修改后,浏览器上就会立即显示更新内容。

导航到 src/App.vue 并使用 nano 或您喜欢的文本编辑器打开以进行编辑。

  1. cd src
  2. nano App.vue

 

这里是默认代码

vuetify-meets-nginx-app/src/App.vue 可以被描述为:vuetify与nginx相遇的应用程序的主Vue文件。
<template>
  <v-app>
    <v-app-bar
      app
      color="primary"
      dark
    >
      <div class="d-flex align-center">
        <v-img
          alt="Vuetify Logo"
          class="shrink mr-2"
          contain
          src="https://cdn.vuetifyjs.com/images/logos/vuetify-logo-dark.png"
          transition="scale-transition"
          width="40"
        />

        <v-img
          alt="Vuetify Name"
          class="shrink mt-1 hidden-sm-and-down"
          contain
          min-width="100"
          src="https://cdn.vuetifyjs.com/images/logos/vuetify-name-dark.png"
          width="100"
        />
      </div>

      <v-spacer></v-spacer>

      <v-btn
        href="https://github.com/vuetifyjs/vuetify/releases/latest"
        target="_blank"
        text
      >
        <span class="mr-2">最新版本</span>
        <v-icon>mdi-open-in-new</v-icon>
      </v-btn>
    </v-app-bar>

    <v-main>
      <HelloWorld/>
    </v-main>
  </v-app>
</template>

<script>
import HelloWorld from './components/HelloWorld';

export default {
  name: 'App',

  components: {
    HelloWorld,
  },

  data: () => ({
    //
  }),
};
</script>

每个组件都有两个部分:一个模板(通常是HTML代码)和一个用JavaScript编写的具有功能的脚本。

模板是最终用户在浏览器中看到的,它决定了用户与你的应用程序的交互方式。通常情况下,你需要导入要在模板中使用的组件,但由于你将Vuetify安装为插件,所有组件都可以在模板中直接使用,无需显式导入。

模板块中有很多v- HTML标签。尽管对于HTML来说非标准,但这些标签是Vuetify组件,并且始终以v-开头。

在模板中,您目前有:

  • v-app:主组件,附加到网站的body部分。
  • v-app-bar:默认侧边栏。
  • v-img:加载图片的组件。
  • v-icon:用于显示图标的组件。
  • v-spacer:将下一个组件对齐到右侧的组件。

关于App.vue文件中的脚本块,在Vuetify安装中并没有添加任何代码在这里,所以你所拥有的只是由Vue cli命令生成的起始代码以及Vue组件所需的最小代码。

现在你已经查看了App.vue文件中的默认代码,准备开始创建你的待办事项应用。第一步将是删除一些你不会使用的默认代码。

整理App.vue文件

这是文章《如何在Ubuntu 20.04上使用Nginx发布一个Vuetify应用程序》的第5部分(共18部分)。

内容片段:默认的HelloWorld组件在您的待办事项应用中不再需要,因此您需要将其从App.vue文件中删除。

要在另一个组件或视图中使用Vue组件,您必须将该组件导入到文件的脚本块中。在您的App.vue文件中,您在第一行导入了HelloWorld组件。

当Vuetify与Nginx应用结合时,源代码路径为/src/App.vue。

...
import HelloWorld from './components/HelloWorld';
...

既然您不会使用这个组件,就删除导入行。

下一步是从App.vue页面的组件依赖列表中移除该组件。在脚本块中,找到以下行:

Vuetify与Nginx应用程序的主文件路径为:vuetify-meets-nginx-app/src/App.vue

...
<script>
  ...

  components: {
    HelloWorld,
  },

  ...
</script>

从组件列表中删除HelloWorld这一行。

最后一步是将它从模板块中移除。

vuetify-meets-nginx-app/src/App.vue(即Vuetify遇上Nginx的应用程序/src/App.vue)

...
<template>
    ...
    <v-main>
      <HelloWorld/>
    </v-main>
  </v-app>
</template>
...

删除HelloWorld这一行。

现在默认的HelloWorld组件已经被移除了,您可以开始创建您的待办事项应用了。

添加组件数据字段

为了构建您的待办事项应用程序,您需要为您的应用程序添加数据字段。组件的数据是一个函数,它返回您将能够在模板中使用的所有数据模型。所有这些数据模型都是一个对象中的JavaScript变量,并且还可以被组件的方法访问。

在脚本块中找到数据字段位置。

vuetify-meets-nginx-app/src/App.vue(即Vuetify遇上Nginx的应用程序源文件)

...
<script>
  ...
  data: () => ({
    //
  }),
};
</script>

您将修改数据函数以存储您的任务列表。将以下突出显示的行添加到数据函数中。

vuetify-meets-nginx-app/src/App.vue(即Vuetify遇上Nginx的应用程序源文件)
...
<script>
    ...
    data: () => ({
        tasks: ['task 1', 'task 2', 'task 3'],
        newTask: null
    }),
};
</script>

通过此更新,您添加了两个数据模型:一个用于存储新任务名称的newTask变量,以及一个用于存储任务列表的tasks数组。现在,这两个数据模型都可以在模板和方法中使用。

注意:如果您对Vue.js如何使数据模型对模板和组件方法可访问的机制不熟悉,建议查阅Vue.js官方文档中的响应式基础知识部分。

为您的应用程序添加功能

接下来,您将为应用程序添加功能。在Vue.js组件中,功能被定义在一个名为methods的函数列表中。请在数据模型下方的脚本块中,添加下面突出显示的代码行来定义三个函数:

本示例中涉及的Vuetify与Nginx应用程序的文件路径为/src/App.vue。

...
<script>
export default {
    name: 'App',

    data: () => ({
        tasks: ['task 1', 'task 2', 'task 3'],
        newTask: null
    }),
    methods: {
        addNewTask() {
            this.tasks.push(this.newTask);
            this.clearNewTask();
        },
        clearNewTask() {
            this.newTask = '';
        },
        removeTask(i) {
            this.tasks.splice(i, 1);
        }
    }
};

你添加了三个功能:

  • addNewTask: 将newTask数据模型中的新任务添加到任务列表中。
  • clearNewTask: 清除newTask的数据模型。
  • removeTask: 根据数组索引从任务列表中移除任务。

现在,你已经为待办事项应用程序添加了所需的功能。接下来,你将修改模板以使用这些方法。

更新模板

你的待办事项应用的最后一部分是模板。在这个部分,你将会更新模板,使用之前部分中添加的方法和数据模型。

你需要从v-app-bar中删除一些不需要的组件。删除v-btn块。然后,你的代码将如下所示:

vuetify-meets-nginx-app/src/App.vue 这个文件是 Vuetify 与 Nginx 应用程序的入口文件。
<template>
    <v-app>
        <v-app-bar
            app
            color="primary"
            dark
        >
        <div class="d-flex align-center">
            <v-img
                alt="Vuetify 标志"
                class="shrink mr-2"
                contain
                src="https://cdn.vuetifyjs.com/images/logos/vuetify-logo-dark.png"
                transition="scale-transition"
                width="40"
            />

            <v-img
                alt="Vuetify 名称"
                class="shrink mt-1 hidden-sm-and-down"
                contain
                min-width="100"
                src="https://cdn.vuetifyjs.com/images/logos/vuetify-name-dark.png"
                width="100"
            />
        </div>

        <v-spacer></v-spacer>

        </v-app-bar>
        ...
    </v-app>
</template>

接下来,您将添加一些组件来定义您的应用程序的基本布局。首先是v-container,它是一个提供将应用程序内容居中和水平填充的能力的组件。有关该组件和其他容器的更多信息,请参阅Vuetify的网格系统文档。

在v-container中,您将添加一个v-card组件,它是另一个Vuetify容器。它用于在屏幕上组织内容,例如面板或静态图像。要了解有关v-card组件的更多信息,请查阅Vuetify文档中的卡片部分。

找到当前模板中的v-main块并添加高亮显示的行。

vuetify-meets-nginx-app/src/App.vue 的内容。
...
<v-main>
    <v-container>
        <v-card elevation="0">
        </v-card>
    </v-container>
</v-main>
...

正如您在代码中看到的那样,v-card组件中有一个elevation=”0″属性。在Vuetify组件中,elevation是一个常见属性,用于调整组件之间的相对Z轴距离。在这种情况下,您不需要任何阴影效果,而0值是用来移除elevation效果的。但是,您可以尝试调整该值来观察不同效果,或者查阅elevation相关文档获取更多信息。

接下来,您将使用两个v-card功能组件:v-card-title,它为卡片标题提供了默认的字体大小和内边距;以及v-card-text,它将包含卡片的主要内容。请将以下代码行添加到您的v-card组件中:

Vuetify和Nginx应用在/vuetify-meets-nginx-app/src/App.vue文件中相结合。

...
<v-main>
    <v-container>
        <v-card elevation="0">
            <v-card-title></v-card-title>
            <v-card-text></v-card-text>
       </v-card>
    </v-container>
</v-main>
...

功能组件是仅渲染模板的组件。它不包含任何逻辑,并且由于它仅仅是一个模板,所以渲染速度更快。如需了解更多有关功能组件的信息,或学习如何创建您自己的功能组件,请参阅Vue.js官方指南中的功能组件部分。

现在您已经完成了容器组件的设置,接下来需要添加一个v-text-field组件来处理新任务的名称。请在您刚刚添加的v-card-title组件中,插入以下需要突出显示的代码行:

vuetify-meets-nginx-app/src/App.vue文件路径
...
<v-main>
    <v-container>
        <v-card elevation="0">
            <v-card-title>
              <v-text-field
                v-model="newTask"
                label="Task Name"
                prepend-icon="mdi-content-save"
                clear-icon="mdi-close-circle"
                clearable
                filled
                type="text"
                @click:prepend="addNewTask"
                @click:clear="clearNewTask"
                ></v-text-field>
            </v-card-title>
           ...
        </v-card>
    </v-container>
</v-main>
...

v-text-field是用于命名新任务的必需组件。

它具有以下特性:

  • v-model="newTask" 将数据模型绑定到组件。您在输入框中输入的任何文本都会被添加到数据模型中。
  • label="Task Name" 是输入框中的占位符文本。
  • prepend-icon="mdi-content-save" 会在文本框的左侧显示保存图标。
  • clear-icon="mdi-close-circle" 是清除按钮的图标。
  • clearable 显示清除图标。
  • filled 为组件应用填充式输入样式。
  • type="text" 设置底层HTML输入字段的类型。其他选项包括email或password。
  • @click:prepend="addNewTask" 将保存按钮的点击事件绑定到addNewTask函数。
  • @click:clear="clearNewTask" 将清除按钮的点击事件连接到clearNewTask函数。

下一步是展示任务列表模型中的每个任务。为此,您将使用v-timeline组件,这是一个用于显示基于时间或顺序的信息的显示组件。您将把它添加到v-card-text中,该组件是v-card的主体组件。在已添加的v-card-text组件内,插入高亮显示的行。

文件路径:vuetify-meets-nginx-app/src/App.vue

...
<v-main>
    <v-container>
        <v-card elevation="0">
            <v-card-title>
            ...
            </v-card-title>
            <v-card-text>
              <v-timeline
                  v-if="tasks.length > 0"
                  dense
              ></v-timeline>
            </v-card-text>
            ...
      </v-card>
   </v-container>
</v-main>
...

v-timeline组件会显示列表中的所有任务。v-if指令确保只有当数据模型中存在至少一个任务时才显示该组件。dense属性用于紧凑显示内容(基本上,它会从组件的CSS样式中减少一些内边距和外边距)。

现在,为了显示每个任务的名称,你需要使用v-timeline的子组件:v-timeline-item。在v-timeline组件内添加以下代码行:

vuetify-meets-nginx-app/src/App.vue 文件的内容。

...
<v-main>
    <v-container>
        <v-card elevation="0">
            <v-card-title>
            ...
            </v-card-title>
            <v-card-text>
              <v-timeline
                  v-if="tasks.length > 0"
                  dense
                >
                    <v-timeline-item
                        v-for="(t, index) in tasks"
                        :key="index"
                    >
                         {{ t }}
                    </v-timeline-item>
              </v-timeline>
            </v-card-text>
        </v-card>
    </v-container>
</v-main>
...

该代码使用v-for循环,在任务列表模型中为每个任务显示一个v-timeline-item组件。由于v-timeline-item是v-timeline的功能组件,因此会以时间顺序的列表样式呈现。

你在v-for循环中将索引添加为键是因为它对于v-for指令是必需的。关于如何在v-for中使用唯一键,请查阅Vue产品文档。

通过{{ t }}行,您将能在v-timeline-item组件中显示任务的名称。

下一步是在列表中添加一个按钮来删除任务。但在此之前,您需要添加一些额外的网格系统组件来组织任务名称和按钮。在v-timeline-item组件中添加突出显示的行:

Vuetify与Nginx应用程序相结合的源代码文件在vuetify-meets-nginx-app/src/App.vue中。

...
<v-main>
    <v-container>
        <v-card elevation="0">
            <v-card-title>
            ...
            </v-card-title>
            <v-card-text>
              <v-timeline
                  v-if="tasks.length > 0"
                  dense
                >
                    <v-timeline-item
                        v-for="(t, index) in tasks"
                        :key="index"
                    >
                        <v-row class="display-1 text-capitalize">
                            <v-col cols="7">
                                {{ t }}
                            </v-col>
                            <v-col
                                class="text-right"
                                cols="5"
                            >
                            </v-col>
                        </v-row>
                     </v-timeline-item>
               </v-timeline>
             </v-card-text>
         </v-card>
     </v-container>
</v-main>
...

通过上面的代码,你增加了:

  • 一个带有两个类的v-row组件,用于设置任务文本的大小(display-1,类似于HTML中的H1)并将所有字符转换为大写(text-capitalize)。
  • 在行内添加了一个v-col组件,用于显示每个任务的名称,该组件需要占用7/12的空间(通过cols=”7″属性设置)。
  • 另一个v-col组件用于放置删除按钮。它需要占用5/12的空间(通过cols=”5″属性设置),并且内部所有组件都通过text-right类设置为右对齐。

最后,是时候将removeTask函数附加到一个按钮组件上,使用v-btn组件。为了简化,你将使用一个图标按钮,即只有图标没有文本的按钮。为此,你还需要一个v-icon组件。

请加入被突出显示的行。这些代码将添加到你的Vuetify与Nginx应用程序的源代码文件App.vue中。

...
<v-timeline
    v-if="tasks.length > 0"
    dense
>
    <v-timeline-item
        v-for="(t, index) in tasks"
        :key="index"
    >
        <v-row class="display-1 text-capitalize">
            <v-col cols="7">
                {{ t }}
            </v-col>
            <v-col
                class="text-right"
                cols="5"
            >
                <v-btn
                    icon
                    @click="removeTask(index)"
                >
                    <v-icon color="red lighten-1" large>
                        mdi-sticker-remove
                    </v-icon>
                </v-btn>
            </v-col>
        </v-row>
    ...
    </v-timeline-item>
</v-timeline>

在您刚刚添加的代码中,v-btn组件的icon属性指定了不需要文本。它修改了组件,只对v-icon组件进行样式设置。

@click组件事件将您的removeTask方法绑定到按钮的点击事件上。因此,每当底层的按钮点击事件被触发时,您的方法将被调用。

您使用了v-for循环提供的索引作为removeTask方法的参数。

最后,v-icon的颜色将是红色lighten-1,大小将为大号,且您使用的是mdi-sticker-remove材料设计的图标。

现在您已经使用一些Vuetify组件更新了模板,并配置了它们以使用和显示数据模型的内容,同时还允许您的应用用户通过页面方法与它们进行交互。

这是App.vue文件的最终代码。

vuetify-meets-nginx-app/src/App.vue的中文翻译:
vuetify-meets-nginx-app/src/App.vue

<template>
    <v-app>
        <v-app-bar
            app
            color="primary"
            dark
        >
        <div class="d-flex align-center">
            <v-img
                alt="Vuetify Logo"
                class="shrink mr-2"
                contain
                src="https://cdn.vuetifyjs.com/images/logos/vuetify-logo-dark.png"
                transition="scale-transition"
                width="40"
            />

            <v-img
                alt="Vuetify Name"
                class="shrink mt-1 hidden-sm-and-down"
                contain
                min-width="100"
                src="https://cdn.vuetifyjs.com/images/logos/vuetify-name-dark.png"
                width="100"
            />
        </div>

        <v-spacer></v-spacer>

        </v-app-bar>

        <v-main>
            <v-container>
                <v-card elevation="0">
                    <v-card-title>
                        <v-text-field
                            v-model="newTask"
                            label="任务名称"
                            prepend-icon="mdi-content-save"
                            clear-icon="mdi-close-circle"
                            clearable
                            filled
                            type="text"
                            @click:prepend="addNewTask"
                            @click:clear="clearNewTask"
                        ></v-text-field>
                    </v-card-title>
                    <v-card-text>
                        <v-timeline
                            v-if="tasks.length > 0"
                            dense
                        >
                            <v-timeline-item
                                v-for="(t, index) in tasks"
                                :key="index"
                            >
                                <v-row class="display-1 text-capitalize">
                                    <v-col cols="7">
                                        {{ t }}
                                    </v-col>
                                    <v-col
                                        class="text-right"
                                        cols="5"
                                    >
                                        <v-btn
                                            icon
                                            @click="removeTask(index)"
                                        >
                                            <v-icon color="red lighten-1" large>
                                                mdi-sticker-remove
                                            </v-icon>
                                        </v-btn>
                                    </v-col>
                                </v-row>
                            </v-timeline-item>
                        </v-timeline>
                    </v-card-text>
                </v-card>
            </v-container>
        </v-main>
    </v-app>
</template>

<script>

export default {
    name: 'App',

    data: () => ({
        tasks: ['任务 1', '任务 2', '任务 3'],
        newTask: null
    }),
    methods: {
        addNewTask() {
            this.tasks.push(this.newTask);
            this.clearNewTask();
        },
        clearNewTask() {
            this.newTask = '';
        },
        removeTask(i) {
            this.tasks.splice(i, 1);
        }
    }
};
</script>

保存并关闭你的文件。

如果你的开发服务器还没有运行,请重新启动它。

  1. npm run serve

 

现在你可以导航到 localhost:8080 来查看你的应用程序运行。

Vuetify待办事项应用程序现在显示列表中的三个任务:任务1、任务2、任务3

在这个步骤中,您创建了一个待办事项应用程序。您增加了功能并更新了用户界面。现在,您已经完成了该应用程序的编写,可以生成一个适用于生产环境的版本。下一步是为生产环境构建该应用程序。

第四步 — 将您的应用程序进行生产环境编译

在之前的步骤中,您已经编写了待办事项应用程序。但在使用Nginx发布之前,您需要为应用程序做好生产环境准备。这一步骤称为构建应用程序。

构建步骤将应用程序转换为浏览器可读取的内容。如果您尝试在浏览器中直接打开您的源文件,您将看不到任何内容。这是因为它们是Vue.js文件,而不是浏览器可以直接读取的HTML、JS和CSS文件。在使用Nginx发布您的应用程序之前,您需要将应用程序构建为生产环境版本,这就是您在此步骤中要做的事情。

您可以使用构建命令来自动完成此操作。package.json 是您应用程序的主要配置文件。它包含有关依赖项和可运行或构建应用程序的命令的信息,例如构建命令,如下所示:

package.json 是一个用于描述项目的配置文件,其中包含了项目的名称、版本、依赖以及其他相关信息。

{
  ...
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint"
  },
  ...
}

关于package.json文件配置的更多详情,请查阅package.json指南。

要开始构建过程,请使用CTRL+C停止开发服务器。

在同一个终端中,切换到项目目录。

  1. cd vuetify-meets-nginx-app

 

执行构建命令:

  1. npm run build

 

当构建完成后,您将在 dist 目录中拥有一个可供生产使用的应用程序版本。

接下来,您将设置Nginx作为反向代理来部署和访问应用程序。

第五步 – 将Nginx配置为反向代理

现在您已经有了一个可工作的应用程序,您必须将Nginx配置为反向代理,以提供您的应用程序文件并将其与您的域名连接起来。

反向代理是运行在服务器上的应用程序或服务,它可以将外部请求转发到另一个位置。在您的情况下,每当用户在浏览器中访问您的域名时,Nginx会通过返回来自您的应用程序的文件来处理该请求。它会返回文件,因为当您构建应用程序时,会生成HTML、JS和CSS文件,Nginx会将其视为服务器上的其他静态文件或网站来处理。

Nginx与站点配合工作。每个站点都是在一个单独的文件中配置的不同网站。所有的配置文件默认放在 /etc/nginx/sites-available/ 目录中。前往该目录。

  1. cd /etc/nginx/sites-available/

 

创建一个名为vuetify-meets-nginx-app的文件。

  1. sudo nano vuetify-meets-nginx-app

 

注意:

您可以根据需要将文件命名为任何名称,但按照惯例,以您希望发布的应用程序或网站的名称命名是常规做法。在您的vuetify-meets-nginx-app文件中,添加以下行,并确保使用您自己的信息更新server_name:
/etc/nginx/sites-available/vuetify-meets-nginx-app 可用于设置 Vuetify 和 Nginx 应用程序。
server {
  listen 80;
  listen [::]:80;
  server_name your_domain;
  autoindex on;
  root   /home/sammy/vuetify-meets-nginx-app/dist/;
  index  index.html;
}

在本教程中,您正在配置Nginx监听80端口,但您可以使用任何您想要的端口。将your_domain替换为您的域名。如果您正在本地开发环境中进行测试,您也可以使用服务器的IP地址或localhost。

通过根目录行,您告诉 Nginx 所有文件都位于 /home/sammy/vuetify-meets-nginx-app/dist/ 目录中,该目录在前一步骤中创建。最后,通过索引行,您告诉 Nginx 主文件是 index.html。

保存并关闭您的文件。

接下来,您需要解决Nginx配置文件中的权限问题。

Nginx是在您的服务器上运行的服务。您可以使用以下命令列出所有与Nginx相关的运行进程。

  1. ps -fea | grep nginx

 

使用带有-fae选项的ps命令以完整格式列出所有当前的进程。然后将该命令的输出进行过滤,仅列出与nginx匹配的进程。

输出的结果将类似于以下内容:

输出

root 39922 1 0 Jul14 ? 00:00:00 nginx: master process /usr/sbin/nginx -g daemon on; master_process on; www-data 39923 39922 0 Jul14 ? 00:00:01 nginx: worker process sammy 117909 117434 0 21:27 pts/0 00:00:00 grep --color=auto nginx

如图所示,nginx服务正以www-data用户运行。

接下来,使用这个命令查看/home/sammy/vuetify-meets-nginx-app/dist/的权限:

  1. ls -l /home/sammy/vuetify-meets-nginx-app/dist/

 

输出将与以下类似:

输出

total 20 drwxrwxr-x 2 sammy sammy 4096 Jul 14 18:54 css -rw-rw-r– 1 sammy sammy 4286 Jul 14 18:54 favicon.ico -rw-rw-r– 1 sammy sammy 853 Jul 14 18:54 index.html drwxrwxr-x 2 sammy sammy 4096 Jul 14 18:54 js

所有的文件和文件夹都具有对用户”Sammy”开放的权限。如果你配置Nginx来读取这些文件,由于Nginx用户”www-data”没有执行权限,这将无法工作。

解决此问题有几个选择:

  • 授予Nginx对dist文件夹的读、写和执行权限。然而,授予一个可从整个网络访问的服务读取本地用户文件的权限是不安全的。此外,Nginx将需要访问所有父文件夹的权限,因为它需要导航到最终文件夹,这基本上会将/home目录向全世界开放。不推荐此方法。
  • 使用sudo运行nginx。这也不安全,因为现在你将拥有一个可以访问服务器上所有文件的服务。
  • 将你的dist内容移动到只有Nginx可以访问而其他用户无法访问的位置。这是最安全的选项。

在本教程中,您将使用第三个选项。

在Ubuntu和一些其他基于Linux的发行版中,服务之间用于交换文件的共享位置是/var路径。您将把文件复制到/var/www,这是Nginx用于网站的默认路径。

从您的项目目录中运行以下命令,将您的文件复制到/var/www路径中。

  1. sudo cp -r /home/sammy/vuetify-meets-nginx-app/dist /var/www/vuetify-meets-nginx-app

 

复制所有文件时将保持与之前相同的权限,即为sammy用户的权限,因此您需要将sammy用户添加到与www-data相同的权限组中。您可以使用以下命令来实现此操作:

  1. sudo usermod -aG www-data sammy

 

目前,Nginx可以以安全方式访问所需的文件。然而,每当生成新版本的应用程序时,您都需要复制项目文件,这可能会增加自动部署、CI/CD工具等的复杂性。更好的解决方案是修改构建命令,直接在正确的路径生成文件。

要做到这一点,打开 package.json 进行编辑,并添加加亮的文本。

package.json 文件

...
"build": "vue-cli-service build --dest /var/www/vuetify-meets-nginx-app",
...

保存并关闭文件。

现在你可以完成Nginx的配置了。打开Nginx配置文件并将其更新为新的应用程序路径。

/etc/nginx/sites-available/vuetify-meets-nginx-app – Nginx配置文件中可用的Vuetify meets Nginx应用程序

server {
  listen 80;
  listen [::]:80;
  server_name your_domain OR your_server_IP;
  autoindex on;
  root   /var/www/vuetify-meets-nginx-app;
  index  index.html;
}

保存并关闭你的文件。

现在你的网站文件准备好了,你需要启用它。为此,请转到启用的网站路径:

  1. cd /etc/nginx/sites-enabled/

 

禁用默认网站以确保您不会在同一端口(端口80)上启用和监听两个网站。

  1. sudo rm default

 

最后,创建一个符号链接文件到你的应用配置文件。

  1. sudo ln -s /etc/nginx/sites-available/vuetify-meets-nginx-app

 

Nginx只会考虑放置在启用目录中的站点文件。您可以直接复制配置文件,但不建议重复文件,因为可能会出现不一致。这就是为什么符号链接(可用文件的文件快捷方式)是更好的方法。

测试以确保您的Nginx文件中没有语法错误。

  1. sudo nginx -t

 

你的输出将会像这样:

输出

nginx: 配置文件 /etc/nginx/nginx.conf 语法正确
nginx: 配置文件 /etc/nginx/nginx.conf 测试成功

nginx: 配置文件 /etc/nginx/nginx.conf 语法正确 nginx: 配置文件 /etc/nginx/nginx.conf 测试成功

为应用更改,请重新启动Nginx服务。

  1. sudo systemctl restart nginx

 

现在,您可以通过导航到您的域名(或者您服务器的IP地址)来查看您的待办应用程序已经准备好并且已发布。

Vuetify待办应用程序显示了一个包含三个任务的列表:任务1,任务2,任务3

在这一步中,你将Nginx配置为反向代理以发布你的应用程序。

结论

在本教程中,你创建了一个Vue.js应用程序并安装和配置了Vuetify框架。然后,你生成了一个静态版本的应用程序,准备上线生产环境,并最后配置了Nginx服务以发布应用。

想要更详细地了解项目文件,请查看Github仓库。

作为下一步,请尝试配置Nginx以通过HTTPS提供您的应用程序。要开始,请遵循我们的教程《如何在Ubuntu 20.04上使用Let’s Encrypt保护Nginx》。

要了解更多关于 Vuetify 的内容,请查阅 Vuetify 文档。如果你有兴趣扩展 Vuetify 组件的功能,请查看我们的教程《扩展 Vuetify 表单字段验证》。

bannerAds