用Vue 3、Nuxt和TypeScript搭建应用程序的脚手架

2,447 阅读6分钟

简介

Nuxt是一个建立在Vue.js框架之上的高级框架。开箱后,Nuxt配备了流行的Vue库,如vue-router、vue-meta,以及用于全局状态管理的Vuex。

此外,Nuxt还使用了一些构建工具,如webpack、Babel和PostCSS。而这些都是开箱即用的预配置。

受Next.js的启发,Nuxt提供了动态服务器端渲染(SSR)。

为什么是Nuxt?

如果Vue已经是一个框架,有人会问,为什么是Nuxt?

虽然Vue是一个伟大的框架,但Nuxt提供了一些额外的令人兴奋的功能,如开箱即用的动态服务器端渲染。另外,Nuxt的目的是通过提供优化的构建工具配置,以及在一些相当复杂的Vue概念上提供一个抽象层,例如路由,来使开发者的生活更轻松。

我们可以将Nuxt的需求总结为三点。

功能齐全

Nuxt包含了Vue和许多流行的Vue库,如用于路由的vue-router,用于全局状态管理的vuex,以及用于处理元标签的vue-meta。

此外,Nuxt是非常通用的。我们可以用Nuxt来构建单页应用--SPA,动态服务器端渲染--SSR,以及静态网站生成--SSG。

增强功能

Nuxt使用文件系统路由,它是vue-router上面的一个抽象层,根据page 目录中的文件树自动生成vue-router配置。

同时,Nuxt通过布局组件Nuxt组件的概念为Vue组件增色。

虽然Vue已经有一个很好的过渡API,但Nuxt在此基础上进行了改进,处理了一些复杂的情况,如页面之间的过渡

优化

开箱即用,Nuxt为构建工具提供了优化配置,如PostCSS、webpack和Babel。

此外,由于支持SSR,良好的元标签处理,以及文件系统路由生成SEO友好的URL,我们的Nuxt应用程序可以为SEO进行优化。

我们得到的其他优化是智能预取,自动代码拆分,以及资产指纹或缓存突发

Nuxt和TypeScript

TypeScript,简而言之,就是JavaScript加上一个类型系统--帮助我们在开发过程中捕捉错误。

除了以上这些,TypeScript还为我们的代码提供了一种自我记录的形式,在大型应用中特别有用。

Nuxt TypeScript支持主要由两个主要的Nuxt包提供,即@nuxt/typescript-build --在布局、组件、插件和中间件中提供支持,以及@nuxt/types --包含Nuxt TypeScript类型定义,并与Nuxt核心一起维护。

我们可以通过运行来安装这些包。

yarn add --dev @nuxt/types
# OR
npm install --save-dev @nuxt/types

除了这些包,Nuxt还提供了一个可选的TypeScript运行时支持,使用@nuxt/typescript-runtime 模块。根据文档,TypeScript运行时支持是需要的,比如说nuxt.config 文件、本地模块和serverMiddlewares ,这些文件是不被webpack编译的。

安装后,需要进一步配置,以便为Vue的核心功能提供TypeScript支持,如Options API、Class API、商店等。你可以在我们之前关于Nuxt.js和TypeScript的文章中了解这些内容。

在这篇文章中,我们专注于使用TypeScript和Vue 3 Composition API。
,让我们在下一节开始学习。

开始使用

默认情况下,Vue Composition API并不包括Nuxt的特定功能,如服务器端渲染。而Nuxt Composition API就是为此而开发的;它结合了Vue Composition API和所有Nuxt的功能。

