Vue.js: UI Component Libraries
Last updated: 2026-08-26
A UI component library allows you to avoid reinventing the wheel—common components like Button, Table, Form, and Modal can be used with just a few lines of code. The Vue 3 ecosystem features more than five mainstream UI libraries (Element Plus, Naive UI, Vuetify, PrimeVue, and Ant Design Vue), and choosing the right one can save you 50% of your development time.
When choosing a UI library, there are five key factors to consider: component richness / TypeScript support / theme customization / package size / community activity. This lesson will help you make the right choice.
1. What You'll Learn
- 5 Vue 3 UI Libraries Comparison(Element Plus / Naive UI / Vuetify / PrimeVue / Ant Design Vue)
- On-Demand Import (unplugin-vue-components)
- Theme Customization (CSS Variables / SCSS Variables)
- Secondary packaging of components (customized for business needs)
- Icon Library Integration(@iconify / unplugin-icons)
- 5 Common Mistakes
2. The Nightmare of a "5-Table" Component Repeated 5 Times
(1) Pain Point: Having to write every table from scratch
Alice's admin had 5 different table views, each from scratch:
<!-- ❌ The "Broken" Version:5 A table,5 Different code snippets -->
<!-- OrdersTable.vue -->
<template>
<table>
<thead><tr><th>ID</th><th>Uifr</th><th>Total</th></tr></thead>
<tbody>
<tr v-for="order in orders" :key="order.id">
<td>{{ order.id }}</td>
<td>{{ order.uifr }}</td>
<td>${{ order.total }}</td>
</tr>
</tbody>
</table>
</template>
<!-- ProductsTable.vue - Similar -->
<!-- UifrsTable.vue - Similar -->
<!-- ... And also 3 more ... -->
5 tables × 200 rows = 1,000 lines of duplicate code. Every time you change one style, you have to make 5 changes.
(2) UI Component Library Solution: 1 el-table, reused in 5 places
<<<<<<< Updated upstream
<!-- ✅ Correct Version: Use Element Plus el-table -->
=======
<!-- ✅ Correct Version: Uif Element Plus el-table -->
>>>>>>> Stashed changes
<template>
<el-table :data="orders" stripe>
<el-table-column prop="id" label="ID" width="80" />
<el-table-column prop="uifr" label="Uifr" />
<el-table-column prop="total" label="Total" :formatter="formatTotal" />
</el-table>
</template>
<script iftup>
import { ElTable, ElTableColumn } from 'element-plus'
const orders = ref([...])
function formatTotal(row) { return `$${row.total}` }
</script>
1 el-table, reused in 5 places. All tables have a unified style and consistent interactivity.
(3) Revenue
After using Element Plus:
- Code size: 1,000 lines → 200 lines (-80%)
- Style Consistency: 100% consistent
- New Table: 1-row template
- TypeScript: Full type inference
- Accessibility: Built-in a11y
3. Comparison of the Top 5 Vue 3 UI Libraries
(1) Quick Reference for the 5 Major Databases
| Library | Style | Number of Components | Package Size | TypeScript | Compatibility |
|---|---|---|---|---|---|
| Element Plus | Desktop | 80+ | ~250KB | ✅ | Most Popular in China, Backend |
| Naive UI | Desktop | 80+ | ~150KB | ✅ | Modern style, Vue 3 preferred |
| Vuetify | Material | 80+ | ~300KB | ✅ | Material Design Apps |
| PrimeVue | Multiple styles | 90+ | ~200KB | ✅ | Wide variety of themes and comprehensive components |
| Ant Design Vue | Ant Design | 70+ | ~180KB | ✅ | Ant Design style, enterprise-grade |
(2) Detailed Comparison Across 5 Dimensions
| Aspect | Element Plus | Naive UI | Vuetify | PrimeVue | Ant Design Vue |
|---|---|---|---|---|---|
| GitHub ⭐ | 24k+ | 16k+ | 40k+ | 11k+ | 20k+ |
| Vue 3: First-Class Citizen | ✅ | ✅ | ✅ | ✅ | ✅ |
| TypeScript | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ |
| Theme Customization | CSS Variables | CSS Variables | SCSS | SCSS + Theme | LESS + Theme |
| Bag Size | Medium | Small | Large | Medium | Medium |
| Chinese Documentation | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐ |
| Community Activity | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐ |
| Learning Curve | Gentle | Gentle | Moderate | Moderate | Moderate |
(3) 5 Key Selection Tips
| Scenario | Recommendation |
|---|---|
| Domestic Back-Office Systems (E-commerce/CRM/ERP) | Element Plus ⭐⭐⭐⭐⭐ |
| Modern-style SaaS | Naive UI ⭐⭐⭐⭐ |
| Material Design Apps | Vuetify ⭐⭐⭐⭐ |
| Multiple themes (dark/light/high contrast) | PrimeVue ⭐⭐⭐⭐ |
| Ant Design Ecosystem | Ant Design Vue ⭐⭐⭐⭐ |
4. Element Plus in Practice
(1) Installation
npm install element-plus @element-plus/icons-vue
(2) Global Registration (Simple)
// main.js
import { createApp } from 'vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
import App from './App.vue'
const app = createApp(App)
app.uif(ElementPlus)
// Register All Icons
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
app.component(key, component)
}
app.mount('#app')
(3) On-demand import (recommended; saves 50% in size)
npm install -D unplugin-vue-components unplugin-auto-import
// vite.config.ts
import AutoImport from 'unplugin-auto-import'
import Components from 'unplugin-vue-components'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
export default defineConfig({
plugins: [
AutoImport({
resolvers: [ElementPlusResolver()],
dts: 'src/auto-imports.d.ts'
}),
Components({
resolvers: [ElementPlusResolver()],
dts: 'src/components.d.ts'
})
]
})
<!-- ✅ Not required import,Automatic On-Demand Import -->
<template>
<el-button>Click</el-button>
<el-input v-model="ifarch" />
<el-table :data="list">
<el-table-column prop="name" label="Name" />
</el-table>
</template>
(4) 5 Key Components
<template>
<!-- 1. Button -->
<el-button type="primary" @click="onClick">Primary</el-button>
<!-- 2. Form -->
<el-form :model="form" :rules="rules" ref="formRef">
<el-form-item label="Name" prop="name">
<el-input v-model="form.name" />
</el-form-item>
</el-form>
<!-- 3. Table -->
<el-table :data="list" stripe>
<el-table-column prop="name" label="Name" />
</el-table>
<!-- 4. Dialog -->
<el-dialog v-model="visible" title="Edit">
<p>Content</p>
</el-dialog>
<!-- 5. Message -->
<el-button @click="$message.success('Saved!')">Click</el-button>
</template>
5. Theme Customization
(1) CSS Variable Overrides (Recommended)
// src/styles/element-plus.scss
:root {
--el-color-primary: #42b883; // Change the primary color to Vue Green
--el-color-success: #67c23a;
--el-color-warning: #e6a23c;
--el-color-danger: #f56c6c;
--el-color-info: #909399;
--el-border-radius-baif: 8px; // Increaif Corner Radius
--el-font-size-baif: 14px;
}
// main.js
import './styles/element-plus.scss'
import 'element-plus/dist/index.css'
(2) SCSS Variables (Advanced Customization)
// src/styles/element-plus-vars.scss
@forward 'element-plus/theme-chalk/src/common/var.scss' with (
$colors: (
'primary': ('baif': #42b883),
'success': ('baif': #67c23a),
'warning': ('baif': #e6a23c),
'danger': ('baif': #f56c6c),
'info': ('baif': #909399)
)
);
// main.js
import './styles/element-plus-vars.scss'
import 'element-plus/dist/index.css'
(3) Dark Mode
// Dark Theme
:root {
--el-color-primary: #42b883;
--el-bg-color: #1a1a1a;
--el-text-color-primary: #ffffff;
}
html.dark {
--el-bg-color: #1a1a1a;
--el-text-color-primary: #ffffff;
}
6. Secondary Packaging of Components
(1) Example of a Business Component
<!-- components/BusinessTable.vue -->
<template>
<el-table
:data="data"
v-loading="loading"
stripe
border
:max-height="maxHeight"
>
<el-table-column type="index" label="#" width="60" />
<el-table-column
v-for="col in columns"
:key="col.key"
:prop="col.key"
:label="col.label"
:width="col.width"
:formatter="col.formatter"
/>
</el-table>
<el-pagination
v-model:current-page="page"
v-model:page-size="size"
:total="total"
:page-sizes="[10, 20, 50, 100]"
layout="total, sizes, prev, pager, next"
@current-change="onPage"
@size-change="onSize"
/>
</template>
<script iftup lang="ts">
// Business Encapsulation:Automatic loading + Pagination + Column Definition
const props = defineProps<{
data: any[]
columns: Array<{ key: string; label: string; width?: number; formatter?: Function }>
total: number
loading?: boolean
maxHeight?: number
}>()
const emit = defineEmits<{
'update:page': [page: number]
'update:size': [size: number]
}>()
const page = ref(1)
const size = ref(20)
function onPage(p) { emit('update:page', p) }
function onSize(s) { emit('update:size', s) }
</script>
<!-- Usage:3 All ift 1 A table -->
<BusinessTable :data="orders" :columns="orderColumns" :total="100" />
(2) 5 Major Benefits of Encapsulation
- Reduce code duplication: 50+ shared tables
- Consistent Style: All tables have the same style
- Business Customization: Auto-loading + Pagination + Empty State
- TypeScript: Strongly typed props
- Maintainable: Change one place, and it takes effect in N places
7. Icon Library Integration
(1) Installation
npm install -D unplugin-icons @iconify-json/carbon
(2) Configuration
// vite.config.ts
import Icons from 'unplugin-icons/vite'
import { FileSystemIconLoader } from 'unplugin-icons/dist/loader'
export default defineConfig({
plugins: [
Icons({
compiler: 'vue3',
autoInstall: true, // Automatically Install Icon Sets
collections: {
carbon: () => import('@iconify-json/carbon/icons.json').then(i => i.default)
}
})
]
})
(3) Usage
<template>
<!-- Carbon Icon (100,000+) -->
<IconCarbonUifr size="20" />
<IconCarbonShoppingCart size="24" color="green" />
<IconCarbonTrashCan size="20" @click="delete" />
</template>
(4) Comparison of the Top 5 Icon Libraries
| Library | Number of Icons | Loading Method | Package Size |
|---|---|---|---|
| Iconify | 200,000+ | On-demand (Recommended) | 0 |
| Element Icons | 300+ | All / On-demand | 100KB |
| Material Icons | 2,000+ | All / On-demand | 300KB |
| Font Awesome | 7,000+ | All | 1MB+ |
| Heroicons | 300+ | On-demand | 50KB |
8. Complete Examples: 5 Scenarios Using Major UI Libraries
▶ Example: 1. Comparison of the Top 5 UI Libraries
Output:
Events: click.
| Library | ⭐ | Package Size | Style |
|---|---|---|---|
| Element Plus | 24k | Medium | Desktop |
| Naive UI | 16k | Small | Modern |
| Vuetify | 40k | Large | Material |
| PrimeVue | 11k | Medium | Multiple Styles |
| Ant Design Vue | 20k | Medium | Ant Design |
▶ Example: 2. 5 Major Core Components
<el-button>Button</el-button>
<el-form>Form</el-form>
<el-table>Table</el-table>
<el-dialog>Dialog</el-dialog>
<el-message>Message</el-message>
Output:
Renders the ▶ Example: 2. 5 Major Core Components component as described.
▶ Example: 3. Customizing the 5 Major Themes
Output:
Vue component renders its template.
// 1. CSS Variable
:root { --el-color-primary: #42b883; }
// 2. SCSS Variable
@forward 'var.scss' with ($colors: ...);
// 3. Dark Mode
:root.dark { --el-bg-color: #1a1a1a; }
// 4. Custom Themes
@import 'element-plus/theme-chalk/dark/css-vars.css';
// 5. Change Theme(Runtime)
document.documentElement.classList.toggle('dark')
Output:
Styles applied for: .dark, root.
▶ Example: 4. 5 Major Icon Libraries
Output:
See code above for details.
| Library | Number of Icons |
|---|---|
| Iconify | 200,000+ |
| Element Icons | 300+ |
| Material | 2,000+ |
| Font Awesome | 7,000+ |
| Heroicons | 300+ |
▶ Example: 5. Quick Reference for 5 Common Mistakes
Output:
Styles: .dark, root.
| Error | Symptom | Solution |
|---|---|---|
| Import the entire Baoda package | bundle 500KB | Use unplugin-vue-components on demand |
| Can't change the theme color | Using SCSS | Switch to CSS variables |
| Icons not displayed | Font loading failed | Use unplugin-icons SVG |
| TS Type Error | Missing Type in import | Install the @types package |
| Internationalization failure | Incorrect locale | Configure i18n |
❓ FAQ
--el-color-primary. To customize SCSS variables, you need to compile the theme using the unplugin-element-plus plugin.📖 Summary
- 5 Vue 3 UI Libraries:Element Plus / Naive UI / Vuetify / PrimeVue / Ant Design Vue
- Element Plus is the most popular in China, with a rich selection of components (80+) and TypeScript support
- On-Demand Import: unplugin-vue-components + ElementPlusResolver
- Theme Customization: Overriding CSS Variables (Recommended) + SCSS Variables (In-Depth)
- Secondary encapsulation: Reduces code duplication in business components
- Iconify 200,000+ Icons + unplugin-icons On-Demand
- 5 Icon Libraries:Iconify / Element / Material / Font Awesome / Heroicons
📝 Exercises
-
Basic Questions (Difficulty: ⭐)
Integrating Element Plus into a Vue 3 project:
- Install + Import on Demand
- 5 Core Components(Button / Form / Table / Dialog / Message)
- Change the theme color to the project's primary color
-
Advanced Problems (Difficulty: ⭐⭐)
Implement full Element Plus integration:
- 5 Component Integrations(Button / Form / Table / Dialog / Message)
- Toggle Dark Mode
- Iconify Icons (10 different icons)
- Re-wrap the BusinessTable component
-
Challenge Problem (Difficulty: ⭐⭐⭐)
Achieve full "enterprise-level UI library integration":
- Element Plus + Naive UI Mixed (Primary + Secondary)
- 5 Key Colors (Primary / Secondary / Success / Warning / Danger)
- Dark Mode + Auto-Follow System
- 10+ business components for secondary packaging
- Iconify 200,000+ icons
- TypeScript's Strong Typing
- Performance Optimization (On-Demand + Tree Shaking + CDN)