Vue3-ElementPlus
目录
ElementPlus按需导入
Icon图标导入
组件中英文切换
ElementPlus常见组件
Layout布局
Form表单
表单校验
自定义校验规则
表单提交预校验(Form Exposes)
重置表单
行内表单
表单组件
多选组合
日期选择器
年份选择器和月份选择器联动
禁用某些年份、月份或日期
input输入框
textarea文本域
插槽自定义label
消息提示
Container 布局容器
编辑
Menu菜单
下拉菜单
指令事件
消息弹出框
卡片
表格
序号
自定义列
Table插槽
整行的点击事件
设置当前选中行高亮颜色
按钮
加载
空状态
对话框
Link链接
分页
抽屉
上传
单选框
弹窗
文件上传
统计组件
ElementPlus按需导入
1.安装
pnpm add element-plus全局导入:
import ElementPlus from 'element-plus' import 'element-plus/dist/index.css' app.use(ElementPlus)2.配置按需导入:
官方文档:快速开始 | Element Plus
按照官网按需导入中的自动导入步骤来进行
pnpm add -D unplugin-vue-components unplugin-auto-import观察Vite代码与原vite文件的差别,将原vite文件中没有的,复制粘贴到合适的位置
3.直接使用组件,样式就是element-Plus的
4.默认components下的文件也会被自动注册
不需要再导入也能使用
5.使用某组件时显示:
可能时安装的版本不够高,需要安装组件所属版本的更高阶
pnpm add element-plus@latest查看当前版本:
pnpm info element-plus versionIcon图标导入
1.安装
pnpm i @element-plus/icons-vue官网参考: Icon 图标 | Element Plus
2.使用
先导入
import { 图标名 } from '@element-plus/icons-vue'在el-input输入框里使用
<el-input :prefix-icon="Lock"></el-input>组件中英文切换
全局配置中文
<script setup> import zhCn from 'element-plus/dist/locale/zh-cn.mjs' </script> <template> <div> <!--App.vue只需要留一个路由出口router-view即可--> <el-config-provider :locale="zhCn"> <router-view></router-view> </el-config-provider> </div> </template>ElementPlus常见组件
官方文档:Button 按钮 | Element Plus
Layout布局
类似栅格网格系统,el-row表示一行,一行分成24份;el-col在el-row中使用,el-col表示列,其中:span="x"代表在一行中占x份,:offset="x"代表左侧margin的份数
Form表单
el-form为整个表单组件;el-form-item为表单的一行,其中label="xx"设置行标签
el-input加上show-password可以实现切换密码可见
<el-input type="password" show-password></el-input>表单校验
校验规则:
(1)在el-form上配置:model="ruleFormRef"绑定的是整个form的数据对象
(2)在el-form上配置:rules="rules"绑定的是整个rules规则对象
(3)在el-form-item上配置props="name"配置生效的是哪个校验规则(和rules中的字段对应)
(4)表单元素上配置v-model="ruleForm.name"给表单元素绑定form的子属性
label-width="宽度"控制前面标题的宽度,方便后面的内容对齐,不能写auto会控制台警告
const formModel = ref({ username: '', password: '', repassword: '', telphone: '' }) //整个表单的校验规则 const rules = { username: [ { required: true, //非空校验 message: '请输入用户名', //消息提示 trigger: 'blur' //触发时机,两个值:blue表示失去焦点,一般在input组件中使;change为值改变,一般在选择框中使用 }, { min: 5, //长度限制 max: 10, message: '用户名必须是5-10位的字符', trigger: 'blur' } ], password: [ { required: true, message: '请输入密码', trigger: 'blur' }, { pattern: /^\S{6,15}$/, //正则表达式 \S非空字符 message: '密码必须是6-15位的非空字符', trigger: 'blur' } ], telphone: [ { pattern: /^[0-9]*$/, message: '请输入纯数字手机号码', trigger: 'blur' } ] }切换页面(例如语言切换)会自动触发校验规则,用户体验感差
优化方法:给el-form组件添加
:validate-on-rule-change="false"<el-form :model="ruleForm" :rules="rules" :validate-on-rule-change="false"> </el-form>自定义校验规则
validator: (rule, value, callback)
(1)rule 当前校验规则相关的信息
(2)value 所校验的表单元素目前的表单值
(3)callback 无论成功还是失败,都需要 callback 回调
--callback()校验成功
--callback(new Error(错误信息)) 校验失败
默认是实时触发,要修改成失焦触发
const rules = { repassword: [ { validator: (rule, value, callback) => { if (value !== formModel.value.password) { callback(new Error('两次输入的密码不一致')) } else { callback() //校验成功,也需要callback } }, trigger: 'blur' } ] }表单提交预校验(Form Exposes)
首先需要获取form组件
<script setup> import { ref } from 'vue' //获取dom元素 const form = ref() </script> <template> <el-form ref="form"></el-form> </template>为提交按钮添加点击事件register
const register = async () => { //注册成功之前,先进行校验,校验成功->请求,校验失败->自动提示 await form.value.validate() console.log('开始注册请求') }重置表单
this.$refs.表单ref名.clearValidate()//移除整个表单的校验结果 this.$refs.表单ref名.clearValidate('prop属性')//移除某个prop属性的校验结果表单ref名.value.resetFields()//将表单的所有字段重置为初始值同时移除表单的校验结果注:只会重置带有prop属性的项,并且最外层el-form要绑定上v-model,里面的每个小项也要和最外层v-model里的小项对应上
表单需要先渲染出来才能使用,有时候会显示报错
dialogVisible.value控制子组件的显示,在子组件打开时重置一下表单
await nextTick()是等表单渲染完成后再触发下面的
watch( () => dialogVisible.value, async (val) => { if (!val) return await nextTick() formRef.value?.resetFields() } )行内表单
<el-form inline></el-form>表单组件
多选组合
const couponCheckList = ref() <el-checkbox-group v-model="couponCheckList"> <div v-for="coupon in couponListData.data.valid_coupons" :key="coupon.coupon_code" > <el-checkbox :checked="true" :label="coupon.coupon_code" :value="coupon.coupon_code" @change="isCheck = true" /> </div> </el-checkbox-group>日期选择器
<el-date-picker v-model="applyDate" type="daterange" range-separator="到" start-placeholder="开始日期" end-placeholder="结束日期" :teleported="false" value-format="YYYY-MM-DD" />value-format设置存储的日期格式,设置了这个之后v-model里存储的值也是对应的,不然还需要修改格式
format是设置在页面里显示的格式
年份选择器和月份选择器联动
<el-form-item label="年份"> <el-date-picker v-model="year" type="year" :teleported="false" @change="handleYearChange" /> </el-form-item> <el-form-item label="月份"> <el-date-picker class="monthSelecter" v-model="month" type="month" :teleported="false" format="MM" @change="handleMonthChange" /> </el-form-item>const year = ref() const month = ref() const handleYearChange = (value) => { // 年份选择器选择后把年份赋值给月份选择器 if (value && month.value) { const newDate = new Date(month.value) // 复制当前日期对象 newDate.setFullYear(value.getFullYear()) // 设置新的年份 month.value = newDate } } const handleMonthChange = (value) => { // 月份选择器选择后把年份赋值给年份选择器 if (value) { year.value = String(value.getFullYear()) } }获取绑定年份选择器所选择的具体年份:
new Date(year.value).getFullYear()禁用某些年份、月份或日期
禁用某些年份:
const disabledDate = (time) => { // 获取当前日期的年份 const year = new Date(time).getFullYear() // 禁用2018年以前和明年后的年份 return year < 2018 || year > new Date().getFullYear() + 1 } <el-date-picker v-model="year" type="year" :teleported="false" :disabled-date="disabledDate" />只允许选择今天、昨天、前天:
const disabledDate = (time) => { // 获取今天的日期 const today = new Date() // 设置时间为0点,确保比较时不考虑时间部分 today.setHours(0, 0, 0, 0) // 获取昨天和前天的日期 const yesterday = new Date(today) yesterday.setDate(today.getDate() - 1) const twoDaysAgo = new Date(today) twoDaysAgo.setDate(today.getDate() - 2) // 如果日期不在今天、昨天和前天之内,则禁用该日期 return ( time.getTime() > today.getTime() || time.getTime() < twoDaysAgo.getTime() ) }获取当年年份:
new Date().getFullYear()input输入框
设置为只读,但是可编辑;disabled是不可编辑不可复制
textarea文本域
设置自适应高度,设置autosize可根据文本高度自适应
:autosize="{ minRows: 0 }"select选择器
multiple:多选
collapse-tags:多选时折叠除第一个的标签
max-collapse-tags="数量":设置前几个数量的标签不折叠
使用插槽自定义显示的内容:显示所选择的value值也就是wh_code
<el-select style="width: 450px" v-model="formData.selectStore" multiple :teleported="false" > <el-option v-for="item in shopList" :label="item.wh_code + ' ' + item.code" :value="item.wh_code" :key="item.wh_code" /> <template #label="{ value }"> {{ value }} </template> </el-select>插槽自定义label
<el-form-item label="一级审批邮箱" prop="firstEmail"> <template v-slot:label> <div style="display: grid"> <span style="line-height: 10px">一级审批邮箱 </span> <span style="color: rgba(0, 0, 0, 0.45)"> (小区经理) </span> </div> </template> <el-input v-model="params.firstEmail" /> </el-form-item>消息提示
ElMessage({ message: '成功', type: 'success', }) 或 ElMessage.success('成功')错误:‘ElMessage’ is not defined.
解决:如果使用的是按需导入,import ElMessage就会导致失效,应该在.eslintrc.cjs文件中添加语句声明全局变量名
globals: { ElMessage: 'readonly', ElMessageBox: 'readonly', ElLoading: 'readonly' }Container 布局容器
Menu菜单
el-menu为整个菜单组件,其中active-text-color代表选中时的颜色,:default-active="$route.path"配置默认高亮的菜单项,router开启就可以点击跳转写在el-menu-item的index中的路径
el-menu-item为菜单项
<el-menu active-text-color="#ffd04b" background-color="#232323" :default-active="$route.path" text-color="#fff" router > <el-menu-item index="/article/channel"> <el-icon><Management /></el-icon> <span>文章分类</span> </el-menu-item> <el-menu-item index="/article/manage"> <el-icon><Promotion /></el-icon> <span>文章管理</span> </el-menu-item> <el-sub-menu index="/user"> <!--多级菜单的标题 - 具名插槽title--> <template #title> <el-icon><UserFilled /></el-icon> <span>个人中心</span> </template> <!--展开的内容 - 默认插槽--> <el-menu-item index="/user/profile"> <el-icon><User /></el-icon> <span>基本资料</span> </el-menu-item> <el-menu-item index="/user/avatar"> <el-icon><Crop /></el-icon> <span>更换头像</span> </el-menu-item> <el-menu-item index="/user/password"> <el-icon><EditPen /></el-icon> <span>重置密码</span> </el-menu-item> </el-sub-menu> </el-menu>下拉菜单
指令事件
消息弹出框
import { ElMessageBox } from 'element-plus'ElMessageBox.confirm('你确认要进行退出么', '温馨提示', { type: 'warning', confirmButtonText: '确认', cancelButtonText: '取消', dangerouslyUseHTMLString: true//提示文字可以使用HTML样式,比如使用换行符<br/> })注意:如果使用的是按需导入,import ElMessage就会导致失效,应该在.eslintrc.cjs文件中添加语句声明全局变量名
globals: { ElMessage: 'readonly', ElMessageBox: 'readonly', ElLoading: 'readonly' }点击取消或右上角×时,控制台会弹出报错
需要增加.catch语句
ElMessageBox.confirm('你确认要进行退出么', '温馨提示', { type: 'warning', confirmButtonText: '确认', cancelButtonText: '取消' }) .then(() => { }) .catch(() => { })卡片
<template> <el-card class="page-container"> <template #header> <div class="header"> <span>文件传送</span> <div class="extra"> <el-button type="primary">选择文件</el-button> </div> </div> </template> <slot></slot> </el-card> </template> <style lang="scss" scoped> .page-container { min-height: 100%; box-sizing: border-box; .header { display: flex; justify-content: space-between; align-items: center; } } </style>表格
el-table-column是一列,其中label是标题,prop是去对象中找对应的属性做渲染,width是宽度
表格中数据不显示:1)绑定的数据是不是响应式的 2)有没有加setup语法糖
序号
<el-table-column lable="序号" type="index"></el-table-column>自定义列
scope.row可以拿到行信息,scope.row.属性名可以拿到某行信息里的,scope.$index是下标
或者函数传递参数
<el-table-column label="操作" width="150"> <template #default="{ row, $index }"> <el-button @click="onEditChannel(row, $index)" :icon="Edit" circle type="primary" plain > </el-button> <el-button @click="onDelChannel(row, $index)" :icon="Delete" circle type="danger" plain > </el-button> </template> </el-table-column>根据某列的值显示对应的内容
<el-table-column label="申请状态" prop="status"> <template #default="{ row }"> <!-- 使用 v-slot 语法 --> <span v-if="row.status === 0">未审批</span> <span v-else>已重启</span> </template> </el-table-column>Table插槽
<template #empty>暂无数据</template>整行的点击事件
@row-click="handleRowClick"const handleRowClick = (row, column, event) => { console.log('行点击事件触发', row); const rowIndex = 表格数组.indexOf(row) // 使用indexOf获取行数据在数组中的位置 console.log('所点击的行的index', rowIndex) };双击事件
@row-dblclick="RowDbclick" const RowDbclick = (row) => {}如果在表格中增加操作栏触发点击事件,会和这个功能冲突,那么可以这样写点击事件:
@click.stop=""设置当前选中行高亮颜色
在表格里添加以下代码:
:highlight-current-row="true"设置选中某一行
table表格的ref值.setCurrentRow(table关联的数据表[行数])获取选中的行信息
<el-table ref="singleTableRef"></el-table> const singleTableRef= ref(null); let row = singleTableRef.value.store.states.currentRow.value;设置高亮的颜色
//修改表格所选中的行的高亮颜色 :deep(.el-table__body tr.current-row > td) { background: var(--el-color-warning-light-9) !important; }格式化数字显示
const formatNumber = (row, column) => { return Math.floor(row[column.property]) .toString() .replace(/\B(?=(\d{3})+(?!\d))/g, ',') // 不保留小数且增加千分位格式 } <el-table-column label="员工目标" prop="target" :formatter="formatNumber" ></el-table-column>实现默认排序
以code列升序排列:
<el-table :default-sort="{ prop: 'code', order: 'ascending' }"> </el-table>ascending(升序)或descending(降序)
按钮
type控制颜色;plain控制镂空效果;round和circle控制形状
@keydown.enter.prevent//禁用按钮回车触发 @keydown.space.prevent//禁用按钮空格触发:loading="变量"//实现加载样式加载
v-loading="true"空状态
<el-empty description="没有数据"></el-empty>对话框
Link链接
<el-link>...</el-link>分页(页码组件)
v-model:current-page代表当前页码,v-model:page-size代表每页条数,:page-sizes可供用户选择的每页条数(注意要包含当前设置的每页条数),layout代表菜单栏(顺序和个数都是一一对应的),@size-change每页条数变化时触发的事件,@current-change当前页变化时触发的事件
更新:Element Plus 已废弃@size-change、@current-change,改为使用@change
total的值一定要为数字类型,不然控制台会报错
total.value = Number(变量) || 0抽屉
v-model控制显示与隐藏,:direction控制方向(默认从右往左),size控制大小
上传
action配置了后台接口地址,请求方式为post,请求参数name="file"
可以通过下面的API修改默认配置
:on-change控制上传事件,
const onSelectFile = (uploadFile) => { console.log('图片链接:',uploadFile.raw) }js控制显示上传
上传组件ref.$el.querySelector('input').click()单选框
v-model双向绑定数据
value单向获取选项数据(不能修改)
修改选项使用@input
弹窗
出现弹窗闪现一下,立刻消失的问题,解决方法:
增加一个setTimeout延时
setTimeout(() => { this.$confirm('此操作将会清空原有数据, 是否继续?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => { //确定后执行 }).catch(() => { //取消后执行 }); }, 200)文件上传
使用el-upload做了一个只允许上传一份excel文件的组件,并且上传新的文件会覆盖原文件
<script setup> import { UploadFilled } from '@element-plus/icons-vue' import { ref } from 'vue' const dialogVisible = ref(false) const title = ref() const isEdit = ref(false) const uploading = ref(true) const fileList = ref([]) const open = async (t, s) => { dialogVisible.value = true //显示抽屉 title.value = t isEdit.value = s } //上传文件组件发生变化时 const handleChange = (file) => { if (!isXLSXCSV(file.name)) { ElMessage({ message: '仅允许上传excel/csv文件', type: 'warning' }) fileList.value = [] return } uploading.value = false fileList.value = [file.raw] } //移除文件时 const handleRemove = () => { uploading.value = true fileList.value = [] } //超出最大文件数时 const handleExceed = (file) => { if (!isXLSXCSV(file[0].name)) { ElMessage({ message: '仅允许上传excel/csv文件', type: 'warning' }) return } ElMessage({ message: '仅允许上传一份文件,已覆盖原文件', type: 'warning' }) fileList.value = [file[0]] } const onSubmit = () => {} const isXLSXCSV = (link) => { return /.xlsx$/.test(link) || /.csv$/.test(link) } defineExpose({ open }) </script> <template> <el-dialog v-model="dialogVisible" :title="title" width="50%"> <el-upload ref="uploadrefss" :file-list="fileList" action="#" accept=".xlsx,.csv" class="upload-demo" drag :limit="1" :auto-upload="false" :on-change="handleChange" :on-remove="handleRemove" :on-exceed="handleExceed" > <el-icon class="el-icon--upload"><upload-filled /></el-icon> <div class="el-upload__text">拖拽文件至这里或 <em>点击上传</em></div> <template #tip> <div class="el-upload__tip"> 限制一份excel/csv文件,下一个文件会覆盖上一个文件 </div> </template> </el-upload> <template #footer> <span class="dialog-footer"> <el-button @click="dialogVisible = false" color="#A88D5B" plain >取消</el-button > <el-button type="primary" @click="onSubmit" color="#A88D5B" style="color: white" :disabled="uploading" > 确认导入 </el-button> </span> </template> </el-dialog> </template> <style> .el-dialog__headerbtn:focus .el-dialog__close, .el-dialog__headerbtn:hover .el-dialog__close { color: #7e6934 !important; } </style>统计组件
显示到小数点后两位
const formatter = (value) => { return value.toFixed(2) } <el-statistic title="超出预期(%)" :value="变量" :formatter="formatter" />