Nuxt3稳定版+naive-ui项目开发

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>

都看到这里了,点个赞把【笔芯】!一直在踩坑中,如有错误,感谢您指正,或者您可以给一些建议。
快要新的一年了,希望大家都身体健康,早日升职加薪!!!!

猜你喜欢

转载自blog.csdn.net/qq_38661597/article/details/128469611