开篇
话不多说,vuetify是vue生态里面最有高级感的一款框架,2022年底vuetify 3正式上线,nuxt 3也逐渐稳定,这两种技术的结合一定会是未来vue app的一大趋势
项目github地址vuetify3-nuxt3-app
目标技术栈
- vue 3.2
- vuetify 3
- nuxt 3
- vite nuxt3已集成
- typescript nuxt3已集成
- pinia
- sass
- vueuse
- vue-echarts 施工中
- 多语言切换 施工中
- google登录集成 施工中
- googleMap集成 施工中
- vuedraggable集成 施工中
- vue-virtual-scroller 虚拟列表 施工中
- vue-masonry vue流体布局方案 施工中
流程
创建nuxt项目
npx nuxi init nuxt3-vuetify3-app
安装依赖
yarn install
启动
yarn serve
当前状态插件未安装且项目目录均未创建
安装 vueitfy 3
yarn add vuetify@next
安装 sass
yarn add sass
创建 vuetify.ts
首先在根目录下创建 plugins目录,再创建vuetify.ts
import { createVuetify } from "vuetify";
import * as components from "vuetify/components";
export default defineNuxtPlugin((nuxtApp) => {
const vuetify = createVuetify({
components,
});
nuxtApp.vueApp.use(vuetify);
});
创建style.scss
在根目录下创建 assets,再创建scss目录,再创建style.scss
并且继承使用vuetify的样式@use "vuetify/styles";
nuxt.config.ts追加vuetify设定
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
css: ["@/assets/scss/style.scss"],
build: {
// transpile 选项中可以配置需要转译的文件或模块的名称,这些文件或模块会在编译过程中被转译,以保证其兼容性。
transpile: ["vuetify"],
},
});
在app.vue中使用vuetify的组件
组件正常显示
全局修改vuetify组件样式
@use "vuetify/styles";
html {
.v-btn {
color: black !important;
}
}
vuetify组件样式被修改
集成 Material Design Icons
yarn add mdi
nuxt.config.ts追加mdi icon样式文件
export default defineNuxtConfig({
css: ["@/assets/scss/style.scss", "mdi/css/materialdesignicons.min.css"],
build: {
// transpile 选项中可以配置需要转译的文件或模块的名称,这些文件或模块会在编译过程中被转译,以保证其兼容性。
transpile: ["vuetify"],
},
});
使用mdi icon
icon正常显示
集成 Iconify
yarn add --dev @iconify/vue
使用iconify
iconify的icon正常使用
创建Vuetify的app框架
创建layouts目录,其下创建default.vue作为<NuxtLayout>的默认layout
// default.vue
<!--
* @Maintainer: J.K. Yang
* @Description: Default Layout
-->
<script setup lang="ts">
import { ref } from "vue";
const order = ref(1);
const navDrawer = ref(true);
</script>
<template>
<div>
<v-app>
<!-- APP BAR -->
<v-app-bar app :order="order">
<v-app-bar-nav-icon @click.stop="navDrawer = !navDrawer">
</v-app-bar-nav-icon>
App Bar
</v-app-bar>
<!-- Navigation Drawer -->
<v-navigation-drawer elevation="4" v-model="navDrawer">
Navigation Drawer
</v-navigation-drawer>
<!-- Main -->
<v-main class="bg-grey-lighten-3">
<v-container fluid class="h-full">
<slot />
</v-container>
</v-main>
<!-- Footer -->
<v-footer app height="72"> Footer </v-footer>
</v-app>
</div>
</template>
<style scoped lang="scss"></style>
创建pages目录,其下创建index.vue作为的默认page
// pages/index.vue
<!--
* @Router: /
* @Maintainer:
* @Description: HomePage
-->
<script setup lang="ts"></script>
<template>
<v-card min-height="87vh"> Index </v-card>
</template>
<style scoped lang="scss"></style>
使用pinia
yarn add pinia @pinia/nuxt
nuxt.config.ts追加pinia模块
export default defineNuxtConfig({
css: ["@/assets/scss/style.scss", "mdi/css/materialdesignicons.min.css"],
modules: ["@pinia/nuxt"],
build: {
// transpile 选项中可以配置需要转译的文件或模块的名称,这些文件或模块会在编译过程中被转译,以保证其兼容性。
transpile: ["vuetify"],
},
});
利用pinia进行全局主题切换
创建 stores 目录,在其下创建 customizeTheme.ts
// customizeTheme.ts
import { defineStore } from "pinia";
interface State {
miniSidebar: boolean;
darkTheme: boolean;
}
export const useCustomizeThemeStore = defineStore({
id: "customizeTheme",
state: (): State => ({
miniSidebar: false,
darkTheme: false,
}),
getters: {},
actions: {
setMiniSideBar(payload: boolean) {
this.miniSidebar = payload;
},
},
});
创建 CustomizeTheme组件
创建components目录,其下创建CustomizeTheme.vue
components下的组件会被Nuxt自动进行全局导入
主题切换组件,对store里面的状态进行更改
<!--
* @Component: CustomizeTheme
* @Maintainer: Yang J.K.
* @Description: HomePage
-->
<script setup lang="ts">
import { useCustomizeThemeStore } from "@/stores/customizeTheme";
const customizeTheme = useCustomizeThemeStore();
</script>
<template>
<div>
<v-navigation-drawer permanent location="right">
<div class="ml-5 pa-5">
<v-switch
v-model="customizeTheme.darkTheme"
label="主题切换"
color="orange"
hide-details
></v-switch>
</div>
<v-divider></v-divider>
<v-btn
class="ma-5"
@click.stop="customizeTheme.setMiniSideBar(!customizeTheme.miniSidebar)"
color="warning"
>收缩侧面菜单</v-btn
>
</v-navigation-drawer>
</div>
</template>
<style scoped></style>
layout里对store里面的状态进行绑定
<!--
* @Maintainer: J.K. Yang
* @Description: Default Layout
-->
<script setup lang="ts">
import { useCustomizeThemeStore } from "@/stores/customizeTheme";
import { ref } from "vue";
const order = ref(1);
const navDrawer = ref(true);
const customizeTheme = useCustomizeThemeStore();
</script>
<template>
<div>
<v-app :theme="customizeTheme.darkTheme ? 'dark' : 'light'">
<!-- APP BAR -->
<v-app-bar app :order="order">
<v-app-bar-nav-icon @click.stop="navDrawer = !navDrawer">
</v-app-bar-nav-icon>
App Bar
</v-app-bar>
<!-- Navigation Drawer -->
<v-navigation-drawer
elevation="4"
v-model="navDrawer"
:rail="customizeTheme.miniSidebar"
>
<v-list density="compact" nav>
<v-list-item
prepend-icon="mdi-folder"
title="My Files"
value="myfiles"
></v-list-item>
<v-list-item
prepend-icon="mdi-account-multiple"
title="Shared with me"
value="shared"
></v-list-item>
<v-list-item
prepend-icon="mdi-star"
title="Starred"
value="starred"
></v-list-item>
</v-list>
</v-navigation-drawer>
<!-- Main -->
<v-main class="bg-grey-lighten-3">
<v-container fluid class="h-full">
<slot />
</v-container>
</v-main>
<!-- Footer -->
<v-footer app height="72" elevation="5"> Footer </v-footer>
<CustomizeTheme />
</v-app>
</div>
</template>
<style scoped lang="scss"></style>
pinia进行全局主题切换可正常使用
后续待更新