使用Nuxt3版本的一些感悟("nuxt": "^3.2.3")
一些基本需要了解的例如
页面布局 layout文件夹 和根目录下的app.vue文件
基于文件的路由目录 pages文加载 路由嵌套 传参等
自定义的组件components文加载 (使用时无需引入 如果想关闭可在nuxt.config.ts关闭)
//如果你想关闭自动导入,你可以将 imports.autoImport设置为 false.
exportdefaultdefineNuxtConfig({
imports: {
autoImport: false
}
})
可组合式API Composables 文件夹 就是自定义一些自己的hooks
Nuxt 内置了一些 如 useCookie、useRoute、useRouter、useState、useHead、useFetch、、、具体官网查看
middleware中间件目录 像Vue3中我们做一些路由守卫 就可以在这里写
plugins插件目录 使用的一些第三方组件可以在此处使用
目前项目中使用到的只有这些 具体的使用和描述还是以官网为准 只是自己的一些见解。。。
当前项目目前使用的插件如下
"dependencies": {
"@ant-design/icons-vue": "^6.1.0",
"@pinia/nuxt": "^0.4.7",
"ant-design-vue": "^3.2.15",
"less": "^4.1.3",
"pinia": "^2.0.33",
"sass": "^1.59.3",
"vue-i18n": "^9.2.2"
}
1.安装ant-design-vue
Nuxt中使用第三方组件库需要在根目录下创建plugins文件夹,并在文件夹中创建自己的插件名称(无需在nuxt.config.ts 文件中引入 Nuxt2需要手动引入)
如在plugins文件夹下创建ant-design-vue.ts 文件 内容如下 可选择全局引入或者按需加载
// import Antd from 'ant-design-vue'; 全局引入
import { Button,Layout } from'ant-design-vue';
exportdefaultdefineNuxtPlugin((nuxtApp) => {
// nuxtApp.vueApp.use(Antd); 全局使用
nuxtApp.vueApp
.use(Button)
.use(Layout)
});
当引入完组件后 接下来引入样式 因为antd的样式使用了Less作为开发语言 所以这里我使用了less文件 需要下载less
当然你也可以使用css样式文件 引入样式文件(需要注意的是在这里引入的样式文件会全局加载)
在nuxt.config.ts 文件中
exportdefaultdefineNuxtConfig({
css:[
// 'ant-design-vue/dist/antd.min.css',
'ant-design-vue/dist/antd.less',
'@/assets/css/animate.min.css',
],
})
现在在页面中就可以使用组件了
<template>
<div>
<a-layout>
<a-layout-header>
Header 我是头部
<a-space>
<a-buttontype="primary">中文简体</a-button>
<a-buttontype="primary">英语</a-button>
</a-space>
</a-layout-header>
<a-layout-content>
Content 我是内容
</a-layout-content>
<a-layout-footer>Footer 我是底部</a-layout-footer>
</a-layout>
</div>
</template>
<scriptlang="ts"setup>
</script>
2.使用vue-i18n 首先安装
同样像使用ant-design-vue一样需要在plugins文件夹中注册
根目录下创建locales文件夹
locales
| - lang
| --- ZH //中文语言文件夹 在里面可以创建其他文件夹或者文件 我自己喜欢以路由为文件夹创建
| ----- app.ts
| --- zh.ts // 在这里引入上面中文里面ZH文件夹中所有的定义 同理下面EN文件夹也是如何 如果有第三个语言 也可以如此创建
| --- EN
| ----- app.ts
| --- en.ts
| - index.ts 引入文件 zh.ts en.ts 并且导出
以上面的中文为例
locales/lang/zh.ts
importappfrom'./ZH/app'
importpaymentfrom'./ZH/payment'//这里是我创建的一个文件夹 里面有一个index.ts文件
exportdefault {
...app,
...payment
}
locales/lang/ZH/app.ts
exportdefault {
app:{//自定义 例如 上面的payment文件夹的index 这里就可以使用文件夹的名称payment:{} 避免重复
title:'标题',
auth:'该页面需要登录请登录后重试'
}
}
locales/index.ts
importzhLocalefrom'./lang/zh'; //引入本地语言 locales/lang/zh.ts
importenLocalefrom'./lang/en'
let zh= {
...zhLocale,
}
let en= {
...enLocale,
}
export { zh,en }//导出
plugins文件夹中创建vue-i18n.ts 文件
import { createI18n } from'vue-i18n';
import { zh,en } from'@/locales/index';//本地语言库
constmessage= {
zh,
en,
}
exportdefaultdefineNuxtPlugin((nuxtApp) => {
constCookie=useCookie('lang');
//这里使用了内置api 可以快速设置获取cookie 当然这里也可以设置在localStorage中使用 不使用useCookie
Cookie.value=Cookie.value||'zh'
consti18n=createI18n({
legacy:false,//使用vue3组合式API时必须设置为FALSE
locale:Cookie.value||'zh',
fallbackLocale: 'zh', // set fallback locale
messages:message,
globalInjection:true,//全局注入$t函数
})
nuxtApp.vueApp.use(i18n)
});
接下来是语言切换
可以在任意的页面或者组建中进行语言的切换
<template>
<div>
<a-buttontype="primary"@click="switchLang('zh')">中文简体</a-button>
<a-buttontype="primary"@click="switchLang('en')">英语</a-button>
</div>
</template>
<scriptlang="ts"setup>
import { useI18n } from'vue-i18n';
const { locale:renameLocale } =useI18n();
constcurrentLang=useCookie('lang');//获取cookie中的lang
constswitchLang= (val:string)=>{
renameLocale.value=val;//本地使用的语言
currentLang.value=val;//更改cookie中的值
}
</script>
当完成以上的配置后 就可以在页面中使用了
使用的方法有两种 在页面中使用 和 在JS中使用。
<template>
<section>
<p>{{ $t('app.title') }}</p><!-- 标题 -->
</section>
</template>
<scriptlang="ts"setup>
import { useI18n } from'vue-i18n';
const { t } =useI18n();
console.log(t('app.title'))//标题
</script>
此时基本的操作就已经完成了 但是我们需要在页面初始化的时候就要确认使用的语言
然后结合ant-design-vue组件库国际化 按照官方文档配置
ant-design-vue 提供了一个 Vue 组件 ConfigProvider 用于全局配置国际化文案
在根目录下的app.vue文件中 当然别忘了plugins/ant-design-vue.ts 文件中引入该组价
<template>
<a-config-provider:locale="currentLang">
.........
</a-config-provider>
</template>
<scriptlang="ts"setup>
importzhfrom'ant-design-vue/es/locale/zh_CN';
importenfrom'ant-design-vue/es/locale/en_US';
importdayjsfrom'dayjs';
// ConfigProvider 不包含时间类组件的国际化,你需要额外引入时间库(dayjs、momentjs、date-fns 等)的国际化文件
import'dayjs/locale/zh-cn';
dayjs.locale('zh-cn');
constcurrentLang=ref(en) ;//zh en
</script>
但是这时候我们的antdesignvue不会随着我们切换语言而改变 因为切换按钮不在当前的app.vue文件内 如果在相同的页面的话现在可以创建响应性的数据currentLang直接使用,,但是真是的项目中切换语言的按钮往往只是一个单纯的切换不和其他的组件在一起
当我们点击切换按钮的时候 更改本地语言 并且更改cookie中的lang字段 此时app.vue如果能实时监控获取更改后的值 然后就可以改变currentLang的值
这里我是用的是pinia 像vuex一样pinia的数据也是响应性的
首先安装 pinia @pinia/nuxt
根目录下创建文件夹store 我这里创建了两个模块 方便以后数据的存储
store
| - modules
| --- app.ts
| --- user.ts
| - index.ts
store/index.ts
import {userStore} from'./modules/user';
import {appStore} from'./modules/app'
exportconstuseStore= ()=>({
userStore:userStore(),
appStore:appStore()
})
store/modules/app.ts
import { defineStore } from'pinia';
// defineStore 方法有两个参数,第一个参数是模块化名字
// 第二个参数是选项,对象里面有三个属性,相比于vuex 少了一个 mutations.
exportconstappStore=defineStore('app', {
state(){ // 存放的就是模块的变量
return {
lang:useCookie('lang') ||'zh',
}
},
getters:{
getStateLang(state){// 页面中使用了多次,这里只会执行一次,然后缓存起来
returnstate.lang?state.lang:'zh'
},
},
actions:{
changeLang(lang:string) {
this.lang=lang;
},
}
})
接下来更改app.vue中的代码
我们需要首次获取到当前本地cookie中的值 如果store获取不到默认zh
<template>
<a-config-provider:locale="currentLang">
.........
</a-config-provider>
</template>
<scriptlang="ts"setup>
importzhfrom'ant-design-vue/es/locale/zh_CN';
importenfrom'ant-design-vue/es/locale/en_US';
importdayjsfrom'dayjs';
import { useStore } from'@/store'
import { storeToRefs } from'pinia'
conststore=useStore();
//首次加载获取 默认zh
constcurrentLang=ref(switchLangFun(store.appStore.getStateLang))
//国际化时间组件
watch(currentLang, val=> {
dayjs.locale(val.locale);
});
//获取store中的语言 storeToRefs可以创建一个响应式的数据 具体使用方法还是需要官方文档
const { lang } =storeToRefs(store.appStore);
watch(lang,val=>{
if(val) currentLang.value=switchLangFun(val)
})
//本地cookie中的zh是字符串
functionswitchLangFun(val:string){
switch(val){
case'zh':
returnzh
case'en':
returnen
case'hk':
returnhk
case'ar':
returnar
default:
returnzh
}
}
</script>
到这里还有一个操作不要忘记 就是当我们点击切换的时候还要更改store中的lang的值
更改你刚才切换语言的组件
<template>
<div>
<a-buttontype="primary"@click="switchLang('zh')">中文简体</a-button>
<a-buttontype="primary"@click="switchLang('en')">英语</a-button>
</div>
</template>
<scriptlang="ts"setup>
import { useI18n } from'vue-i18n';
const { locale:renameLocale } =useI18n();
constcurrentLang=useCookie('lang');//获取cookie中的lang
constswitchLang= (val:string)=>{
renameLocale.value=val;//本地使用的语言
currentLang.value=val;//更改cookie中的值
//改变store
store.appStore.changeLang(val) ///changeLang为store中的actions方法
}
</script>
至此这个项目中使用vue-i18n 已经完成。。。。。。。
但是、、、、当我感觉一切都完成的时候 此时又发现一个问题
因为在vue的项目中难免会遇到路由守卫
通过对Nuxt的了解我们知道在Nuxt的项目中我们可以在middleware中间件中使用路由守卫。直接在middleware文件夹下创建文件即可。这里有全局的中间件和作用于文件的中间件 如何使用以官网为准
创建auth.global.ts文件 含有.global的文件即为全局中间件 创建这个中间件主要对页面需要token的页面进行拦截 如果不存在token则重定向login登录或者提示信息 (即使这个中间件不提示信息只做重定向 但是肯定会有别的中间件会提示信息进行拦截 比如某个页面需要一定的管理员权限才能进去 此时就不能重定向某个页面 只能提示然后终止导航)
auth.global.ts
import { messageasMessage,Modal } from'ant-design-vue'
import { useI18n } from'vue-i18n';
exportdefaultdefineNuxtRouteMiddleware((to, from) => {
if(process.client){//只在客户端显示 具体请以官网为准
const {t} =useI18n();
consttoken=useCookie('app-token');
//某些特定的页面不需要token login register reset
constnoTokenPath= ['/login','/register','/reset']
if(!noTokenPath.includes(to.path)){
if(!token.value){
// Message.error('This is an error message');
// return abortNavigation('500')
Modal.error({
title: 'Tip',
content: t('app.auth'),//该页面需要登录请登录后重试
});
}
}
}
})
因为提示的信息 肯定也是国际化的 按照正常的操作引入
import { useI18n } from 'vue-i18n';const { t } = useI18n();
但是当我们使用 t('app.auth') 系统就会报错 Must be called at the top of a setup function因为vue-i18n 必须在setup中使用。
这时候我们需要plugins插件的帮助
更改 plugins/vue-i18n.ts 文件
import { createI18n } from'vue-i18n';
import { zh,en } from'@/locales/index';//本地语言库
constmessage= {
zh,
en,
}
exportdefaultdefineNuxtPlugin((nuxtApp) => {
constCookie=useCookie('lang');
//这里使用了内置api 可以快速设置获取cookie 当然这里也可以设置在localStorage中使用 不使用useCookie
Cookie.value=Cookie.value||'zh'
consti18n=createI18n({
legacy:false,//使用vue3组合式API时必须设置为FALSE
locale:Cookie.value||'zh',
fallbackLocale: 'zh', // set fallback locale
messages:message,
globalInjection:true,//全局注入$t函数
})
nuxtApp.vueApp.use(i18n)
//新增的 提供一个辅助函数 然后在中间件auth.global.ts中调用
return{
provide:{
myi18n:()=>i18n
}
}
});
更改middleware/auth.global.ts
import { messageasMessage,Modal } from'ant-design-vue'
//import { useI18n } from 'vue-i18n';
exportdefaultdefineNuxtRouteMiddleware((to, from) => {
///新增的
const { $myi18n } =useNuxtApp()
const { t } =$myi18n().global
if(process.client){//只在客户端显示 具体请以官网为准
//const {t} = useI18n();
consttoken=useCookie('app-token');
//某些特定的页面不需要token login register reset
constnoTokenPath= ['/login','/register','/reset']
if(!noTokenPath.includes(to.path)){
if(!token.value){
// Message.error('This is an error message');
// return abortNavigation('500')
Modal.error({
title: 'Tip',
content: t('app.auth'),//该页面需要登录请登录后重试
});
}
}
}
})
nuxt.config.ts中别忘了添加去除vue-i18n控制台警告
exportdefaultdefineNuxtConfig({
...
vite:{
...
resolve:{
alias:{
'vue-i18n':'vue-i18n/dist/vue-i18n.cjs.js'
}
}
...
}
...
})
至此vue-i18n的使用基本已经完成,本地测试没有问题,打包本地测试也没有问题。end。。。。。。。。。。。。。
在Nuxt3中结合Ant-design-vue如何自定义主题。
这个问题我网上找了好多天的资料 都没有解决 最终在结合之前的vue3项目才解决掉,原本的出发点就不正确 一直以为解决的出发点应该在nuxt中解决 最终解决的方法在Vite插件配置中解决。需要安装插件 vite-plugin-style-import yarn add vite-plugin-style-import -D
import { createStyleImportPlugin,AntdResolve } from'vite-plugin-style-import'
exportdefaultdefineNuxtConfig({
...
vite:{
plugins:[
createStyleImportPlugin({
resolves: [AntdResolve()],
}),
],
css:{
preprocessorOptions: {
less: {
modifyVars: {// 更改主题
// hack: `true; @import (reference) "${path.resolve('src/assets/less/global.less')}";`,
'primary-color': '#2096f3', // 全局主色
'link-color': '#2096f3', // 链接色
'success-color': '#00B86B', // 成功色
'warning-color': '#FF9500', // 警告色
},
javascriptEnabled: true,
},
},
}
}
...
})