关键概念
导入功能的提升
Components 文件夹组件自动导入
- 在 Nuxt 中,你可以在 components/ 目录中创建这些组件,它们将自动在整个应用程序中可用,无需显式地导入。
Auto-imports 自动导入(响应式 API、生命周期)
1
2
3
4
5
|
<script setup lang="ts">
/* ref() and computed() are auto-imported */
const count = ref(1)
const double = computed(() => count.value * 2)
</script>
|
Built-in Auto-imports 内置自动导入
1
2
3
|
<script setup lang="ts">
/* useFetch() is auto-imported */ const {(data, refresh, status)} = await useFetch('/api/hello')
</script>
|
Vue.js 路由
1. 通过pages/
每个组件生成路由
1
2
3
4
5
|
-| pages/
---| about.vue
---| index.vue
---| posts/
-----| [id].vue
|
2. <NuxtLink>
标签进行路由跳转
1
2
3
4
5
6
7
8
9
10
11
|
<template>
<header>
<nav>
<ul>
<li><NuxtLink to="/about">About</NuxtLink></li>
<li><NuxtLink to="/posts/1">Post 1</NuxtLink></li>
<li><NuxtLink to="/posts/2">Post 2</NuxtLink></li>
</ul>
</nav>
</header>
</template>
|
3. Route Parameters 路由参数
1
2
3
4
|
<script setup lang="ts">
const route = useRoute() // When accessing /posts/1, route.params.id will be 1
console.log(route.params.id)
</script>
|
4. Route Middleware 路由中间件
- 导航到特定路由之前提取要运行的代码
- 路由中间件在 Nuxt 应用程序的 Vue 部分运行。尽管名称相似,但它们与服务器中间件完全不同,后者在应用程序的 Nitro 服务器部分运行。
1
2
3
4
5
6
|
export default defineNuxtRouteMiddleware((to, from) => {
// isAuthenticated() is an example method verifying if a user is authenticated
if (isAuthenticated() === false) {
return navigateTo("/login");
}
});
|
1
2
3
4
5
6
7
8
9
|
<script setup lang="ts">
definePageMeta({
middleware: "auth",
});
</script>
<template>
<h1>Welcome to your dashboard</h1>
</template>
|
5. Route Validation 路由验证
- Nuxt 通过你想要验证的每个页面中
definePageMeta()
中的 validate
属性提供路由验证。
validate
属性接受路由
作为参数。您可以返回一个布尔值,以确定这是否是要使用此页面呈现的有效路由。如果返回 false
,但找不到其他匹配项,则会导致 404 错误。您也可以直接返回带有 statusCode
/statusMessage
的对象,以立即响应错误(不会检查其他匹配项)。
1
2
3
4
5
6
7
8
|
<script setup lang="ts">
definePageMeta({
validate: async (route) => {
// Check if the id is made up of digits
return typeof route.params.id === 'string' && /^\d+$/.test(route.params.id)
}
})
</script>
|
Rendering Modes 渲染模式
- 浏览器和服务器都可以解释 JavaScript 代码,以将 Vue.js 组件转换为 HTML 元素。此步骤称为 渲染 。
- 默认情况下,Nuxt 使用通用渲染来提供更好的用户体验、性能并优化搜索引擎索引,但您可以在一行配置中切换渲染模式。
关于服务端渲染和客户端渲染的一个bug,使用setInterval计时器,服务端报错500
1
2
3
|
setInterval(() => {
request()
}, 3000);
|
1. 问题分析
当你在 Nuxt 的组件或页面中直接使用 setInterval 时,这段代码会在服务端渲染阶段被执行。然而,setInterval 是浏览器环境中的 API,在服务端(Node.js)环境中会报错,提示类似以下内容:
1
|
ReferenceError: setInterval is not defined
|
2. 解决方案
-
使用 process.client
判断是否在客户端运行
nuxt 提供了 process.client
变量,用于判断当前代码是否在浏览器环境中运行。你可以通过这个变量确保 setInterval
只在客户端执行。
1
2
3
4
5
6
7
8
9
10
11
|
// 确保 setInterval 只在客户端运行
if (process.client) {
const intervalId = setInterval(() => {
loadData()
}, 3000)
// 组件销毁时清除计时器,防止内存泄漏
onUnmounted(() => {
clearInterval(intervalId)
})
}
|
-
将计时器逻辑放在 mounted
生命周期钩子中
在 Vue.js 中,mounted
钩子只会在客户端渲染完成后执行,因此可以将计时器逻辑放在这里。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
export default {
mounted() {
this.interval = setInterval(() => {
this.loadData();
}, 3000);
},
beforeDestroy() {
// 清除计时器,防止内存泄漏
clearInterval(this.interval);
},
methods: {
loadData() {
console.log('加载数据...');
}
}
};
|
什么是服务器渲染的,什么是客户端渲染的?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
<script setup lang="ts">
const counter = ref(0); // executes in server and client environments
const handleClick = () => {
counter.value++; // executes only in a client environment
};
</script>
<template>
<div>
<p>Count: {{ counter }}</p>
<button @click="handleClick">Increment</button>
</div>
</template>
|
在初始请求中,计数器 ref 在服务器中初始化,因为它呈现在 <p>
标记内。handleClick 的内容在此处永远不会执行。在浏览器中激活期间,counter ref 会重新初始化。handleClick 最终将自身绑定到按钮;因此,可以合理地推断 handleClick 的主体将始终在浏览器环境中运行。
Universal Rendering 通用渲染
原理
- 当浏览器请求启用了通用渲染的 URL 时,Nuxt 会在服务器环境中运行 JavaScript (Vue.js) 代码,并将完全渲染的 HTML 页面返回给浏览器。如果页面是提前生成的,Nuxt 也可以从缓存中返回完全渲染的 HTML 页面。用户会立即获得应用程序的全部初始内容,这与客户端渲染相反。
- 下载 HTML 文档后,浏览器会解释此内容,Vue.js 将控制该文档。曾经在服务器上运行的相同 JavaScript 代码再次在客户端(浏览器)上运行,现在通过将其侦听器绑定到 HTML 来启用交互性(因此是通用渲染)。
效果
- 通用渲染允许 Nuxt 应用程序提供快速的页面加载时间,同时保留客户端渲染的优势。此外,由于内容已经存在于 HTML 文档中,因此爬网程序可以毫无开销地为其编制索引。
- 通用渲染用途广泛,几乎可以适应任何用例,特别适用于任何面向内容的网站:博客、营销网站、投资组合、电子商务网站和市场。
1. 服务器端渲染(SSR)
-
概念:
- 在 SSR 模式下,页面的 HTML 内容是在服务器端动态生成的,然后发送到客户端。客户端接收到 HTML 后,再通过 JavaScript 进行进一步的交互。
- SSR 是 Nuxt 3 的默认渲染模式,适合需要 SEO 优化或需要快速首屏加载的应用。
-
好处
- 性能:用户可以立即访问页面的内容,因为浏览器显示静态内容的速度比 JavaScript 生成的内容快得多。同时,Nuxt 在水合过程中保留了 Web 应用程序的交互性。
- 搜索引擎优化:通用渲染将页面的整个 HTML 内容作为经典服务器应用程序交付给浏览器。Web 爬虫可以直接为页面的内容编制索引,这使得 Universal rendering 成为您想要快速编制索引的任何内容的绝佳选择。
-
缺点
- 开发约束:服务器和浏览器环境不提供相同的 API,因此编写可以在两端无缝运行的代码可能很棘手。幸运的是,Nuxt 提供了指南和特定变量来帮助您确定一段代码的执行位置。
- 成本:需要运行服务器才能动态呈现页面。这会增加每月成本,就像任何传统服务器一样。但是,由于浏览器接管了客户端导航的通用渲染,服务器调用大大减少了。利用 edge-side 渲染可以降低成本。
2. 静态站点生成(Static Site Generation, SSG)
- 在 SSG 模式下,页面的 HTML 是在构建时预先生成的,并作为静态文件部署到服务器。这些静态页面可以在没有服务器端逻辑的情况下直接被客户端加载。
- SSG 适合内容不经常更新的网站,如博客或文档网站。
3. 单页应用(Single Page Application, SPA)
- 在 SPA 模式下,页面的 HTML 是在客户端动态生成的,服务器只提供一个初始的 HTML 模板和必要的 JavaScript 文件。
- SPA 适合对交互性要求较高的应用,但可能对 SEO 不太友好。
Client-Side Rendering 客户端渲染
相较于通用渲染相反,不做过多叙述
- 好处
- 开发速度:不考虑服务器的兼容性
- 便宜: 不考虑服务器基础设施成本
- 离线: 在 Internet 不可用时很好地保持工作
- 缺点
- 性能: 需等待浏览器下载、解析、运行js,响应长,影响用户体验
- 搜索引擎优化: 索引和更新通过客户端渲染交付的内容需要更多时间。不利于引擎爬虫。
- 您可以在 nuxt.config.ts中使用 Nuxt 启用仅客户端渲染:
1
2
3
|
export default defineNuxtConfig({
ssr: false
})
|
:warning: 如果你确实使用 ssr: false
,你还应该放置一个 HTML 文件, ~/app/spa-loading-template.html
其中包含一些你想用来渲染加载屏幕的 HTML,该屏幕将一直呈现,直到你的应用程序被激活。
Deploying a Static Client-Rendered App部署静态客户端呈现的应用程序
Hybrid Rendering 混合渲染
Route Rules 路由规则
Edge-Side Rendering 边侧渲染
Nuxt的Server层服务
通过defineEventHandler()
定义接口
server文件夹下定义接 名字channel.get.ts
,默认get接口
1
2
3
4
5
6
7
|
// server
// - /api
// - channel.get.ts
import channel from "~/database/channel" //channel 是database定义的默认数据
export default defineEventHandler(()=>{
return channel
})
|
使用useFetch()调用接口
1
2
3
|
// 无需导入
// 解构-重命名
const {data:channelList} =await useFetch('/api/channel')
|
我写过的项目的写法的记录
1
2
3
4
5
6
7
8
9
10
11
12
13
|
import { API_HOT_CATEGORY_LIST } from '~/api/category'
import { nodeFetch } from '~/server/utils/handle'
export default defineEventHandler(async (event) => {
const body = await readBody(event)
const data = await nodeFetch(API_HOT_CATEGORY_LIST, { body, nitroEvent: event })
return {
data,
status: 0,
info: 'ok',
}
})
|