这是我参与「掘金日新计划 · 8 月更文挑战」的第7天,点击查看活动详情
建议按序观看
我们把基本的全家桶安装完成之后,就该开始配置 UI 组件库了。那么作为一个脚手架安装 UI 组件库,有以下几种方式。
全局安装(不推荐)
import { createApp } from 'vue'
import naive from 'naive-ui'
const app = createApp(App)
app.use(naive)
然后在全局直接使用
<template>
<n-button>naive-ui</n-button>
</template>
缺点: 当你去使用一个 UI 组件库的时候,你会发现有很多的组件,其实你本没有使用,但是这样引入的话,会导致,整体打出来的包很大。
使用 UMD
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<script src="https://unpkg.com/vue"></script>
<!-- 会使用最新版本,你最好指定一个版本 -->
<script src="https://unpkg.com/naive-ui"></script>
</head>
<body>
<div id="app">
<n-button>{{ message }}</n-button>
</div>
<script>
const App = {
setup() {
return {
message: 'naive'
}
}
}
const app = Vue.createApp(App)
app.use(naive)
app.mount('#app')
</script>
</body>
</html>
在页面中直接加载 umd 版本,好处就是利用了 http的多个下载线程,直接下载 UI 组件库的包,速度比全局要快。缺点就是依旧包很大,整体下载的意义不大。
按需全局安装
import { NInput , useMessage } from 'naive-ui'
export const setupUi = (app: App): void => {
const components = [NInput]
components.forEach((component) => {
app.component(component.name, component)
})
app.config.globalProperties.$message = useMessage
}
按照前文的说法,可以做一个创建,然后再 main.ts种引入,最后做到按需部分加载,这样的设计在 webpack 中很常见,可以省去在.vue
页面中的直接引用。
页面中按需引用
<template>
<n-button>naive-ui</n-button>
</template>
<script setup lang='ts'>
import { NButton } from 'naive-ui'
</script>
自动引入
我个人学习的时候,发现这种方式可能是 vite 中的一大特色,他可以做到直接使用,并且直接处理对应管理,已达到项目中,即不用再页面中引入,又可以按需加载。
扫描二维码关注公众号,回复:
14431465 查看本文章
按需自动加载UI组件: unplugin-vue-components
安装
pnpm i -D unplugin-auto-import
该插件主要作用是省去每次使用一个自定义组件,或UI组件库的组件时对组件的引入。兼容不同UI组件库,需要在安装对应UI组件库的前提下,并引入对应UI组件库的 resolvers
改组件提供各种 UI 组件库的resolvers
// 当引入 "unplugin-vue-components/vite 组件之后,页面中需要引入组件的地方就都不需要引入了
import Components from "unplugin-vue-components/vite";
// 引入对应 UI库的 resolver,则对应UI组件库的组件也不需要单独引入了
import {
AntDesignVueResolver,
ElementPlusResolver,
VantResolver,
NaiveUiResolver,
} from "unplugin-vue-components/resolvers";
AutoImport
// 实现 Vue及Vue相关的库、api的 按需加载
import AutoImport from "unplugin-auto-import/vite";
AutoImport({
imports: ["vue", "vue-router", "pinia"],
})
举一个例子
<script setup>
<!-- ref 也不需要引入 -->
const counter = ref(0);
const add = () => counter.value++;
</script>
<template>
<div>{{ counter }}</div>
<button @click="add">counter+1</button>
<!-- 以下组件都可以直接引入 -->
<Foo></Foo>
<el-button>elmentplus button</el-button>
<n-button>naiveui button</n-button>
</template>
处理 vite.config.ts文件
通常看到的config文件
export default defineConfig({
plugins: [vue()]
})
这样写的缺点就是在未来,我想要配置多的 mode (模式) 的时候就会有一些问题
import { loadEnv } from 'vite'
import type { UserConfig, ConfigEnv } from 'vite'
const CWD = process.cwd();
export default ({ mode }: ConfigEnv): UserConfig => {
const { VITE_NODE_ENV } = loadEnv(mode, CWD)
const isProd = ['development', 'test', 'production'].includes(VITE_NODE_ENV)
return {
plugins: [vue()]
}
}
配置自动导入
import vue from "@vitejs/plugin-vue";
// 当引入 "unplugin-vue-components/vite 组件之后,页面中需要引入组件的地方就都不需要引入了
import AutoImport from "unplugin-auto-import/vite";
import Components from "unplugin-vue-components/vite";
import { NaiveUiResolver } from "unplugin-vue-components/resolvers";
import type { UserConfig, ConfigEnv } from "vite";
const CWD = process.cwd();
export default ({ mode }: ConfigEnv): UserConfig => {
const { VITE_NODE_ENV } = loadEnv(mode, CWD);
const isProd = ["development", "test", "production"].includes(VITE_NODE_ENV);
console.log(isProd);
return {
plugins: [
vue(),
AutoImport({
imports: [
"vue",
"vue-router",
"pinia",
{
"naive-ui": [
"useDialog",
"useMessage",
"useNotification",
"useLoadingBar",
],
},
],
}),
Components({
resolvers: [NaiveUiResolver()],
}),
],
};
};
写一个页面测试一下
<template>
<n-menu v-model:value="activeKey" mode="horizontal" :options="menuOptions" />
<n-layout has-sider>
<n-layout-sider content-style="padding: 24px;"> 海淀桥 </n-layout-sider>
<n-layout>
<n-layout-header>颐和园路</n-layout-header>
<n-layout-content content-style="padding: 24px;">
<router-view />
</n-layout-content>
<n-layout-footer>成府路</n-layout-footer>
</n-layout>
</n-layout>
</template>
<script lang="ts" setup>
import type { MenuOption } from "naive-ui";
import { RouterLink } from "vue-router";
const options: MenuOption[] = [
{
label: () =>
h(
RouterLink,
{
to: {
name: "Home",
params: {
lang: "zh-CN",
},
},
},
{ default: () => "回家" }
),
key: "hear-the-wind-sing",
},
{
label: () =>
h(
RouterLink,
{
to: {
name: "About",
params: {
lang: "zh-CN",
},
},
},
{ default: () => "About" }
),
key: "a-wild-sheep-chase",
},
];
const activeKey = ref<string | null>(null);
const menuOptions = reactive(options);
</script>
<style scoped>
.n-layout-header,
.n-layout-footer {
background: rgba(128, 128, 128, 0.2);
padding: 24px;
}
.n-layout-sider {
background: rgba(128, 128, 128, 0.3);
}
.n-layout-content {
background: rgba(128, 128, 128, 0.4);
}
</style>