前言:在 Vue3 项目开发中,Element Plus 作为官方推荐的第三方组件库,凭借丰富的组件、良好的兼容性和美观的样式,成为中后台管理系统、常规业务页面开发的首选。但实际开发中,很多开发者会遇到两个核心问题:一是完整引入 Element Plus 导致打包体积过大,影响项目加载速度;二是组件原生功能无法完全匹配业务需求,重复开发相似逻辑导致代码冗余。本文基于 Vue3 + Vite + JavaScript 实战,详细讲解 Element Plus 两种按需引入方式(自动引入/手动引入)的配置流程,以及高频组件(按钮、表格、表单)的二次封装技巧。
一、前置准备:环境搭建与依赖安装
前提:已搭建 Vue3 + Vite 项目(若未搭建,执行 npm create vite@latest my-vue3-project -- --template vue 快速搭建,后续步骤一致),建议使用 pnpm 管理依赖,避免版本冲突。
1.1 安装核心依赖
首先安装 Element Plus 核心包,以及按需引入所需的辅助插件(自动引入方式必备),终端执行以下命令(三选一,推荐 pnpm):
bash
# npm 安装(稳定版)
npm install element-plus@2.7.0 --save
# 自动引入所需插件(必装,用于自动注册组件和样式)
npm install unplugin-auto-import unplugin-vue-components -D
# pnpm 安装(推荐,速度更快、依赖更稳定)
pnpm add element-plus@2.7.0
pnpm add unplugin-auto-import unplugin-vue-components -D
# yarn 安装
yarn add element-plus@2.7.0
yarn add unplugin-auto-import unplugin-vue-components -D
说明:Element Plus 2.7.0 版本兼容性最佳,避免使用 beta 版导致的组件异常;unplugin-auto-import 用于自动引入 Element Plus 的 API(如 ElMessage、ElMessageBox),unplugin-vue-components 用于自动引入组件和样式,无需手动编写 import 语句,大幅提升开发效率。
二、Element Plus 按需引入:两种方式详解(推荐自动引入)
Element Plus 提供「完整引入」和「按需引入」两种方式,完整引入虽配置简单,但会加载所有组件和样式,导致打包体积过大(生产环境不推荐);按需引入仅加载项目中使用的组件和样式,是企业级项目的首选方案,以下详解两种按需引入方式。
2.1 方式一:自动引入(推荐,零手动配置,适合大多数项目)
自动引入依赖于前文安装的两个插件,通过配置 Vite 插件,实现组件、API、样式的自动识别和注册,无需手动 import 任何组件,直接在模板中使用即可。
2.1.1 配置 Vite 插件
打开项目根目录的 vite.config.js 文件,修改配置如下(新增 AutoImport 和 Components 插件配置):
javascript
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// 引入自动引入相关插件
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
// 引入 Element Plus 解析器(用于识别 Element Plus 组件和 API)
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
export default defineConfig({
plugins: [
vue(),
// 自动引入 Element Plus API(如 ElMessage、ElMessageBox)
AutoImport({
resolvers: [ElementPlusResolver()],
// 可选:指定自动引入的API类型,默认包含所有
imports: ['vue', 'element-plus'],
// 可选:生成自动引入的声明文件,避免TS报错(JS项目可省略)
dts: 'src/auto-imports.d.ts'
}),
// 自动引入 Element Plus 组件和样式
Components({
resolvers: [
// 配置 Element Plus 解析器,自动识别组件并引入对应样式
ElementPlusResolver({
// 若需要自定义主题,设置 importStyle: 'sass'(后续主题定制会用到)
importStyle: 'css'
})
],
// 可选:生成组件声明文件(JS项目可省略)
dts: 'src/components.d.ts'
})
]
})
2.1.2 测试自动引入效果
配置完成后,无需在 main.js 中做任何额外配置,直接在任意 Vue 组件中使用 Element Plus 组件,示例如下(以 ElButton、ElInput 为例):
vue
<template>
<div class="demo">
<!-- 直接使用 Element Plus 组件,无需手动 import -->
<el-button type="primary" @click="showMessage"> primary按钮 </el-button>
<el-input placeholder="请输入内容" v-model="inputValue" style="width: 300px; margin-left: 20px;" />
</div>
</template>
<script setup>
// 无需手动 import ElMessage,自动引入
const inputValue = ref('')
const showMessage = () => {
ElMessage.success('自动引入测试成功!')
}
</script>
启动项目(npm run dev),可正常显示组件和样式,点击按钮会弹出成功提示,说明自动引入配置生效。
补充:Vue3 CLI 项目配置差异------将上述插件配置写入 vue.config.js 文件,其余步骤一致,插件用法完全相同。
2.2 方式二:手动引入(灵活可控,适合特殊场景)
若项目需严格控制引入的组件和样式,或不希望使用自动引入插件,可采用手动引入方式,按需导入所需组件和对应样式,步骤如下:
2.2.1 单个组件手动引入(示例)
在需要使用组件的 Vue 文件中,手动 import 组件和对应样式,示例如下(以 ElButton、ElDialog 为例):
vue
<template>
<div class="demo">
<el-button type="success" @click="openDialog"> 打开弹窗 </el-button>
<el-dialog v-model="visible" title="手动引入弹窗" width="500px">
<p>手动引入 Element Plus 组件测试</p>
</el-dialog>
</div>
</template>
<script setup>
import { ref } from 'vue'
// 手动引入组件和对应样式
import { ElButton, ElDialog } from 'element-plus'
import 'element-plus/es/components/button/style/css'
import 'element-plus/es/components/dialog/style/css'
const visible = ref(false)
const openDialog = () => {
visible.value = true
}
</script>
2.2.2 全局手动引入(批量注册)
若多个组件需使用同一组件,可在 main.js 中批量引入并全局注册,避免重复 import,示例如下:
javascript
// main.js
import { createApp } from 'vue'
import App from './App.vue'
// 批量手动引入所需组件
import { ElButton, ElInput, ElMessage } from 'element-plus'
// 批量引入对应样式
import 'element-plus/es/components/button/style/css'
import 'element-plus/es/components/input/style/css'
const app = createApp(App)
// 全局注册组件
app.component('ElButton', ElButton)
app.component('ElInput', ElInput)
// 全局挂载 API(如 ElMessage)
app.config.globalProperties.$message = ElMessage
app.mount('#app')
说明:手动引入的核心是「组件与样式一一对应」,若遗漏样式引入,组件会显示异常;相比自动引入,手动引入更灵活,但需手动维护组件和样式的引入,适合组件使用较少的项目。
2.3 按需引入避坑指南
- 自动引入插件会自动生成
auto-imports.d.ts和components.d.ts两个声明文件,无需手动修改,若删除会导致 TS 项目报错(JS 项目可忽略)。 - 手动引入时,需注意样式路径的正确性,Element Plus 2.x 版本的样式路径为
element-plus/es/components/组件名/style/css,避免写错路径导致样式失效。 - 若项目使用 Sass 自定义主题,自动引入时需将
ElementPlusResolver中的importStyle改为'sass',并配置 Sass 预处理器(后续主题定制会详细讲解)。
三、Element Plus 二次封装:高频组件实战(企业级规范)
Element Plus 原生组件虽功能完善,但在实际业务中,往往需要根据项目需求统一样式、补充通用逻辑(如按钮权限控制、表格分页统一、表单校验封装),二次封装的核心是「复用逻辑、统一规范、降低维护成本」,且不破坏原生组件的所有功能(支持透传 props、事件、插槽)。以下讲解 3 个高频组件的二次封装实战。
3.1 二次封装 ElButton:统一样式 + 权限控制
业务场景:项目中按钮需统一尺寸、圆角、颜色,部分按钮需根据用户权限显示/隐藏,避免重复编写样式和权限判断逻辑。
3.1.1 封装组件(src/components/MyButton.vue)
vue
<template>
<!-- 透传所有 props、事件,不破坏原生功能 -->
<el-button
v-if="hasPermission"
:size="size"
:type="type"
:round="round"
v-bind="$attrs"
v-on="$listeners"
class="my-button"
>
<!-- 透传插槽 -->
<slot></slot>
</el-button>
</template>
<script setup>
import { defineProps, withDefaults, useAttrs, useListeners } from 'vue'
// 定义 props,继承 ElButton 原生 props,新增权限相关 props
const props = withDefaults(defineProps({
// 按钮类型,继承 ElButton 原生类型
type: {
type: String,
default: 'primary'
},
// 按钮尺寸,统一默认值为 small
size: {
type: String,
default: 'small'
},
// 是否圆角,统一默认开启
round: {
type: Boolean,
default: true
},
// 权限标识(用于控制按钮显示/隐藏)
permission: {
type: String,
default: ''
}
}), {})
// 模拟权限判断(实际项目中可对接后端权限接口)
const hasPermission = () => {
// 假设用户拥有的权限列表(实际从 Pinia/Store 中获取)
const userPermissions = ['add', 'edit', 'delete', 'view']
// 若未设置 permission,默认显示
if (!props.permission) return true
// 匹配权限,有则显示,无则隐藏
return userPermissions.includes(props.permission)
}
// 透传 attrs 和 listeners(确保原生功能正常使用)
const $attrs = useAttrs()
const $listeners = useListeners()
</script>
<style scoped>
/* 统一按钮样式,覆盖原生样式,适配项目需求 */
.my-button {
margin: 0 4px;
font-size: 14px;
/* 统一圆角大小 */
border-radius: 4px !important;
/* hover 效果优化 */
&:hover {
opacity: 0.9;
}
}
</style>
3.1.2 组件使用示例
vue
<template>
<div class="button-demo">
<!-- 基础使用(默认样式、无权限控制) -->
<my-button> 普通按钮 </my-button>
<!-- 自定义类型和权限(只有拥有 add 权限才显示) -->
<my-button type="success" permission="add" @click="handleAdd"> 新增 </my-button>
<!-- 自定义尺寸,透传原生 disabled 属性 -->
<my-button type="danger" size="mini" disabled permission="delete"> 删除 </my-button>
</div>
</template>
<script setup>
// 无需手动引入 ElButton,直接使用封装后的 MyButton
import MyButton from '@/components/MyButton.vue'
const handleAdd = () => {
ElMessage.success('新增操作')
}
</script>
优势:统一按钮样式和默认配置,权限控制逻辑复用,后续修改按钮样式或权限规则,只需修改 MyButton 组件,无需改动所有使用场景。
3.2 二次封装 ElTable:统一分页 + 通用操作
业务场景:中后台项目中,表格是高频组件,几乎所有表格都需要分页、勾选、编辑/删除操作,二次封装可统一分页逻辑、表格样式,减少重复代码,核心思路是「配置化驱动表格渲染」,适配不同业务场景。
3.2.1 封装组件(src/components/MyTable.vue)
vue
<template>
<div class="my-table">
<!-- 表格主体,透传所有 props 和事件 -->
<el-table
v-bind="$attrs"
v-on="$listeners"
:data="tableData"
border
stripe
:loading="loading"
style="width: 100%"
>
<!-- 勾选列(可选,通过 showSelect 控制) -->
<el-table-column
v-if="showSelect"
type="selection"
width="55"
align="center"
/>
<!-- 序号列(可选,通过 showIndex 控制) -->
<el-table-column
v-if="showIndex"
type="index"
label="序号"
width="60"
align="center"
/>
<!-- 动态渲染表格列(通过 columns 配置) -->
<el-table-column
v-for="(col, index) in columns"
:key="index"
v-bind="col"
:label="col.label"
:prop="col.prop"
:width="col.width"
:align="col.align || 'left'"
>
<!-- 透传列插槽,支持自定义单元格内容 -->
<slot :name="`col-${col.prop}`" v-slot="scope">
{{ scope.row[col.prop] }}
</slot>
</el-table-column>
<!-- 操作列(可选,通过 showAction 控制) -->
<el-table-column
v-if="showAction"
label="操作"
width="180"
align="center"
>
<slot name="action" v-slot="scope">
<my-button size="mini" type="primary" @click="handleEdit(scope.row)"> 编辑 </my-button>
<my-button size="mini" type="danger" @click="handleDelete(scope.row)"> 删除 </my-button>
</slot>
</el-table-column>
</el-table>
<!-- 分页组件(可选,通过 showPagination 控制) -->
<div class="table-pagination" v-if="showPagination">
<el-pagination
v-model:current-page="currentPage"
v-model:page-size="pageSize"
:total="total"
:page-sizes="[10, 20, 50, 100]"
layout="total, sizes, prev, pager, next, jumper"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</div>
</div>
</template>
<script setup>
import { defineProps, withDefaults, defineEmits, ref } from 'vue'
import MyButton from './MyButton.vue'
// 定义 props,支持配置化渲染
const props = withDefaults(defineProps({
// 表格数据
tableData: {
type: Array,
default: () => []
},
// 表格列配置(核心,格式:[{ label: '列名', prop: '字段名', width: 100 }])
columns: {
type: Array,
default: () => []
},
// 总条数(分页用)
total: {
type: Number,
default: 0
},
// 是否显示勾选列
showSelect: {
type: Boolean,
default: false
},
// 是否显示序号列
showIndex: {
type: Boolean,
default: true
},
// 是否显示操作列
showAction: {
type: Boolean,
default: true
},
// 是否显示分页
showPagination: {
type: Boolean,
default: true
},
// 当前页码
currentPage: {
type: Number,
default: 1
},
// 每页条数
pageSize: {
type: Number,
default: 10
},
// 是否加载中
loading: {
type: Boolean,
default: false
}
}), {})
// 定义事件,向父组件传递操作信号
const emit = defineEmits([
'size-change', // 每页条数改变
'current-change', // 当前页码改变
'edit', // 编辑操作
'delete' // 删除操作
])
// 编辑操作
const handleEdit = (row) => {
emit('edit', row)
}
// 删除操作
const handleDelete = (row) => {
emit('delete', row)
}
// 每页条数改变
const handleSizeChange = (val) => {
emit('size-change', val)
}
// 当前页码改变
const handleCurrentChange = (val) => {
emit('current-change', val)
}
</script>
<style scoped>
.my-table {
margin-bottom: 20px;
}
.table-pagination {
display: flex;
justify-content: flex-end;
margin-top: 16px;
}
/* 统一表格样式,适配项目需求 */
::v-deep .el-table th {
background-color: #f5f7fa;
font-weight: 600;
font-size: 14px;
}
::v-deep .el-table td {
font-size: 13px;
}
</style>
3.2.2 组件使用示例
vue
<template>
<my-table
:table-data="tableData"
:columns="tableColumns"
:total="total"
:loading="loading"
show-select
@current-change="handleCurrentChange"
@size-change="handleSizeChange"
@edit="handleEdit"
@delete="handleDelete"
>
<!-- 自定义单元格内容(插槽用法) -->
<template #col-status="scope">
<el-tag :type="scope.row.status === 1 ? 'success' : 'danger'">
{{ scope.row.status === 1 ? '启用' : '禁用' }}
</el-tag>
</template>
<!-- 自定义操作列(覆盖默认操作按钮) -->
<template #action="scope">
<my-button size="mini" type="primary" @click="handleEdit(scope.row)"> 编辑 </my-button>
<my-button size="mini" type="warning" @click="handleView(scope.row)"> 查看 </my-button>
</template>
</my-table>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import MyTable from '@/components/MyTable.vue'
// 表格列配置(根据业务需求自定义)
const tableColumns = ref([
{ label: '用户名', prop: 'username', width: 120 },
{ label: '手机号', prop: 'phone', width: 140 },
{ label: '状态', prop: 'status', width: 100 },
{ label: '创建时间', prop: 'createTime', width: 180 }
])
// 表格数据(实际项目中从接口获取)
const tableData = ref([])
const total = ref(0)
const loading = ref(false)
const currentPage = ref(1)
const pageSize = ref(10)
// 模拟接口请求,获取表格数据
const getTableData = () => {
loading.value = true
// 实际项目中替换为真实接口请求(如 axios)
setTimeout(() => {
tableData.value = [
{ username: '张三', phone: '13800138000', status: 1, createTime: '2024-01-01 10:00:00' },
{ username: '李四', phone: '13900139000', status: 0, createTime: '2024-01-02 10:00:00' }
]
total.value = 20
loading.value = false
}, 1000)
}
// 页码改变
const handleCurrentChange = (val) => {
currentPage.value = val
getTableData()
}
// 每页条数改变
const handleSizeChange = (val) => {
pageSize.value = val
currentPage.value = 1
getTableData()
}
// 编辑操作
const handleEdit = (row) => {
console.log('编辑', row)
}
// 查看操作
const handleView = (row) => {
console.log('查看', row)
}
// 删除操作
const handleDelete = (row) => {
console.log('删除', row)
}
// 页面挂载时获取数据
onMounted(() => {
getTableData()
})
</script>
优势:通过配置 columns 快速渲染表格,统一分页和操作逻辑,支持插槽自定义单元格和操作列,适配不同业务场景,后续新增表格页面,只需配置 columns 和请求接口即可,大幅提升开发效率。
3.3 二次封装 ElForm:统一校验 + 简化配置
业务场景:表单是项目中不可或缺的组件,原生 ElForm 需编写大量 el-form-item 标签和校验规则,二次封装可通过配置化生成表单,统一校验规则和样式,简化代码,核心思路是「JSON 配置驱动表单渲染」,支持复杂交互和规则校验。
3.3.1 封装组件(src/components/MyForm.vue)
vue
<template>
<el-form
v-bind="$attrs"
v-on="$listeners"
:model="formModel"
:rules="formRules"
ref="formRef"
class="my-form"
:label-width="labelWidth"
>
<el-form-item
v-for="(item, index) in formItems"
:key="index"
:label="item.label"
:prop="item.prop"
:required="item.required || false"
:span="item.span || 12"
>
<!-- 动态渲染表单组件,根据 type 区分 -->
<component
:is="getComponent(item.type)"
v-model="formModel[item.prop]"
v-bind="item.props || {}"
:placeholder="item.placeholder || `请输入${item.label}`"
/>
</el-form-item>
<!-- 表单操作按钮(可选,通过 showBtn 控制) -->
<el-form-item v-if="showBtn" :span="24" class="form-btn">
<my-button type="primary" @click="handleSubmit"> 提交 </my-button>
<my-button type="default" @click="handleReset" style="margin-left: 10px;"> 重置 </my-button>
</el-form-item>
</el-form>
</template>
<script setup>
import { defineProps, withDefaults, defineEmits, ref, computed } from 'vue'
import MyButton from './MyButton.vue'
// 引入 Element Plus 表单相关组件
import { ElInput, ElSelect, ElOption, ElDatePicker, ElInputNumber } from 'element-plus'
// 定义表单组件映射(根据 type 匹配对应组件)
const componentMap = {
input: ElInput,
select: ElSelect,
date: ElDatePicker,
number: ElInputNumber
}
// 定义 props,支持配置化生成表单
const props = withDefaults(defineProps({
// 表单数据模型
formModel: {
type: Object,
default: () => {}
},
// 表单项目配置(核心)
formItems: {
type: Array,
default: () => []
},
// 表单校验规则
formRules: {
type: Object,
default: () => {}
},
// 标签宽度
labelWidth: {
type: String,
default: '100px'
},
// 是否显示操作按钮
showBtn: {
type: Boolean,
default: true
}
}), {})
// 定义事件,向父组件传递提交和重置信号
const emit = defineEmits(['submit', 'reset'])
// 获取表单组件(根据 type 匹配)
const getComponent = (type) => {
return componentMap[type] || ElInput // 默认使用 Input 组件
}
// 表单 ref,用于校验
const formRef = ref(null)
// 提交表单(带校验)
const handleSubmit = () => {
formRef.value.validate((isValid) => {
if (isValid) {
emit('submit', props.formModel)
}
})
}
// 重置表单
const handleReset = () => {
formRef.value.resetFields()
emit('reset')
}
</script>
<style scoped>
.my-form {
width: 100%;
margin-bottom: 20px;
}
.form-btn {
display: flex;
justify-content: flex-start;
margin-top: 16px;
}
/* 统一表单样式 */
::v-deep .el-form-item {
margin-bottom: 16px;
}
::v-deep .el-input, ::v-deep .el-select, ::v-deep .el-date-picker {
width: 100%;
}
</style>
3.3.2 组件使用示例
vue
<template>
<my-form
:form-model="formModel"
:form-items="formItems"
:form-rules="formRules"
@submit="handleFormSubmit"
@reset="handleFormReset"
/>
</template>
<script setup>
import { ref } from 'vue'
import MyForm from '@/components/MyForm.vue'
// 表单数据模型
const formModel = ref({
username: '',
phone: '',
gender: '',
age: '',
joinTime: ''
})
// 表单项目配置(根据业务需求自定义)
const formItems = ref([
{
label: '用户名',
prop: 'username',
type: 'input',
required: true,
placeholder: '请输入用户名'
},
{
label: '手机号',
prop: 'phone',
type: 'input',
required: true,
placeholder: '请输入手机号',
props: {
maxLength: 11,
clearable: true
}
},
{
label: '性别',
prop: 'gender',
type: 'select',
required: true,
props: {
clearable: true
},
// 下拉框选项(通过 props 传递)
props: {
options: [
{ label: '男', value: 'male' },
{ label: '女', value: 'female' }
]
}
},
{
label: '年龄',
prop: 'age',
type: 'number',
props: {
min: 18,
max: 60,
step: 1
}
},
{
label: '入职时间',
prop: 'joinTime',
type: 'date',
props: {
type: 'date',
format: 'YYYY-MM-DD'
}
}
])
// 表单校验规则(统一配置,支持自定义校验)
const formRules = ref({
username: [
{ required: true, message: '请输入用户名', trigger: 'blur' },
{ min: 3, max: 10, message: '用户名长度在 3-10 之间', trigger: 'blur' }
],
phone: [
{ required: true, message: '请输入手机号', trigger: 'blur' },
{ pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号', trigger: 'blur' }
],
gender: [
{ required: true, message: '请选择性别', trigger: 'change' }
]
})
// 表单提交
const handleFormSubmit = (formData) => {
console.log('表单提交数据:', formData)
// 实际项目中对接接口提交数据
ElMessage.success('表单提交成功!')
}
// 表单重置
const handleFormReset = () => {
console.log('表单重置')
}
</script>
优势:通过配置 formItems 快速生成表单,统一校验规则和样式,支持多种表单组件(输入框、下拉框、日期选择器等),后续修改表单字段或校验规则,只需修改配置,无需改动模板代码,大幅提升开发效率和可维护性。
四、进阶优化:主题定制与常见问题排查
4.1 自定义主题(可选,适配项目视觉风格)
Element Plus 支持通过 Sass 自定义主题,修改默认颜色、字体等样式,步骤如下(基于自动引入方式):
javascript
// 1. 安装 Sass 依赖(若未安装)
pnpm add sass -D
// 2. 新建主题文件:src/styles/element-theme.scss
// 覆盖 Element Plus 默认变量(仅修改需要的,其余保持默认)
@forward 'element-plus/theme-chalk/src/common/var.scss' with (
$colors: (
'primary': (
'base': #1677ff, // 主色调(可替换为项目主色)
),
'success': (
'base': #52c41a,
),
'warning': (
'base': #faad14,
),
'danger': (
'base': #f5222d,
)
)
);
// 3. 修改 vite.config.js 配置,引入主题文件
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 { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
export default defineConfig({
plugins: [
vue(),
AutoImport({
resolvers: [ElementPlusResolver()]
}),
Components({
resolvers: [
// 改为 sass 引入,适配主题定制
ElementPlusResolver({ importStyle: 'sass' })
]
})
],
// 配置 Sass 预处理器,自动引入主题变量
css: {
preprocessorOptions: {
sass: {
additionalData: `@use "@/styles/element-theme.scss" as *;`
}
}
}
})
配置完成后,重启项目,即可看到主题颜色已修改,所有 Element Plus 组件会自动适配新的主题样式。
4.2 常见问题排查
- 问题1:自动引入组件后,样式不生效? 解决方案:检查 vite.config.js 中 ElementPlusResolver 的 importStyle 配置,确保为 'css' 或 'sass';检查插件是否安装成功,重启项目尝试。
- 问题2:二次封装组件后,原生 props 或事件无法使用? 解决方案:确保在封装组件中使用
v-bind="$attrs"和v-on="$listeners"透传所有原生 props 和事件,避免遗漏。 - 问题3:表单校验不生效? 解决方案:确保 form-item 的 prop 属性与 formModel 中的字段名一致;校验规则的 trigger 与组件事件匹配(如 input 用 blur,select 用 change)。
- 问题4:自定义主题后,样式异常? 解决方案:确保 Sass 依赖安装成功;主题文件路径配置正确;ElementPlusResolver 的 importStyle 已改为 'sass'。
五、总结
本文详细讲解了 Vue3 与 Element Plus 的联动实战,核心覆盖「按需引入」和「二次封装」两大核心需求:按需引入通过自动/手动两种方式,有效优化项目打包体积,提升加载速度;二次封装聚焦高频组件,通过配置化驱动和逻辑复用,解决代码冗余、维护困难的问题,同时不破坏 Element Plus 原生组件的功能。