Element Plus 组件库实战技巧与踩坑记录

张开发
2026/4/18 11:37:15 15 分钟阅读

分享文章

Element Plus 组件库实战技巧与踩坑记录
Element Plus 组件库实战技巧与踩坑记录分享我在Vue 3项目中使用Element Plus的经验技巧和踩坑记录前言Element Plus是Vue 3生态中最流行的UI组件库之一提供了丰富的组件和良好的设计。在开发博客项目的过程中我积累了很多使用Element Plus的经验和技巧也踩过一些坑。本文将分享这些实战经验。快速上手1. 安装与配置# 安装Element Plusnpminstallelement-plus# 安装图标库npminstallelement-plus/icons-vue// main.tsimport{createApp}fromvueimportElementPlusfromelement-plusimportelement-plus/dist/index.cssimport*asElementPlusIconsVuefromelement-plus/icons-vueimportAppfrom./App.vueconstappcreateApp(App)// 注册所有组件app.use(ElementPlus)// 注册所有图标for(const[key,component]ofObject.entries(ElementPlusIconsVue)){app.component(key,component)}app.mount(#app)2. 按需引入推荐为了减小包体积建议按需引入组件# 安装按需引入插件npminstall-Dunplugin-vue-components unplugin-auto-import// vite.config.tsimport{defineConfig}fromviteimportvuefromvitejs/plugin-vueimportAutoImportfromunplugin-auto-import/viteimportComponentsfromunplugin-vue-components/viteimport{ElementPlusResolver}fromunplugin-vue-components/resolversexportdefaultdefineConfig({plugins:[vue(),AutoImport({resolvers:[ElementPlusResolver()],}),Components({resolvers:[ElementPlusResolver()],}),],})这样配置后使用组件时会自动按需引入无需手动import。常用组件技巧1. 表单组件el-form深度验证template el-form refformRef :modelformData :rulesrules label-width120px el-form-item label标题 proptitle el-input v-modelformData.title / /el-form-item el-form-item label邮箱 propemail el-input v-modelformData.email / /el-form-item el-form-item label密码 proppassword el-input v-modelformData.password typepassword show-password / /el-form-item el-form-item el-button typeprimary clickhandleSubmit 提交 /el-button el-button clickhandleReset 重置 /el-button /el-form-item /el-form /template script setup langts import type { FormInstance, FormRules } from element-plus const formRef refFormInstance() const formData reactive({ title: , email: , password: }) const rules reactiveFormRules({ title: [ { required: true, message: 请输入标题, trigger: blur }, { min: 2, max: 50, message: 长度在 2 到 50 个字符, trigger: blur } ], email: [ { required: true, message: 请输入邮箱地址, trigger: blur }, { type: email, message: 请输入正确的邮箱地址, trigger: [blur, change] } ], password: [ { required: true, message: 请输入密码, trigger: blur }, { min: 6, message: 密码长度不能少于 6 位, trigger: blur } ] }) const handleSubmit async () { if (!formRef.value) return await formRef.value.validate((valid, fields) { if (valid) { // 验证通过提交表单 console.log(提交:, formData) } else { console.log(验证失败:, fields) } }) } const handleReset () { formRef.value?.resetFields() } /script动态表单template el-form :modelformData el-form-item v-for(item, index) in formData.items :keyindex :label项目 (index 1) el-input v-modelitem.value / el-button clickremoveItem(index) iconDelete typedanger 删除 /el-button /el-form-item el-button clickaddItem iconPlus 添加项目 /el-button /el-form /template script setup langts const formData reactive({ items: [{ value: }] }) const addItem () { formData.items.push({ value: }) } const removeItem (index: number) { formData.items.splice(index, 1) } /script2. 表格组件表格排序和筛选template el-table :datafilteredData :default-sort{ prop: date, order: descending } sort-changehandleSortChange el-table-column proptitle label标题 sortable / el-table-column propcategory label分类 :filterscategoryFilters :filter-methodfilterCategory / el-table-column propviews label浏览量 sortable / el-table-column propdate label日期 sortable / /el-table /template script setup langts const articles refArticle[]([]) const filteredData computed(() { return articles.value }) const categoryFilters [ { text: Vue, value: Vue }, { text: React, value: React }, { text: TypeScript, value: TypeScript } ] const filterCategory (value: string, row: Article) { return row.category value } const handleSortChange (sort: any) { console.log(排序改变:, sort) } /script表格分页template el-table :datapaginatedData !-- 列定义 -- /el-table el-pagination v-model:current-pagecurrentPage v-model:page-sizepageSize :totaltotal :page-sizes[10, 20, 50, 100] layouttotal, sizes, prev, pager, next, jumper size-changehandleSizeChange current-changehandleCurrentChange / /template script setup langts const currentPage ref(1) const pageSize ref(10) const total ref(0) const paginatedData computed(() { const start (currentPage.value - 1) * pageSize.value const end start pageSize.value return articles.value.slice(start, end) }) const handleSizeChange (size: number) { pageSize.value size } const handleCurrentChange (page: number) { currentPage.value page } /script3. 弹窗组件对话框嵌套template el-button clickshowDialog true打开对话框/el-button el-dialog v-modelshowDialog title父对话框 p这是父对话框的内容/p el-button clickshowChildDialog true 打开子对话框 /el-button el-dialog v-modelshowChildDialog title子对话框 append-to-body p这是子对话框的内容/p /el-dialog /el-dialog /template script setup langts const showDialog ref(false) const showChildDialog ref(false) /script注意嵌套对话框时子对话框需要添加append-to-body属性。4. 树形组件异步加载树template el-tree :propsdefaultProps :loadloadNode lazy show-checkbox / /template script setup langts const defaultProps { label: name, children: children, isLeaf: leaf } const loadNode async (node: Node, resolve: (data: TreeData[]) void) { if (node.level 0) { // 加载根节点 const data await loadRootNodes() resolve(data) } else { // 加载子节点 const data await loadChildNodes(node.data.id) resolve(data) } } const loadRootNodes async () { // 异步加载数据 return [ { name: 节点1, id: 1 }, { name: 节点2, id: 2 } ] } /script主题定制1. 使用CSS变量// styles/theme.scss :root { --el-color-primary: #409eff; --el-color-success: #67c23a; --el-color-warning: #e6a23c; --el-color-danger: #f56c6c; --el-color-info: #909399; } // 使用自定义主题 $--color-primary: var(--el-color-primary);2. SCSS变量覆盖// vite.config.tsimport{defineConfig}fromviteimportvuefromvitejs/plugin-vueimportElementPlusfromunplugin-element-plus/viteexportdefaultdefineConfig({plugins:[vue(),ElementPlus({// 使用scss样式useSource:true})]})// styles/element-variables.scss /* 改变主题色变量 */ $--color-primary: #1890ff; $--color-success: #52c41a; $--color-warning: #faad14; $--color-danger: #f5222d; $--color-info: #909399; /* 改变icon字体路径变量必需 */ $--font-path: ~element-plus/lib/theme-chalk/fonts; import ~element-plus/packages/theme-chalk/src/index;3. 暗黑模式template el-switch v-modelisDark changetoggleDark inline-prompt active-text暗 inactive-text亮 / /template script setup langts const isDark ref(false) const toggleDark (value: boolean) { if (value) { document.documentElement.classList.add(dark) } else { document.documentElement.classList.remove(dark) } } /script style /* 暗黑模式样式 */ html.dark { --el-bg-color: #141414; --el-text-color-primary: #e5eaf3; --el-border-color: #4c4d4f; --el-border-color-light: #414243; } /style性能优化1. 图标按需加载// utils/icons.tsimport{registerIcons}fromelement-plus/es/components/icon// 只注册需要的图标exportfunctionlazyRegisterIcons(){consticons[Edit,Delete,View,Download,Share,Star,Plus,Search,Home]// 使用requestIdleCallback在空闲时注册constidleCallbackwindow.requestIdleCallback||window.setTimeoutidleCallback((){registerIcons(icons)})}// main.tsimport{lazyRegisterIcons}from./utils/iconslazyRegisterIcons()2. 虚拟滚动template el-virtual-list :dataitems :height400 :item-size50 template #default{ item, index } div classitem {{ index }} - {{ item.name }} /div /template /el-virtual-list /template script setup langts import { ElVirtualList } from element-plus // 生成大量数据 const items Array.from({ length: 10000 }, (_, i) ({ id: i, name: Item ${i} })) /script踩坑记录1. Dialog关闭不触发事件问题点击遮罩层关闭Dialog时没有触发关闭事件。解决使用before-close属性el-dialog v-modelvisible :before-closehandleClose template #header span标题/span /template /el-dialog script setup langts const handleClose (done: () void) { // 执行关闭前的逻辑 done() } /script2. Table固定列错位问题表格固定列在滚动时出现错位。解决监听窗口大小变化调用doLayout方法template el-table reftableRef :datatableData el-table-column propdate label日期 fixed / el-table-column propname label姓名 / /el-table /template script setup langts const tableRef ref() onMounted(() { window.addEventListener(resize, () { tableRef.value?.doLayout() }) }) /script3. Select下拉框显示位置错误问题Select组件的下拉框在页面滚动后显示位置错误。解决使用popper-options配置el-select v-modelvalue :popper-options{ modifiers: [ { name: flip, options: { fallbackPlacements: [bottom-start, top-start] } } ] } el-option v-foritem in options :keyitem.value :labelitem.label :valueitem.value / /el-select4. DatePicker时间格式问题问题DatePicker返回的日期格式不符合预期。解决使用value-format属性el-date-picker v-modeldate typedatetime value-formatYYYY-MM-DD HH:mm:ss placeholder选择日期时间 /5. Upload组件上传失败问题Upload组件在某些情况下上传失败。解决正确处理on-success和on-error回调el-upload action/api/upload :on-successhandleSuccess :on-errorhandleError :before-uploadbeforeUpload el-button typeprimary上传文件/el-button /el-upload script setup langts const handleSuccess (response: any, file: any) { if (response.code 200) { ElMessage.success(上传成功) } else { ElMessage.error(response.message) } } const handleError (error: any) { ElMessage.error(上传失败 error.message) } const beforeUpload (file: File) { const isJPG file.type image/jpeg || file.type image/png const isLt2M file.size / 1024 / 1024 2 if (!isJPG) { ElMessage.error(只能上传JPG/PNG图片!) } if (!isLt2M) { ElMessage.error(图片大小不能超过2MB!) } return isJPG isLt2M } /script最佳实践1. 统一配置// config/element-plus.tsimport{ElConfigProvider}fromelement-plusimportzhCnfromelement-plus/es/locale/lang/zh-cnexportdefault{locale:zhCn,size:default,zIndex:3000}!-- App.vue -- template el-config-provider :localelocale router-view / /el-config-provider /template script setup langts import zhCn from element-plus/es/locale/lang/zh-cn const locale zhCn /script2. 封装常用组件!-- components/SearchInput.vue -- template el-input v-modelsearchText :placeholderplaceholder clearable clearhandleClear inputhandleInput template #prefix el-iconSearch //el-icon /template template #suffix el-button v-ifsearchText link iconClose clickhandleClear / /template /el-input /template script setup langts import { ref, watch } from vue interface Props { modelValue: string placeholder?: string } const props withDefaults(definePropsProps(), { placeholder: 请输入搜索内容 }) const emit defineEmits{ (e: update:modelValue, value: string): void (e: search, value: string): void }() const searchText ref(props.modelValue) watch(() props.modelValue, (val) { searchText.value val }) watch(searchText, (val) { emit(update:modelValue, val) }) const handleClear () { searchText.value emit(search, ) } const handleInput debounce((value: string) { emit(search, value) }, 300) /script3. 全局样式覆盖// styles/element-overrides.scss // 全局修改el-button样式 .el-button { border-radius: 4px; font-weight: 500; --primary { background-color: #1890ff; border-color: #1890ff; :hover { background-color: #40a9ff; border-color: #40a9ff; } } } // 修改el-dialog样式 .el-dialog { border-radius: 8px; overflow: hidden; .el-dialog__header { padding: 20px 20px 10px; border-bottom: 1px solid #f0f0f0; } .el-dialog__body { padding: 20px; } }总结Element Plus是一个功能强大、设计优秀的UI组件库掌握以下要点可以更好地使用它按需引入- 减小包体积主题定制- 符合项目风格性能优化- 图标懒加载、虚拟滚动踩坑经验- 了解常见问题和解决方案最佳实践- 封装常用组件、统一配置希望这些经验能帮助你在Vue 3项目中更好地使用Element Plus标签#ElementPlus #Vue3 #UI组件库 #前端 #实战技巧点赞❤️ 收藏⭐️ 评论你的支持是我创作的动力

更多文章