Featured image of post Nuxt 学习之旅 1

Nuxt 学习之旅 1

文章在个人网站中发布,原文链接:Nuxt学习之旅1

前言

在AI时代的冲击下,单纯的切图仔或者会一点前端工程化和系统化,已经不是什么值钱的技能了。
为了不被时代滚滚的车轮轧到,决心趁着年轻学习一点全栈技术。而且目前中文Nuxt的教程还是较少的,所以就有了这套帖子,自己学习,也是帮助后来人少走弯路。

安装Nuxt

我就直接使用WebStorm来建立项目了,作为初学者便利性和少踩坑还是应该在首位的。
当然使用其它IDE建立项目也很简单,如下的命令就是使用当前最新nuxt版本创建项目:

1
npm create nuxt@latest 你的项目名称

之后的流程无论使用什么IDE都一样,Nuxt会启动一个交互式的配置流程,完成之后就可以使用npm run dev启动开发服务器了。

1
npm run dev

然后,咱们的第一个Nuxt项目就启动了!

一个全新的Nuxt项目截图

约定大于配置

Nuxt有个特点就是约定大于配置,理论上我们无需编写任何配置文件,Nuxt会按照约定来工作。例如我们无需配置路由,直接在pages目录下创建文件,Nuxt会自动识别并创建对应的路由。
现在我们来尝试添加一个login页面:

建立页面

我们在先app目录下建立一个pages目录,新建一个app/pages/index.vue,然后再建立app/pages/login.vue,并写上相应的内容。此时如果我们删掉app.vue,Nuxt就会把index.vue作为首页渲染出来了。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
<script lang="ts">
import {defineComponent} from 'vue'

export default defineComponent({
  name: "index"
})
</script>

<template>
  <div>
    <!--  Nuxt用于页面跳转  -->
    <NuxtLink to="/login">前往登录页</NuxtLink>
    <h2>我是首页</h2>
  </div>
</template>

<style scoped>

</style>

默认布局

app.vue是什么呢?他是我们的默认布局文件,也就是所有页面的父组件,我们把它删掉,Nuxt就会按照约定渲染index.vue。不过我们现在先把它加回来并编写一点布局:

1
2
3
4
5
6
7
8
<template>
  <div>
    <!--  app.vue是Nuxt约定的入口  -->
    <h1>这里是默认布局哦</h1>
    <!--  NuxtPage可以渲染下一级路由的内容  -->
    <NuxtPage />
  </div>
</template>

Nuxt发现app.vue存在就会使用它来渲染index.vue作为首页,现在我们的页面和项目结构就变成了这样:

项目结构截图

建立网络接口

Nuxt的网络接口也是约定式的,使用js语言来编写,对于咱们前端十分友好。
我们在项目根目录下建立一个server目录(注意不是app目录下),然后建立server/api/hello.ts文件。那么Nuxt就会自动创建/api/hello的接口。
我们写一个简单的接口用来计算两个数字的和:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
export default defineEventHandler((event) => {
    // 获取路由参数num1和num2
    const query = getQuery(event)
    const num1 = Number(query.num1)
    const num2 = Number(query.num2)
    if(isNaN(num1) || isNaN(num2)) {
        // 如果参数不是数字,抛出错误
        throw createError({
            status: 500,
            statusText: "Invalid query number",
        })
    }else{
        // 返回计算结果
        return num1 + num2
    }
})

前端使用接口

我们在app/pages/index.vue中调用这个接口试试看,这些代码乍一看可能难以理解,在后边我会分开解释。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<script lang="ts">
import {defineComponent} from 'vue'

export default defineComponent({
  name: "index",
  data(): any{
    // 此处的数据由服务器处理完毕后将会随页面一起携带至前端
    return {
      result: 0,
      num1: 0,
      num2: 0,
    }
  },
  created(): any {
    // 这部分代码在服务器上执行
    const route = useRoute()
    if(route.query.num1){ this.num1 = route.query.num1 }
    if(route.query.num2){ this.num2 = route.query.num2 }
    const data = useFetch('/api/hello',{
      query: { num1: this.num1, num2: this.num2 }
    })
    this.result = data.data
  },
  methods: {
    // 这里的代码在浏览器执行
    async plus(){
      this.result = await $fetch('/api/hello',{
        query: { num1: this.num1, num2: this.num2 }
      })
    }
  }
})
</script>

<template>
  <div>
    <!--  Nuxt用于页面跳转  -->
    <NuxtLink to="/login">前往登录页</NuxtLink>
    <h2>我是首页</h2>
    <input v-model="num1"/> + <input v-model="num2"/> = {{result}}
    <button @click="plus">计算</button>
  </div>
</template>

<style scoped>

</style>

我们先看服务器上处理的这部分:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
    // 这部分代码在服务器上执行
    // useRoute()可以获得路由参数,我们从这里获取num1和num2参数
    const route = useRoute()
    if(route.query.num1){ this.num1 = route.query.num1 }
    if(route.query.num2){ this.num2 = route.query.num2 }
    // useFetch()用于在服务器内部调用接口
    const data = useFetch('/api/hello',{
      query: { num1: this.num1, num2: this.num2 }
    })
    // 给data赋值,nuxt将会将它渲染到页面上
    this.result = data.data

在Nuxt中,beforeCreatecreated两个生命周期是在服务器上被运行的。我们可以像php那样预先在服务器组装好页面。

服务器返回的页面是已经渲染好的内容

可以看到,我们带参数访问页面时,服务器直接返回了计算好结果的页面,而不是SPA那样先获取一个空页面再填充数据。

然后再看浏览器端的代码:

1
2
3
4
5
6
7
8
9
methods: {
    // 这里的代码在浏览器执行
    async plus(){
      // $fetch()是Nuxt提供的数据请求函数
      this.result = await $fetch('/api/hello',{
        query: { num1: this.num1, num2: this.num2 }
      })
    }
  }

这就和SPA没有区别了,将这个方法绑定到按钮上,就会在浏览器发起网络请求。

浏览器发起网络请求

小结

我们今天新建并体验了一把Nuxt。
创建了两个页面和一个接口,并且在前后端分别使用了它。了解了Nuxt强大的服务端渲染能力,前后端无缝连接。

Licensed under CC BY-NC-SA 4.0
最后更新于 Apr 06, 2026 00:00 UTC