Nuxt3稳定版+naive-ui项目开发
nuxt3在2022-11-16发布了稳定版本,网上很多资料的nuxt版本和其他插件或者ui框架的使用都不匹配,踩坑中,欢迎指正,不胜感激,让我们开始把。
nuxt3安装
按照官网,已安装node,vscode情况下
1.终端里cd进你想要的文件夹, 执行npx nuxi init ;(输入项目名称)
2. 再执行code ,就会在vscode里打开项目
3. 执行npm install安装依赖;
4. npm run dev就启动好项目了;
创建目录结构
1.pages放vue文件,列如index.vue,aboutUs.vue等等 app.vue改为NuxtPage,就能看到你index里的内容了
<template>
<div>
<NuxtPage />
</div>
</template>
2.assets
3.components公共组件
4.composables做数据的共享和一些公共的方法,在vue文件里不用引入,nuxt会自动引入;我这里做了api的管理,在该文件夹下新建index.ts文件,如下
import Http from '@/utils/request'
// 首页
export const getIndexInfo = (params: any) => {
return Http.get('/xxx/xxx', params) //接口路径
}
在页面使用
<template>
<div>
<h1>Welcome to the homepage</h1>
</div>
</template>
<script lang="ts" setup>
const info = await getIndexInfo ({
})
console.log('info', info)
</script>
5.layouts 布局,增加default.vue,app.vue里用NuxtLayout ,就会给整个网站加上同样的布局了
// default.vue
<template>
<div>
<Header/>
<div class="main">
<slot />
</div>
<Footer/>
</div>
</template>
//app.vue
<template>
<div class="text-base">
<NuxtLayout>
<NuxtPage />
</NuxtLayout>
</div>
</template>
<script lang="ts" setup>
</script>
某个页面不需要公共布局,或者想要指定其他布局方式,在页面通过definePageMeta设置
<script setup lang="ts">
// This will work in both `<script setup>` and `<script>`
definePageMeta({
layout: false
})
// 或者
definePageMeta({
layout: "custom",
});
</script>
6.middleware中间件,可以做 页面的登录校验。在下面新建auth.ts.通过cookie里的信息判断用户是否登录,没有登录则把to的fullpath保存下来,并且跳到登录页面,登录完成后跳转到刚刚保存的fullPath
export default defineNuxtRouteMiddleware((to, from) => {
console.log('to', to)
const origin_path = useCookie('origin_path', {})
const userInfo = useCookie('userInfo')
})
7.pugins插件,需要客户端渲染的插件命名为xxx.client.ts。跟纯vue项目使用插件有点类似,安装插件之后,在plugins建相关插件名的ts文件,import进去,vue是直接挂载到vue实例上,nuxt是通过nuxtApp.vueApp。以vue3-video-play为例:
import vue3videoPlay from "vue3-video-play"; // 引入组件
import "vue3-video-play/dist/style.css"; // 引入css
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.use(vue3videoPlay)
})
8.public 我目前用来放了favicon.icon。在nuxt.config.ts文件下,通过app.head.link配置。
4.utils放了封装的数据请求,新建request.ts。。。。key值要有,不然接口只会返回请求的第一个接口的数据。在用户操作调接口的地方,可以传入时间戳作为key值,比如登录,发送验证码等
import {
hash } from 'ohash'
export interface ResOptions<T> {
data?: T
success?: boolean
message?: string
}
const fetch = (url: string, options?: any): Promise<any> => {
const {
public: {
apiBase } } = useRuntimeConfig()
const reqUrl = apiBase + url // 你的接口地址
const key = options?.key ? options?.key : hash(JSON.stringify(options) + url)
const cookie = useCookie('userInfo')
return new Promise(async (resolve, reject) => {
useFetch(reqUrl, {
...options,
lazy: true,
headers: {
Authorization: 'Bearer' + ' ' + cookie['_rawValue']['token']
},
key,
})
.then(({
data, error }) => {
console.log('then', data)
if (error.value) {
reject(error.value)
return
}
const value: any = data.value
if (value['success'] !== true) {
//这里根据自己项目后端返回的数据做处理
if (value.data?.status === 401) {
cookie.value = ''
navigateTo('/login')
}
// 这里处理错误回调
// $message.error(value.message)
// 或者页面接口请求处catch
reject(value)
} else {
resolve(value['data'])
}
}).catch((err: any) => {
reject(err)
})
})
}
export default new class Http {
get(url: string, params?: any): Promise<any> {
return fetch(url, {
method: 'get', params })
}
post(url: string, body?: any): Promise<any> {
return fetch(url, {
method: 'post', body })
}
put(url: string, body?: any): Promise<any> {
return fetch(url, {
method: 'put', body })
}
delete(url: string, body?: any): Promise<any> {
return fetch(url, {
method: 'delete', body })
}
}
5.env环境变量
加了环境变量后,需要在package.json里加入命令行启动的对应的环境
"scripts": {
"build": "nuxt build --mode production",
"dev": "nuxt dev --mode development",
"generate": "nuxt generate --mode production",
"preview": "nuxt preview --mode production",
"postinstall": "nuxt prepare --mode production"
},
每个文件下都跟其他博主的差不多,就不一一赘述了. 环境加好了,还需要在nuxt.config.ts里配置
nuxt.config.ts配置
// https://nuxt.com/docs/api/configuration/nuxt-config
import {
loadEnv } from 'vite'
interface VITE_ENV_CONFIG {
VITE_APP_BASE_API: string,
}
const envScript = process.env.npm_lifecycle_script.split(' ')
const envName = envScript[envScript.length - 1] // 通过启动命令区分环境
const envData = loadEnv(envName, 'env') as unknown as VITE_ENV_CONFIG
console.log('当前环境:', envData)
export default defineNuxtConfig({
app: {
head: {
title: 'jjjjj',
meta: [
{
charset: 'utf-8' },
{
name: 'keywords', content: "xxx" },
{
name: 'description', content: "xxx" },
],
script: [
{
src: 'http://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js' }
],
}
},
runtimeConfig: {
// The private keys which are only available server-side
// apiSecret: '123',
// Keys within public are also exposed client-side
public: {
apiBase: envData.VITE_APP_BASE_API //把当前的环境变量设置到apiBase,这里和rc版本有点不一样
}
},
build: {
transpile:
process.env.NODE_ENV === 'production'
? [
'naive-ui',
'vueuc',
'@css-render/vue3-ssr',
'@juggle/resize-observer'
]
: ['@juggle/resize-observer']
},
vite: {
envDir: '~/env', // 指定env文件夹
optimizeDeps: {
include:
process.env.NODE_ENV === 'development'
? ['naive-ui', 'vueuc', 'date-fns-tz/esm/formatInTimeZone']
: []
}
}
})
naive-ui安装
看到这个ui框架觉得很是喜欢,有我想要的效果。安装按照官方的说明,安装,配置即可。在plugins下加入插件的时候有ts报错,最后修改如下(第一次接触ts,欢迎指正)
import {
setup } from '@css-render/vue3-ssr'
export default defineNuxtPlugin((nuxtApp) => {
if (process.server) {
const {
collect } = setup(nuxtApp.vueApp)
const originalRenderMeta = nuxtApp.ssrContext?.renderMeta
nuxtApp.ssrContext = nuxtApp.ssrContext // 这两行不一样,我没有把空对象赋值上去
if (nuxtApp.ssrContext) {
// 加了一个nuxtApp.ssrContext有值的判断
nuxtApp.ssrContext.renderMeta = () => {
if (!originalRenderMeta) {
return {
headTags: collect()
}
}
const originalMeta = originalRenderMeta()
if ('then' in originalMeta) {
return originalMeta.then((resolvedOriginalMeta) => {
return {
...resolvedOriginalMeta,
headTags: resolvedOriginalMeta['headTags'] + collect()
}
})
} else {
return {
...originalMeta,
headTags: originalMeta['headTags'] + collect()
}
}
}
}
}
})
naive-ui的使用
像message组件,dialog等组件,要在app.vue用相应的provider组件包裹起来
<template>
<NMessageProvider>
<NDialogProvider>
<div>
<NuxtPage />
</div>
</NDialogProvider>
</NMessageProvider>
</template>
<script lang="ts" setup>
import {
NMessageProvider,
NDialogProvider
} from 'naive-ui'
</script>
在pages下使用
<template>
<div>
<h1>Welcome to the homepage</h1>
<NButton @click="cb1">useMessage</NButton>
<NButton @click="cb2">useDialog</NButton>
<NNumberAnimation ref="numberAnimationInstRef" :from="0" :to="12039" />
</div>
</template>
<script lang="ts" setup>
import {
useMessage,
useDialog
} from 'naive-ui'
const message = useMessage()
const dialog = useDialog()
const cb1 = () => {
message.info('message')
}
const cb2 = () => {
dialog.info({
title: 'dialog',
content: '消息消息',
positiveText: '确定',
onPositiveClick: () => {
message.success('我就知道')
}
})
}
</script>
都看到这里了,点个赞把【笔芯】!一直在踩坑中,如有错误,感谢您指正,或者您可以给一些建议。
快要新的一年了,希望大家都身体健康,早日升职加薪!!!!