根据文档,Nuxt组成的API模块会自动安装为一个插件。 [@vue/composition-api](https://github.com/vuejs/composition-api)作为一个插件,所以我们不需要单独启用它。
另外,为了方便,Nuxt组合API模块导出了@vue/composition-api 方法和挂钩,所以你可以直接从@nuxtjs/composition-api

@nuxtjs/composition-api 提供了一种使用Vue 3 Composition API与Nuxt特定功能的方法。而根据文档,Nuxt Composition API的一些特点是。

  • 支持v2.12以上版本的新Nuxt fetch
  • 在组合APIsetup() 钩中提供对路由器、应用、商店的简单访问
  • 直接与你的vue-meta属性互动 在setup() 钩子内的组合API
  • ref 提供了一个直接的替代品,可自动对SSR 进行字符串化和水化 (ssrRef)
  • 用TypeScript编写

在下一节中,我们将使用Nuxt、TypeScript和Nuxt组合API建立一个远程招聘网站。

构建我们的应用程序

首先,我们通过运行启动我们的应用程序。

yarn create nuxt-app <project-name>

or 

npx create-nuxt-app <project-name>

它会问你一些关于名字、Nuxt选项、UI框架、TypeScript等问题。一定要选择TypeScript。这将安装和配置上面讨论的Nuxt TypeScript模块。

现在,通过运行安装Nuxt composition API包。

// change into project directory
cd <project-name>

// install package
yarn add @nuxtjs/composition-api

然后通过修改nuxt.config.js 文件启用该模块,如下图所示。

...
    buildModules: [
        // https://go.nuxtjs.dev/typescript
        '@nuxt/typescript-build',

        // @nuxtjs/composition-api
        '@nuxtjs/composition-api/module'
    ],
...

最后,通过运行来启动该应用程序。

yarn start

我们得到。

Welcome to Nuxt Page

现在让我们来创建我们的types 。创建一个类型目录,包含一个Jobs.ts 和一个OrderItem.ts 文件。

Jobs.ts 文件中添加以下代码。

interface Job {
    title: string;
    location: string;
    salary: number;
    id: string;
}
export default Job;

并将以下代码添加到OrderItem.ts 文件中。

type OrderTerm = 'title' | 'salary' | 'location';
export default OrderTerm;

index.vue 文件中添加以下代码。

<template>
  <div class="app">
    <header>
      <div class="title">
        <h1>Remote Developer Jobs</h1>
      </div>
      <div class="order">
        <button @click="handleClick('title')">Order by title</button>
        <button @click="handleClick('salary')">Order by salary</button>
        <button @click="handleClick('location')">Order by location</button>
      </div>
    </header> 
    <JobList :jobs="jobs" :order="order" />
  </div>
</template>
<script lang="ts">
  import { defineComponent, ref } from '@nuxtjs/composition-api';
  import Job from '@/types/Jobs'
  import OrderTerm from '@/types/OrderItems'
  import JobList from '@/components/JobList.vue'
  export default defineComponent({
    name: 'App',
    components: { JobList },
    setup() {

      const jobs = ref<Job[]>([
        { title: 'React developer', location: 'New York', salary: 30000, id: '1' },
        { title: 'Nodejs developer', location: 'London', salary: 40000, id: '2' },
        { title: 'Flutter developer', location: 'Lagos', salary: 35000, id: '3' },
        { title: 'Vuejs developer', location: 'Boston', salary: 21000, id: '4' },
        { title: 'Svelte developer', location: 'San Francisco', salary: 32000, id: '5' }
      ])
      const order = ref<OrderTerm>('title')
      const handleClick = (term: OrderTerm) => order.value = term
      return { jobs, order, handleClick }
    }
  });
</script>
<style>
  header {
    text-align: center;
  }
  header .order {
    margin-top: 20px;
  }
  button {
    margin: 0 10px;
    color: #1195c9;
    border: 3px solid #1195c9;
    background: #d5f0ff;
    padding: 8px 16px;
    border-radius: 4px;
    cursor: pointer;
    font-weight: bold;
  }
  header .title{
    display: flex;
    justify-content: center;
  }
  header img {
    width: 60px;
    margin-right: 20px;
  }
  header h1 {
    font-size: 3em;
  }
</style>

在上面的代码中,我们通过使用 [defineComponent](https://v3.vuejs.org/guide/typescript-support.html#defining-vue-components)全局方法。这使得TypeScript能够正确地对我们Vue组件内的代码进行类型检查。

另外,我们使用JobList 组件渲染我们的工作列表,所以让我们创建该组件。删除组件目录中的文件,在里面创建一个JobList.vue 文件。在JobList.vue 文件中添加以下代码。

<template>
  <div class="job-list">
    <p>Ordered by {{ order }}</p>
    <transition-group name="list" tag="ul">
      <li v-for="job in orderedJobs" :key="job.id">
        <h2>{{ job.title }} in {{ job.location }}</h2>
        <div class="salary">
          <p>{{ job.salary }} rupees</p>
        </div>
        <div class="description">
          <p>Lorem ipsum dolor sit amet consectetur, adipisicing elit. Rem omnis voluptatum eius doloremque optio iusto sequi dignissimos. Pariatur earum assumenda dolores possimus quidem quam, reprehenderit aliquid consequuntur amet non facere.</p>
        </div>
      </li>
    </transition-group>
  </div>
</template>

<script lang="ts">
  import { defineComponent, PropType, computed } from '@nuxtjs/composition-api'
  import Job from '@/types/Jobs'
  import OrderTerm from '@/types/OrderItems'

  export default defineComponent({
    props: {
      jobs: {
        type: Array as PropType<Job[]>,
        required: true
      },
      order: {
        type: String as PropType<OrderTerm>,
        required: true
      }
    },
    setup(props) {
      const orderedJobs = computed(() => {
        return [...props.jobs].sort((a: Job, b: Job) => {
          return a[props.order] > b[props.order] ? 1 : -1
        })
      })
      return { orderedJobs }
    },
  })
</script>
<style scoped>
  .job-list {
    max-width: 960px;
    margin: 40px auto;
  }
  .job-list ul {
    padding: 0
  }
  .job-list li {
    list-style-type: none;
    background: white;
    padding: 16px;
    margin: 16px 0;
     border: 2px solid #1195c9;
    border-radius: 4px;
  }
  .job-list h2 {
    margin: 0 0 10px;
    text-transform: capitalize;
  }
  .salary {
    display: flex;
  }
  .salary img {
    width: 30px;
  }
  .salary p {
    color: #17bf66;
    font-weight: bold;
    margin: 10px 4px;
  }
  .list-move {
    transition: all 1s;
  }
</style>

我们上面的JobList 组件需要两个required 道具,即jobsorder 。而我们使用类型断言指定了这些道具的types 。类型断言是TypeScript的一个功能,它使我们能够在TypeScript无法推断出正确类型的情况下指定类型。正如在我们上面的组件中看到的,jobs 道具是一个Jobs 的数组,而order 道具是一个OrderItem 的数组。

所以,通过使用propTypes 和泛型,我们使用类型断言指定了正确的道具类型。

最后,我们有了。

Job Search Board Demo

结论

Nuxt是一个伟大的框架,开箱即用,功能丰富,提供了很多帮助,使开发者的生活更轻松。

另一方面,TypeScript可以帮助开发者在开发过程中捕捉到错误,这些错误对开发者的经验和整个软件质量都有好处。

Composition API是一个新的API概念,用于编写Vue组件。虽然Composition API并没有废除Options API,但它是构建大型应用程序的首选,因为在这种情况下,共享和重用代码是一个重要的问题。

我希望在阅读完这篇文章后,你已经学到了足够的知识,可以开始在你的项目中使用这三个工具。如果你对源代码感兴趣,你可以在GitHub上获得我们应用程序的完整代码。

The postScaffolding an app with Vue 3, Nuxt, and TypeScriptappeared first onLogRocket Blog.