前言
Naive UI :一个完全使用 TypeScript 编写的 Vue 3 组件库,也是Vue 作者尤大推荐的Vue组件库。
Tailwind CSS:能让你少写很多代码的css工具库。
本案例使用最新的Vue3,Vite3,TypeScript搭建
NaiveUI官网:www.naiveui.com
TailwindCSS官网:www.tailwindcss.cn
一、环境要求
a)NodeJS:这是必须的,安装就不在此赘述了
b)Vue3
c)Vite:Vite 需要 Node.js 版本 14.18+,16+
下图为nodejs,npm,vue对应的版本号
二、创建项目
npm create vite@latest
1、输入项目名称
2、选择Vue
3、选择TypeScript
4、项目创建完成
5、使用下面的命令安装、启动项目
cd xiaomo-app-naive-ui
npm insall
npm run dev
6、启动成功运行的项目
创建项目至此完成,下面开始安装Naive UI框架。
三、安装和使用Naive UI
Naive UI :一个完全使用 TypeScript 编写的 Vue 3 组件库,Naive UI 仅支持 Vue3
1、安装Naive UI
npm i -D naive-ui
安装字体
npm i -D vfonts
安装图标
NaiveUI官方建议:使用 xicons 作为图标库。
支持很多图标库,下面我们选择一两个图标库来使用
# For vue3
npm i -D @vicons/fluent
npm i -D @vicons/ionicons4
npm i -D @vicons/ionicons5
npm i -D @vicons/antd
npm i -D @vicons/material
npm i -D @vicons/fa
npm i -D @vicons/tabler
npm i -D @vicons/carbon
npm i -D @ricons/utils # react
npm i -D @vicons/utils # vue3
npm i -D @v2icons/utils # vue2
安装 ionicons5
npm i -D @vicons/ionicons5
安装vicons/utils
npm i -D @vicons/utils # vue3
2、使用Naive UI(直接引入)
直接引入(推荐)
你可以直接导入组件并使用它。这种情况下,只有导入的组件才会被打包。
全局安装(不推荐)
安装全部组件
失去 tree-shaking 的能力,打包有冗余代码。
本案例使用直接引入的方式使用Naive UI框架
直接在App.vue里面编写如下代码:
<!-- App.vue -->
<template>
<n-space>
<n-button>Default</n-button>
<n-button type="tertiary">Tertiary</n-button>
<n-button type="primary">Primary</n-button>
<n-button type="info">Info</n-button>
<n-button type="success">Success</n-button>
<n-button type="warning">Warning</n-button>
<n-button type="error">Error</n-button>
</n-space>
</template>
<script setup lang="ts">
import { NButton } from 'naive-ui'
</script>
main.ts 文件如下:
// main.ts
import { createApp } from 'vue'
import App from './App.vue'
createApp(App).mount('#app')
运行项目,最后呈现的效果如下
此时完整的package.json如下
{
"name": "xiaomo-app-naive-ui",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vue-tsc --noEmit && vite build",
"preview": "vite preview"
},
"dependencies": {
"vue": "^3.2.37"
},
"devDependencies": {
"@vicons/ionicons5": "^0.12.0",
"@vicons/utils": "^0.1.4",
"@vitejs/plugin-vue": "^3.1.0",
"naive-ui": "^2.33.3",
"typescript": "^4.6.4",
"vfonts": "^0.0.3",
"vite": "^3.1.0",
"vue-tsc": "^0.40.4"
}
}
以上为直接引入的方式,也就是需要使用的组件都需要 import 进入,这样使用起来很不方便,下面使用安装插件的方式来自动引入组件
3、使用Naive UI(自动引入)
# 安装自动导入组件的插件
npm install -D unplugin-vue-components unplugin-auto-import
此时完整的package.json文件
{
"name": "xiaomo-app-naive-ui",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vue-tsc --noEmit && vite build",
"preview": "vite preview"
},
"dependencies": {
"vue": "^3.2.37"
},
"devDependencies": {
"@vicons/ionicons5": "^0.12.0",
"@vicons/utils": "^0.1.4",
"@vitejs/plugin-vue": "^3.1.0",
"naive-ui": "^2.33.3",
"typescript": "^4.6.4",
"unplugin-auto-import": "^0.11.2",
"unplugin-vue-components": "^0.22.7",
"vfonts": "^0.0.3",
"vite": "^3.1.0",
"vue-tsc": "^0.40.4"
}
}
修改vite.config.ts文件
// import区域加入下面三行代码
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { NaiveUiResolver } from 'unplugin-vue-components/resolvers'
// plugins下面的vue(),下方加入下面的代码
AutoImport({
imports: [
'vue',
{
'naive-ui': [
'useDialog',
'useMessage',
'useNotification',
'useLoadingBar'
]
}
]
}),
Components({
resolvers: [NaiveUiResolver()]
})
完整的 vite.config.ts文件如下
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { NaiveUiResolver } from 'unplugin-vue-components/resolvers'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
AutoImport({
imports: [
'vue',
{
'naive-ui': [
'useDialog',
'useMessage',
'useNotification',
'useLoadingBar'
]
}
]
}),
Components({
resolvers: [NaiveUiResolver()]
})
]
})
目录结构如下:
再次编辑App.vue,删除组件的引入,保存后刷新页面,一样的效果,即说明自动引入组件成功了
<!-- App.vue -->
<template>
<n-space>
<n-button>Default</n-button>
<n-button type="tertiary">Tertiary</n-button>
<n-button type="primary">Primary</n-button>
<n-button type="info">Info</n-button>
<n-button type="success">Success</n-button>
<n-button type="warning">Warning</n-button>
<n-button type="error">Error</n-button>
</n-space>
</template>
<script setup lang="ts">
</script>
删除了 import { NButton } from 'naive-ui'
保存后运行的效果如下:
4、使用图标
图标使用方法一(用xicons的Icon组件进行icon 的控制)
<!-- App.vue -->
<template>
<n-space>
<n-button type="success">
<Icon :size="20">
<CarOutline />
</Icon>
小车
</n-button>
</n-space>
</template>
<script setup lang="ts">
import { CarOutline } from '@vicons/ionicons5'
import { Icon } from '@vicons/utils'
</script>
效果图
图标使用方法二(用naive-ui中<n-icon/ >)
<!-- App.vue -->
<template>
<n-space>
<n-button type="error">
<n-icon :size="20">
<CarOutline />
</n-icon>
小车车
</n-button>
</n-space>
</template>
<script setup lang="ts">
import { CarOutline } from '@vicons/ionicons5'
</script>
效果图
四、安装Tailwind CSS
Tailwind CSS非常的好用,能让你用很少的代码做出很炫的效果
安装 Tailwind 以及其它依赖项:
npm install -D tailwindcss@latest postcss@latest autoprefixer@latest
创建配置文件
# 使用下面的命令会生成 tailwind.config.cjs 和 postcss.config.cjs 两个配置文件
npx tailwindcss init -p
此时完整的package.json文件
{
"name": "xiaomo-app-naive-ui",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vue-tsc --noEmit && vite build",
"preview": "vite preview"
},
"dependencies": {
"vue": "^3.2.37"
},
"devDependencies": {
"@vicons/ionicons5": "^0.12.0",
"@vicons/utils": "^0.1.4",
"@vitejs/plugin-vue": "^3.1.0",
"autoprefixer": "^9.8.8",
"naive-ui": "^2.33.3",
"postcss": "^8.4.16",
"tailwindcss": "^3.1.8"
"typescript": "^4.6.4",
"unplugin-auto-import": "^0.11.2",
"unplugin-vue-components": "^0.22.7",
"vfonts": "^0.0.3",
"vite": "^3.1.0",
"vue-tsc": "^0.40.4"
}
}
tailwind.config.cjs文件
// tailwind.config.cjs
module.exports = {
purge: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}'],
darkMode: false, // or 'media' or 'class'
theme: {
extend: {}
},
variants: {
extend: {}
},
plugins: []
// 若不想要默认的设置生效,添加下面的配置
// corePlugins: {
// preflight: false
// }
}
postcss.config.cjs文件
// postcss.config.cjs
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {}
}
}
目录结构如下:
接下来在src目录下新建styles目录,在styles目录下新建tailwind.css文件,内容如下:
/* tailwind.css */
@tailwind base;
@tailwind components;
@tailwind utilities;
在main.ts中引入tailwind.css
import { createApp } from 'vue'
import App from './App.vue'
import './styles/tailwind.css' // 引入tailwind.css
createApp(App).mount('#app')
修改App.vue,实现tailwind css 的一个小案例
<!-- App.vue -->
<template>
<ul class="space-y-4">
<li>
<div class="w-64 h-3 bg-gradient-to-br from-fuchsia-500 to-purple-600"></div>
</li>
<li>
<div class="w-56 h-3 bg-gradient-to-br from-fuchsia-500 to-purple-600"></div>
</li>
<li>
<div class="w-48 h-3 bg-gradient-to-br from-fuchsia-500 to-purple-600"></div>
</li>
<li>
<div class="w-40 h-3 bg-gradient-to-br from-fuchsia-500 to-purple-600"></div>
</li>
<li>
<div class="w-32 h-3 bg-gradient-to-br from-fuchsia-500 to-purple-600"></div>
</li>
<li>
<div class="w-24 h-3 bg-gradient-to-br from-fuchsia-500 to-purple-600"></div>
</li>
<li>
<div class="w-20 h-3 bg-gradient-to-br from-fuchsia-500 to-purple-600"></div>
</li>
<li>
<div class="w-16 h-3 bg-gradient-to-br from-fuchsia-500 to-purple-600"></div>
</li>
<li>
<div class="w-12 h-3 bg-gradient-to-br from-fuchsia-500 to-purple-600"></div>
</li>
<li>
<div class="w-10 h-3 bg-gradient-to-br from-fuchsia-500 to-purple-600"></div>
</li>
</ul>
</template>
<script setup lang="ts">
</script>
效果如下:
五、NaiveUI整合TailwindCSS 及遇到的问题
整合之前先全局配置一下NaiveUI
<!-- App.vue -->
<template>
<NConfigProvider :locale="zhCN" :date-locale="dateZhCN" :theme="getDarkTheme" :theme-overrides="getThemeOverrides" >
</NConfigProvider>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { zhCN, dateZhCN, darkTheme } from 'naive-ui'
import { lighten } from '@/utils/index'
const designStore = {
appTheme: '#2d8cf0',
darkTheme: false
}
/**
* 获取主题覆盖
*/
const getThemeOverrides = computed(() => {
const appTheme = designStore.appTheme
const lightenStr = lighten(designStore.appTheme, 6)
return {
common: {
primaryColor: appTheme,
primaryColorHover: lightenStr,
primaryColorPressed: lightenStr
},
LoadingBar: {
colorLoading: appTheme
}
}
})
/**
* 获取暗黑主题
*/
const getDarkTheme = computed(() =>
designStore.darkTheme ? darkTheme : undefined
)
</script>
utils/index.ts文件
/**
* 将通过的百分比与十六进制颜色的R、G或B相加
* @param {string} color 要更改的颜色
* @param {number} amount 改变颜色的量
* @returns {string} 颜色的处理部分
*/
function addLight(color: string, amount: number) {
const cc = parseInt(color, 16) + amount
const c = cc > 255 ? 255 : cc
return c.toString(16).length > 1 ? c.toString(16) : `0${c.toString(16)}`
}
/**
* 根据通过的百分比点亮6个字符的十六进制颜色
* @param {string} color 要更改的颜色
* @param {number} amount 改变颜色的量
* @returns {string} 已处理的颜色,表示为十六进制
*/
export function lighten(color: string, amount: number) {
color = color.indexOf('#') >= 0 ? color.substring(1, color.length) : color
amount = Math.trunc((255 * amount) / 100)
return `#${addLight(color.substring(0, 2), amount)}${addLight(
color.substring(2, 4),
amount
)}${addLight(color.substring(4, 6), amount)}`
}
/**
* 判断是否 url
*/
export function isUrl(url: string) {
return /^(http|https):\/\//g.test(url)
}
修改App.vue
<!-- App.vue -->
<template>
<NConfigProvider :locale="zhCN" :date-locale="dateZhCN" :theme="getDarkTheme" :theme-overrides="getThemeOverrides">
<div class="flex h-screen items-center justify-center bg-green-100">
<n-space>
<n-button>Default</n-button>
<n-button type="tertiary">Tertiary</n-button>
<n-button type="primary">Primary</n-button>
<n-button type="info">Info</n-button>
<n-button type="success">Success</n-button>
<n-button type="warning">Warning</n-button>
<n-button type="error">Error</n-button>
</n-space>
</div>
</NConfigProvider>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { zhCN, dateZhCN, darkTheme } from 'naive-ui'
import { lighten } from '@/utils/index'
const designStore = {
appTheme: '#2d8cf0',
darkTheme: false
}
/**
* 获取主题覆盖
*/
const getThemeOverrides = computed(() => {
const appTheme = designStore.appTheme
const lightenStr = lighten(designStore.appTheme, 6)
return {
common: {
primaryColor: appTheme,
primaryColorHover: lightenStr,
primaryColorPressed: lightenStr
},
LoadingBar: {
colorLoading: appTheme
}
}
})
/**
* 获取暗黑主题
*/
const getDarkTheme = computed(() =>
designStore.darkTheme ? darkTheme : undefined
)
</script>
运行效果如下:
可以很清楚的看到每个NaiveUI的按钮背景颜色没了,这也就是整合出现的第一个问题(兼容性问题)
TailwindCSS官方描述:从 v2.0 版本开始,Tailwind CSS 依赖于 PostCSS 8。由于 PostCSS 8 才使用了几个月,因此生态系统中的许多其他工具尚未更新,这意味着在安装 Tailwind,并尝试编译 CSS 时,您可能会在终端中看到这样的错误:
先卸载tailwindcss postcss autoprefixer
npm uninstall tailwindcss postcss autoprefixer
再安装PostCSS 7 兼容性版本
npm install -D tailwindcss@npm:@tailwindcss/postcss7-compat postcss@^7 autoprefixer@^9
此时完整的package.json文件:
{
"name": "xiaomo-app-naive-ui",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vue-tsc --noEmit && vite build",
"preview": "vite preview"
},
"dependencies": {
"vue": "^3.2.37"
},
"devDependencies": {
"@vicons/ionicons5": "^0.12.0",
"@vicons/utils": "^0.1.4",
"@vitejs/plugin-vue": "^3.1.0",
"autoprefixer": "^9.8.8",
"naive-ui": "^2.33.3",
"postcss": "^7.0.39",
"tailwindcss": "npm:@tailwindcss/postcss7-compat@^2.2.17",
"typescript": "^4.6.4",
"unplugin-auto-import": "^0.11.2",
"unplugin-vue-components": "^0.22.7",
"vfonts": "^0.0.3",
"vite": "^3.1.0",
"vue-tsc": "^0.40.4"
}
}
postcss版本由原来的8.4.16变成了7.0.39
tailwindcss版本由原来的3.1.8变成了npm:@tailwindcss/postcss7-compat@^2.2.17
再次运行效果如下:
从上面的代码也看出来了要让所有的内容垂直水平居中,使用TailwindCSS只需要添加class="flex h-screen items-center justify-center",即可搞定了,是不是很方便
login.vue
<template>
<div class="flex h-screen items-center justify-center bg-green-100 view-account">
<div class="md:flex bg-gradient-to-r from-gray-50 to-gray-200 shadow-2xl rounded-xl p-8 md:p-0 ">
<img class="w-32 h-32 md:w-48 md:h-auto md:rounded-l-2xl-none rounded-full mx-auto" :src="appConfig.loginLogo"
alt="" width="384" height="512" />
<div class="pt-6 md:p-8 text-center md:text-left space-y-4">
<div>
<p class="text-2xl font-semibold">{{ appConfig.loginDesc }}</p>
</div>
<div class="font-medium">
<n-form ref="loginFormRef" label-placement="left" size="large" :model="loginForm" :rules="loginRules">
<n-form-item path="userName">
<n-input v-model:value="loginForm.userName" placeholder="请输入用户名">
<template #prefix>
<n-icon size="18" color="#808695">
<PersonOutline />
</n-icon>
</template>
</n-input>
</n-form-item>
<n-form-item path="password">
<n-input v-model:value="loginForm.password" type="password" show-password-on="click" placeholder="请输入密码">
<template #prefix>
<n-icon size="18" color="#808695">
<LockClosedOutline />
</n-icon>
</template>
</n-input>
</n-form-item>
<n-form-item>
<n-checkbox v-model:checked="autoLogin">自动登录</n-checkbox>
</n-form-item>
<n-form-item>
<n-button type="primary" @click="handleLogin" size="large" :loading="loading" block>登录
</n-button>
</n-form-item>
</n-form>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, reactive } from 'vue'
import { appConfig } from '@/config/AppConfig'
import { PersonOutline, LockClosedOutline } from '@vicons/ionicons5'
const autoLogin = ref(true)
const loading = ref(false) // 加载图标 默认false
const loginForm = reactive({
userName: 'xiaomo',
password: '123456',
isCaptcha: true
})
const loginRules = {
userName: { required: true, message: '请输入用户名', trigger: 'blur' },
password: { required: true, message: '请输入密码', trigger: 'blur' }
}
const handleLogin = (e: any) => {
// 登录逻辑
}
</script>
<style scoped>
@media (min-width: 768px) {
.view-account {
background-image: url('@/assets/images/login.svg');
background-repeat: no-repeat;
background-position: 50%;
background-size: 100%;
}
}
</style>
效果图如下 :
版权归原作者 小墨先生 所有, 如有侵权,请联系我们删除。