Nuxt特点
- 自动化
- 自动导入 (文件系统自动配置路由)
- 零配置支持Typescript
- 配置构建工具
- 渲染模式 - 通用渲染(服务器端渲染和水化渲染) - 客户端渲染 - 完整的静态站点生成 - 混合渲染(每个路由的缓存策略) PS:虽然很便捷,但是很多坑
Nuxt基础配置模板地址 https://github.com/Seven7v/Nuxt3-vue3-project
代码语言:txt复制git clone https://github.com/Seven7v/Nuxt3-vue3-project.git
首先安装一个Nuxt项目
代码语言:txt复制npx nuxi@latest init may-app // my-app你的项目名称
安装成功 就是我们的基本运行项目工作
代码语言:txt复制cd my-app
代码语言:txt复制npm i
代码语言:txt复制npm run dev
package.json 命令
生成的项目中,package.json中自动生成了几个命令
npm run build
生成的是/.mjs
文件,不是之前vue项目生成的静态文件,需要将生成的sever部署需要在node环境下部署,普通环境无法运行
"scripts": {
"build": "nuxt build", // 生成环境,同构渲染
"dev": "nuxt dev", // 开发者环境,支持同构渲染
"generate": "nuxt generate", // 生成静态资源,在output中的public文件夹中
"preview": "nuxt preview", // build 命令后可以可以启动一个node服务来运行生成的文件
"postinstall": "nuxt prepare"
},
Nutx的自动化
入口文件为app.vue
pages
首先手动创建一个pages文件夹,用来存放项目页面。
poges 文件夹中的页面会自动配置好页面路由。
代码语言:txt复制|- pages
|-- home.vue
同理 如果 是这样的目录结构,/home
路由也可以加载index.vue中的内容
|- pages
|-- home
|-- index.vue
app.js
增加<NuxtPage>
组件,与vue-router中的<router-view>
功能一致
<template>
<div>
<NuxtPage></NuxtPage>
</div>
</template>
这里通过localhost:3000/home
就可以直接访问home页面
components
创建components文件夹 ,用来存放组件内容
components文件夹内的组件会自动注册,不需要使用import导入
代码语言:txt复制|- components
|-- Header.vue
app.js
中直接使用<Header/>
<template>
<div>
<Header/>
<NuxtPage></NuxtPage>
</div>
</template>
此时Header的组件内容也会显示出来
layouts
创建layouts
文件夹,并创建default.vue
|- layouts
|-- default.vue
|-- notab.vue
default.vue
中加入<NuxtPage>和刚刚完成的组件
<template>
<div>
<Header />
<NuxtPage></NuxtPage>
<Tabbar />
</div>
</template>
app.js
中直接使用<NuxtLayout>
组件默认会将default中的内容展示出来
<template>
<div>
<NuxtLayout></NuxtLayout>
</div>
</template>
如果想展示notab页面中的布局 可以使用name属性
代码语言:txt复制<template>
<div>
<NuxtLayout name = "notab"></NuxtLayout>
</div>
</template>
这时页面可以切换布局
composables
composables文件夹下是公共函数,nuxt会自动加载里面的ts代码到页面使用,可以在里面写一些全局的方法。 文件名多用use
开头
|- composables
|-- useLang.ts
useLang.ts
export const useLang = () => useState("lang",()=>'zh-cn')
Nuxt 路由
基本路由
和vue-router
提供的router-link
相似,在Nuxt中使用路由跳转 使用组件<NuxtLink>
也可以使用 custom属性 定制生成的内容不是 <a> 标签
代码语言:txt复制 <!-- active-class="active" 给active class 设置样式,可以自动实现选中高亮 -->
<template>
<div class="mod-header">
<div>
<!-- 基本写法 -->
<NuxtLink to="/home" active-class="active">
Home
</NuxtLink>
<!-- 定制元素 -->
<!-- custom属性代表定制 -->
<NuxtLink custom v-slot="{isActive, href, navigate } " to="/home" active-class="active">
<h4 :href="href" @click="navigate" :class="isActive?'active':''">
Home
</h4>
</NuxtLink>
</div>
</div>
</template>
<!-- 如果想要使用scss 或者 less 预处理器需要额外安装 -->
<style lang="scss" scoped>
.active {
border-bottom: 2px solid #000;
}
</style>
路由下的子路由如/home/hot
可以有两种目录结构 (这里有个坑
|- pages
|-- home.vue
|-- home // 文件夹
|--hot.vue
这样的目录结构,hot.vue 相当于是home.vue的组件内容,可以在home.vue的<NuxtPage>显示,如果home.vue中不写<NuxtPage>, 跳转**/home/hot
** 不会显示页面内容
或者
代码语言:txt复制|- pages
|-- home
|-- index.vue
|-- hot.vue // 单独页面 不是组件内容
这样的目录结构,home 页面和hot页面时单独存在的,跳转**/home/hot
** 可以单独显示hot页面内容,在home 中 使用<NuxtPage> 无效
<NuxtLink to="/home/hot" >HOT</NuxtLink>
动态路由
涉及到详情页路由,如/detial/idxxxxx
格式的路由目录格式
|- pages
|-- detail
|-- [id].vue
如果访问 /detail/9527
后面跟任何ID都可以显示当前页面
[id].vue
获取参数
<script setup lang="ts">
const route = useRoute() // 可以直接使用,不需要导入
console.log(route.params) // route.params 中就是我们传递过来的内容 { id : '9527 '}
</script>
使用 路由的跳转方法router.push
不需要先导入useRouter ,可以直接在页面中使用
<script setup lang="ts">
const router = useRouter() // 可以直接使用,不需要导入
const handleToDetail = (id: number) => {
router.push(`/detail/${id}`)
}
</script>
路由中间件
这里有关于页面路由配置的写法,但是并不详细
内联配置
代码语言:txt复制<!-- 对单页面的路由守卫 -->
<script setup lang="ts">
definePageMeta({
middleware: (to, from) => {
if (!localStorage.getItem('token')) {
return navigateTo('/login') //一定要写return
}
}
})
</script>
命名中间件
如果多个页面需要配置守卫,可以将单页的内容 抽出
代码语言:txt复制|- middleware
|-- auth.ts // 中间件名称自定义
auth.ts
中写入
export default defineNuxtRouteMiddleware((to, from) => {
if (!localStorage.getItem('token')) {
return navigateTo('/login') //一定要写return
}
})
页面如果需要用到中间件的地方只需要配置,就可以实现导航守卫功能
代码语言:txt复制<script setup lang="ts">
definePageMeta({
middleware: 'auth'
})
</script>
全局中间件
代码语言:txt复制|- middleware
|-- auth.global.ts // 加上global后缀,默认全局中间件,进入所有路由都会通过这里
auth.global.ts
export default defineNuxtRouteMiddleware((to, from) => {
const limitList = ['/article', '/home', '/product'] // 配置适配 路由
if (limitList.includes(to.fullPath)) {
if (!localStorage.getItem('token')) { // !!!!这里有个大坑
return navigateTo('/login') //一定要写return
}
}
})
这样写如果从不做验证的页面进如,后跳转到**/home
**时完全没有问题的,但是如果,路由地址中直接写**/home
**回车,页面会加载不出来,提示500报错,没有localStorage。此时/home时首页,首页渲染时服务端返回,所以没有localStorage,可以将token 放到cookie中解决 ****
也可以使用 proess.server
来判断,此代码是否是在服务端 运行的,如果时true,可以做对应处理。
打印后,在启动项目的终端会打印出true
将token储存在cookie中,使用useCookie
useCookie
可以实现如下操作
if (process.server) {
// 从服务端的cookie中获取token
} else {
// js 使用从浏览器的cookie中获取token
}
从而可以写成,这样从/home
直接进入的话就不会报错了
export default defineNuxtRouteMiddleware((to, from) => {
const limitList = ['/article', '/home', '/product']
if (limitList.includes(to.fullPath)) {
const token = useCookie('token')
if (!token.value) {
return navigateTo('/login') //一定要写return
}
}
})
页面重定向
现在进入页面 直接加载会显示404,这时可以进行重定向
代码语言:txt复制|- middleware
|-- redirect.global.ts // 中间件名称自定义
代码语言:txt复制export default defineNuxtRouteMiddleware((to, from) => {
if (to.fullPath === '/') {
return navigateTo('/home')
}
})