Vue3 + Nuxt3 项目笔记
Vue3+Nuxt3在线教育项目笔记
1. 项目初始化
1.1 引入Nuxt3
初始化项目
1 |
|
运行项目
1 |
|
1.2 引入Naive-UI
参考官方文档服务端渲染SSR引入流程
安装
naive-ui
和@css-render/vue3-ssr
在
nuxt.config.ts
增添下列配置1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22// https://v3.nuxtjs.org/api/configuration/nuxt.config
export default defineNuxtConfig({
build: {
transpile:
process.env.NODE_ENV === 'production'
? [
'naive-ui',
'vueuc',
'@css-render/vue3-ssr',
'@juggle/resize-observer'
]
: ['@juggle/resize-observer']
},
vite: {
optimizeDeps: {
include:
process.env.NODE_ENV === 'development'
? ['naive-ui', 'vueuc', 'date-fns-tz/esm/formatInTimeZone']
: []
}
}
})在 Nuxt 项目的
plugins
文件夹增加这个插件
1.3 引入Windi CSS
安装
1
yarn add nuxt-windicss -D
在
nuxt.config.ts
增添下列配置1
2
3
4
5export default {
buildModules: [
'nuxt-windicss',
],
}
1.4 自定义全局错误页面
从naive-ui中复制错误模板页,拷贝到根目录的error.vue页面
1 |
|
1.5 自定义全局loading
在plugins中创建globalloading.js文件,在生命周期hook函数中加载loading条
loadingBar设置参考naive-ui的独立API设置
1 |
|
2. 全局Layout布局
2.1 主布局实现
修改app.vue页面,用NuxtLayout包裹NuxtPage,并禁用inline主题
1
2
3
4
5
6
7
8
9
10
11
12
13<template>
<NConfigProvider inline-theme-disabled>
<NuxtLayout>
<NuxtPage/>
</NuxtLayout>
</NConfigProvider>
</template>
<script setup>
import {
NConfigProvider
} from "naive-ui"
</script>根目录创建layouts文件夹,创建default.vue文件
1
2
3
4
5
6
7<template>
<div class="body">
<NavBar/>
<slot/>
<PageFooter/>
</div>
</template>根目录创建components文件夹,创建导航栏与页脚两个组件
2.2 引入全局css
保证每个页面的左右边距一致
在根目录下创建assets文件夹,创建main.css文件
1
2
3
4
5
6
7
8.container {
width: 100%;
max-width: 1140px;
padding-left: 15px;
padding-right: 15px;
margin-left: auto;
margin-right: auto;
}在nuxt.config.ts文件中引入css
1
2
3css: [
"@/assets/main.css"
],更改default.vue页面,加入container样式
1
2
3
4
5
6
7
8
9<template>
<div class="body">
<NavBar/>
<main class="container">
<slot/>
</main>
<PageFooter/>
</div>
</template>
2.3 引入图标库
安装图标
1
npm i -D @vicons/ionicons5
在vue中引入import
1
2
3
4
5
6
7
8<script setup>
import {
NIcon
} from "naive-ui"
import {
Search
} from "@vicons/ionicons5"
</script>
2.4 公共头部开发
修改components/NavBar组件,设置不同的css样式
左侧logo采用NButton制作
中间偏左为导航菜单栏
右侧为搜索与登陆按钮
- 搜索采用带图标的button组件
- 用户头像登陆按钮采用NDropdown组件
2.5 动态路由
动态路由跳转页面
1 |
|
在pages下创建页面时,需要遵循一定规则
- 带有中括号表示是动态路由
- menus中的path路径属性与pages中的文件目录及文件一一对应
2.6 组件封装
通过插槽slot代表需要存放的内容
通过defineProps定义组件中传递进来的参数
1
2
3
4
5
6defineProps({
active: {
type: Boolean,
default: false
}
})
2.7 引入Element-Plus以及图标库
安装相应库
1
npm install sass element-plus @element-plus/icons-vue unplugin-vue-components unplugin-auto-import --save
在assets/index.scss中加入如下内容,放置到首行
1
@use "element-plus/dist/index.css";
在plugins下创建
element-plus.client.js
文件1
2
3
4
5
6
7
8import * as ElementPlus from 'element-plus/dist/index.full'
import zhCn from 'element-plus/es/locale/lang/zh-cn'
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.use(ElementPlus, {
locale: zhCn,
})
})修改
nuxt.config.ts
如下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// https://v3.nuxtjs.org/api/configuration/nuxt.config
export default defineNuxtConfig({
css: [
'element-plus/dist/index.css',
"~/assets/main.scss"
],
modules: [
'nuxt-windicss',
],
build: {
transpile:
[
'naive-ui',
'vueuc',
'@css-render/vue3-ssr',
'@juggle/resize-observer',
"element-plus"
]
},
vite: {
optimizeDeps: {
include: ['date-fns-tz/esm/formatInTimeZone']
}
}
})在对应的vue中按需引入
1
2import { ElButton, ElIcon } from "element-plus";
import { Star } from "@element-plus/icons-vue";
3. 前后端数据交互
3.1 未封装前
采用useFetch方法调用接口
1 |
|
3.2 请求和响应拦截器封装
创建composables文件夹,在其中创建useHttp.js文件
1 |
|
4. 自定义全局方法
在plugins目录下新建tools.js文件
定义方法:commonOpen
1
2
3
4
5
6
7export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.provide("commonOpen", (item) => {
if(item.type == 'webview') {
window.open(item.url)
}
})
})调用:$开头
1
@click="$commonOpen(item)"
定义插件之后需要重启页面
5. 页面标题设置
全局标题:在nuxt.config.js中配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20app: {
head: {
titleTemplate: '%s - 帝莎编程', // 所有页面标题模板
title: '帝莎编程',
charset: 'utf-8',
htmlAttrs: {
lang: "zh-cn"
},
meta: [
{ name: 'description', content: '帝莎编程描述' },
{ name: 'keywords', content: '帝莎编程关键词' }
],
script: [
// { src: "http://xxx.js" }
],
link: [
// { rel: "stylesheet", href: "http://xxx.css" }
]
}
}页面标题:在对应的vue-script中配置
1
2
3useHead({
title: '帝莎编程首页'
})
6. 父子组件通信
6.1 父传子
父组件在子组件上标记ref
1
<SearchBar ref="SearchBarRef"></SearchBar>
父组件定义方法,调用子组件内的方法
1
2const SearchBarRef = ref(null)
const openSearch = () => SearchBarRef.value.open() // 按钮点击调用openSearch子组件定义被ref调用的方法
1
2
3
4const open = () => {
keyword.value = ""
drawer.value = true
}
注意:vue3内通过ref定义的const常量,需要通过.value获取值和修改值
7. 指定页面布局
某些页面不使用default布局,而是自定义另外的布局
在这些页面的script中加入:
1 |
|
8. CSS不可复制
1 |
|