Vue.js Element Plus
Introduction
Element Plus is a popular Vue.js 3 UI library that provides a rich collection of components for building beautiful, responsive, and accessible web applications. It's the Vue 3 version of the widely-used Element UI library, redesigned with the Composition API in mind. If you're building modern Vue applications and need a comprehensive set of ready-to-use components, Element Plus is an excellent choice.
In this tutorial, we'll explore Element Plus, understand how to set it up, and learn how to use some of its most common components to build elegant user interfaces.
Getting Started with Element Plus
Installation
To get started with Element Plus in your Vue.js 3 project, you need to install it using npm or yarn:
# Using npm
npm install element-plus
# Using yarn
yarn add element-plus
Basic Setup
Once installed, you can set up Element Plus in your Vue application in two ways:
1. Full Import
For a quick start, you can import all Element Plus components at once:
import { createApp } from 'vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import App from './App.vue'
const app = createApp(App)
app.use(ElementPlus)
app.mount('#app')
2. On-demand Import (Recommended for Production)
For production applications, it's better to import only the components you need to reduce bundle size. You can use Auto Import with plugins:
import { createApp } from 'vue'
import App from './App.vue'
// Import components you need
import { ElButton, ElInput, ElSelect } from 'element-plus'
// Import styles
import 'element-plus/dist/index.css'
const app = createApp(App)
// Register components
app.component('ElButton', ElButton)
app.component('ElInput', ElInput)
app.component('ElSelect', ElSelect)
app.mount('#app')
Basic Components
Let's explore some of the basic components that Element Plus offers:
Buttons
Buttons are one of the most common UI elements. Element Plus provides a variety of button styles and types:
<template>
<div class="button-demo">
<h3>Button Types</h3>
<el-row>
<el-button>Default</el-button>
<el-button type="primary">Primary</el-button>
<el-button type="success">Success</el-button>
<el-button type="info">Info</el-button>
<el-button type="warning">Warning</el-button>
<el-button type="danger">Danger</el-button>
</el-row>
<h3>Button Sizes</h3>
<el-row>
<el-button size="large">Large</el-button>
<el-button>Default</el-button>
<el-button size="small">Small</el-button>
</el-row>
<h3>Button Features</h3>
<el-row>
<el-button plain>Plain</el-button>
<el-button round>Round</el-button>
<el-button circle><el-icon><Search /></el-icon></el-button>
<el-button :loading="true">Loading</el-button>
<el-button disabled>Disabled</el-button>
</el-row>
</div>
</template>
<script setup>
import { Search } from '@element-plus/icons-vue'
</script>
The result would show a variety of buttons with different styles, sizes, and states.
Form Elements
Forms are essential for collecting user input. Element Plus provides form components like inputs, selects, and more:
<template>
<el-form :model="form" label-width="120px">
<el-form-item label="Name">
<el-input v-model="form.name" placeholder="Please input name" />
</el-form-item>
<el-form-item label="Activity Zone">
<el-select v-model="form.region" placeholder="Please select a zone">
<el-option label="Zone One" value="zone-1" />
<el-option label="Zone Two" value="zone-2" />
</el-select>
</el-form-item>
<el-form-item label="Active">
<el-switch v-model="form.active" />
</el-form-item>
<el-form-item label="Description">
<el-input v-model="form.desc" type="textarea" rows="3" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit">Create</el-button>
<el-button>Cancel</el-button>
</el-form-item>
</el-form>
</template>
<script setup>
import { reactive } from 'vue'
const form = reactive({
name: '',
region: '',
active: false,
desc: ''
})
const onSubmit = () => {
console.log('Form submitted:', form)
}
</script>
This example creates a form with various input types like text input, select dropdown, switch toggle, and textarea.
Advanced Components
Element Plus offers many advanced components for building complex interfaces. Let's look at some examples:
Data Table
Tables are used to display large amounts of data in an organized way:
<template>
<div>
<el-table :data="tableData" style="width: 100%">
<el-table-column prop="date" label="Date" width="180" />
<el-table-column prop="name" label="Name" width="180" />
<el-table-column prop="address" label="Address" />
<el-table-column fixed="right" label="Operations" width="120">
<template #default="scope">
<el-button link type="primary" size="small" @click="handleEdit(scope.row)">
Edit
</el-button>
<el-button link type="primary" size="small" @click="handleDelete(scope.row)">
Delete
</el-button>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { ElMessage } from 'element-plus'
const tableData = ref([
{
date: '2023-05-03',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles'
},
{
date: '2023-05-02',
name: 'John',
address: '932 Washington Blvd, Seattle'
},
{
date: '2023-05-04',
name: 'Morgan',
address: '219 Madison St, San Francisco'
}
])
const handleEdit = (row) => {
ElMessage.success(`Editing ${row.name}'s information`)
}
const handleDelete = (row) => {
ElMessage.warning(`Deleting ${row.name} from records`)
}
</script>
This creates a data table with columns for date, name, address, and operations. It also includes edit and delete functionality.
Dialogs
Dialogs (or modals) are useful for focused user interactions:
<template>
<div>
<el-button type="text" @click="dialogVisible = true">
Click to open Dialog
</el-button>
<el-dialog
v-model="dialogVisible"
title="Dialog Title"
width="30%"
:before-close="handleClose"
>
<span>This is dialog content that can contain any elements</span>
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogVisible = false">Cancel</el-button>
<el-button type="primary" @click="confirmDialog">
Confirm
</el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
const dialogVisible = ref(false)
const handleClose = (done) => {
ElMessageBox.confirm('Are you sure to close this dialog?')
.then(() => {
done()
})
.catch(() => {
// User canceled closing
})
}
const confirmDialog = () => {
ElMessage({
message: 'Action confirmed!',
type: 'success',
})
dialogVisible.value = false
}
</script>
<style scoped>
.dialog-footer {
display: flex;
justify-content: flex-end;
gap: 10px;
}
</style>
This shows a button that when clicked, opens a dialog with customizable content and action buttons.
Layout System
Element Plus comes with a powerful layout system using rows and columns, similar to Bootstrap or other CSS frameworks:
<template>
<div>
<h3>Basic Layout</h3>
<el-row>
<el-col :span="24"><div class="grid-content bg-purple-dark">24</div></el-col>
</el-row>
<el-row>
<el-col :span="12"><div class="grid-content bg-purple">12</div></el-col>
<el-col :span="12"><div class="grid-content bg-purple-light">12</div></el-col>
</el-row>
<el-row>
<el-col :span="8"><div class="grid-content bg-purple">8</div></el-col>
<el-col :span="8"><div class="grid-content bg-purple-light">8</div></el-col>
<el-col :span="8"><div class="grid-content bg-purple">8</div></el-col>
</el-row>
<h3>Layout with Gutter</h3>
<el-row :gutter="20">
<el-col :span="6"><div class="grid-content bg-purple">6</div></el-col>
<el-col :span="6"><div class="grid-content bg-purple-light">6</div></el-col>
<el-col :span="6"><div class="grid-content bg-purple">6</div></el-col>
<el-col :span="6"><div class="grid-content bg-purple-light">6</div></el-col>
</el-row>
<h3>Responsive Layout</h3>
<el-row :gutter="10">
<el-col :xs="8" :sm="6" :md="4" :lg="3" :xl="1">
<div class="grid-content bg-purple">Responsive</div>
</el-col>
<el-col :xs="4" :sm="6" :md="8" :lg="9" :xl="11">
<div class="grid-content bg-purple-light">Responsive</div>
</el-col>
<el-col :xs="4" :sm="6" :md="8" :lg="9" :xl="11">
<div class="grid-content bg-purple">Responsive</div>
</el-col>
<el-col :xs="8" :sm="6" :md="4" :lg="3" :xl="1">
<div class="grid-content bg-purple-light">Responsive</div>
</el-col>
</el-row>
</div>
</template>
<style scoped>
.el-row {
margin-bottom: 20px;
}
.el-row:last-child {
margin-bottom: 0;
}
.el-col {
border-radius: 4px;
}
.grid-content {
border-radius: 4px;
min-height: 36px;
display: flex;
justify-content: center;
align-items: center;
}
.bg-purple-dark {
background: #99a9bf;
}
.bg-purple {
background: #d3dce6;
}
.bg-purple-light {
background: #e5e9f2;
}
</style>
The layout system uses a 24-column grid that helps create responsive layouts for different screen sizes.
Real-World Project: Task Management App
Let's put together what we've learned to create a simple task management application using Element Plus:
<template>
<el-container>
<el-header>
<h1>Task Manager</h1>
</el-header>
<el-main>
<el-row>
<el-col :span="24">
<el-form :inline="true" @submit.prevent="addTask">
<el-form-item>
<el-input v-model="newTask" placeholder="Add a new task" />
</el-form-item>
<el-form-item>
<el-select v-model="newTaskPriority" placeholder="Priority">
<el-option label="Low" value="low" />
<el-option label="Medium" value="medium" />
<el-option label="High" value="high" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" native-type="submit">Add Task</el-button>
</el-form-item>
</el-form>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-table :data="tasks" style="width: 100%">
<el-table-column prop="task" label="Task" />
<el-table-column prop="priority" label="Priority">
<template #default="scope">
<el-tag
:type="priorityTagType(scope.row.priority)"
size="small">
{{ scope.row.priority }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="status" label="Status">
<template #default="scope">
<el-switch
v-model="scope.row.completed"
@change="updateTaskStatus(scope.row)"
:inactive-text="'Pending'"
:active-text="'Completed'"
/>
</template>
</el-table-column>
<el-table-column label="Actions">
<template #default="scope">
<el-button
type="danger"
size="small"
@click="removeTask(scope.$index)"
:icon="Delete"
/>
</template>
</el-table-column>
</el-table>
</el-col>
</el-row>
<el-row v-if="tasks.length > 0">
<el-col :span="24">
<el-divider />
<el-statistic :value="completionRate" :precision="0" suffix="%">
<template #title>Task Completion Rate</template>
</el-statistic>
</el-col>
</el-row>
</el-main>
<el-footer>
<p>Task Manager built with Vue and Element Plus</p>
</el-footer>
</el-container>
</template>
<script setup>
import { ref, computed } from 'vue'
import { Delete } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'
const newTask = ref('')
const newTaskPriority = ref('medium')
const tasks = ref([
{ task: 'Learn Vue.js', priority: 'high', completed: true },
{ task: 'Master Element Plus', priority: 'medium', completed: false },
{ task: 'Build a project', priority: 'high', completed: false },
])
const completionRate = computed(() => {
if (tasks.value.length === 0) return 0
const completedCount = tasks.value.filter(task => task.completed).length
return Math.round((completedCount / tasks.value.length) * 100)
})
const priorityTagType = (priority) => {
const types = {
low: 'info',
medium: 'warning',
high: 'danger'
}
return types[priority]
}
const addTask = () => {
if (!newTask.value.trim()) {
ElMessage.warning('Task cannot be empty!')
return
}
tasks.value.push({
task: newTask.value,
priority: newTaskPriority.value,
completed: false
})
ElMessage.success('Task added successfully!')
newTask.value = ''
newTaskPriority.value = 'medium'
}
const updateTaskStatus = (task) => {
ElMessage({
message: `Task "${task.task}" marked as ${task.completed ? 'completed' : 'pending'}`,
type: task.completed ? 'success' : 'info',
})
}
const removeTask = (index) => {
const taskName = tasks.value[index].task
tasks.value.splice(index, 1)
ElMessage.success(`Task "${taskName}" removed successfully!`)
}
</script>
<style scoped>
.el-header, .el-footer {
background-color: #B3C0D1;
color: #333;
text-align: center;
line-height: 60px;
}
.el-main {
background-color: #E9EEF3;
color: #333;
padding: 20px;
}
.el-container {
margin-bottom: 40px;
min-height: 100vh;
}
.el-divider {
margin: 20px 0;
}
.el-form {
margin-bottom: 20px;
}
</style>
This example creates a complete task management application with the ability to:
- Add new tasks with priority levels
- View tasks in a table
- Toggle task completion status
- Delete tasks
- View task completion statistics
Theming and Customization
Element Plus provides extensive theming capabilities:
Basic CSS Variables Override
/* In your global CSS file */
:root {
--el-color-primary: #6750a4;
--el-color-success: #2e7d32;
--el-color-warning: #ed6c02;
--el-color-danger: #d32f2f;
--el-color-info: #0288d1;
}
Component Style Overrides
<style>
.custom-button.el-button--primary {
background-color: #8e44ad;
border-color: #8e44ad;
}
.custom-button.el-button--primary:hover {
background-color: #9b59b6;
border-color: #9b59b6;
}
</style>
Summary
Element Plus is a comprehensive UI library for Vue.js 3 that provides a wide range of components for building beautiful and responsive web applications. In this guide, we've covered:
- Installing and setting up Element Plus
- Using basic components like buttons and form elements
- Working with advanced components like tables and dialogs
- Creating layouts with the responsive grid system
- Building a real-world task management application
- Customizing themes and styles
Element Plus helps streamline front-end development by providing pre-designed, consistent components that work well together and follow modern design principles. Its extensive documentation and active community make it an excellent choice for Vue.js projects of any size.
Additional Resources
For further learning about Element Plus, consider exploring these resources:
Exercises
-
Basic Component Practice: Create a registration form using Element Plus form components like Input, Select, Radio, DatePicker, and Button.
-
Navigation Exercise: Build a responsive navigation menu with Element Plus that collapses on mobile screens.
-
Dashboard Challenge: Create a dashboard layout that includes a header, sidebar menu, content area, and footer. Add widgets like statistics cards, a data table, and a line chart.
-
Theme Customization: Create a custom theme by overriding Element Plus's default CSS variables and apply it to your application.
-
CRUD Application: Build a simple CRUD (Create, Read, Update, Delete) application for managing products using Element Plus components and Vue.js's reactivity system.
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)