03-elementPlus
主要记录一下elementPlus相关的问题
修改css样式
https://blog.csdn.net/wangyile4399/article/details/115402411
直接加::v-deep
text
<style scoped>
::v-deep(.el-input__inner){
background: aqua ;
font-size: 30px ;
}
</style>
表格合并
表格合并+自定义表头
vue
<template>
<div class="table-header-tool">
<el-select
v-model="chooseFiledList"
multiple
clearable
collapse-tags
placeholder="Select"
popper-class="custom-header"
:max-collapse-tags="1"
style="width: 200px"
>
<div style="margin: 10px">
<el-checkbox
v-model="checkAll"
:indeterminate="indeterminate"
@change="handleCheckAll"
>
全选
</el-checkbox>
</div>
<el-option
v-for="item in filedTitle"
:key="item"
:label="item"
:value="item"
/>
</el-select>
</div>
<el-table :data="tableData" border :span-method="objectSpanMethod">
<el-table-column v-if="chooseFiledList.indexOf('date')!=-1" prop="date" label="Date" />
<el-table-column v-if="chooseFiledList.indexOf('name')!=-1" prop="name" label="Name" />
<el-table-column v-if="chooseFiledList.indexOf('status')!=-1" prop="status" label="Status" />
</el-table>
</template>
<script setup>
import {ref, onMounted, nextTick, watch} from 'vue';
import axios from 'axios';
//是否全选
const checkAll = ref(true)
//是否半选
const indeterminate = ref(false)
//选中展示的字段
const chooseFiledList = ref(['date','name','status'])
//字段下拉列表
const filedTitle = ref(['date','name','status'])
//全选选中事件
const handleCheckAll = (val) => {
indeterminate.value = false
if (val) {
chooseFiledList.value = filedTitle.value.map(item => item)
} else {
chooseFiledList.value =[]
}
}
//监控字段
watch(chooseFiledList, (val) => {
if (val.length === 0) {
checkAll.value = false
indeterminate.value = false
} else if (val.length === filedTitle.value.length) {
checkAll.value = true
indeterminate.value = false
} else {
indeterminate.value = true
}
nextTick(()=>{
//这边使用这个是为了 el-table-column中使用了v-if来判断和显示
//如果不调用此方法的话,会出现样式错乱和滚动条无缘无故的出现等问题
app.proxy.$refs.tableRef.doLayout()
})
})
const tableData = ref([]);
let hbObj = ref({})
let propertyList = [
'date'
]
// 从后端获取数据
const fetchData = async () => {
// 示例:使用 axios 从后端获取数据
const response = await axios.get('/2.json');
tableData.value = response.data;
hbObj.value = computeCell(response.data,propertyList)
};
// 合并单元格的逻辑
const objectSpanMethod = ({
row,
column,
rowIndex,
columnIndex,
}) => {
// console.log(row,column,rowIndex,columnIndex)
let property = column.property
if (propertyList.indexOf(property) != -1){
let aList = hbObj.value[property]
const fRow = aList[rowIndex]
const fCol = fRow > 0 ? 1 : 0
return {
rowspan: fRow, // 合并的行数
colspan: fCol // 合并的列数,为0表示不显示
}
}else{
return [1,1]
}
}
const computeCell = (data,propertyList) => {
let result = {}
for (let j = 0; j < propertyList.length; j++) {
let property = propertyList[j]
let list = []
let curIndex = 0
for (let i = 0; i < data.length; i++) {
if (i == 0){
list.push(1)
curIndex = 0
}else{
if (data[i][property] == data[i - 1][property]){
list[curIndex] += 1;
list.push(0);
}else{
list.push(1);
curIndex = i;
}
}
}
result[property] = list
}
return result;
}
onMounted(() => {
fetchData();
});
</script>
<style scoped>
.table-header-tool{
display: flex;
justify-content: end;
}
</style>
表单校验
注意
需要 :rules="rules"
需要加上prop="account"
需要ref="registerFormRef"
vue
<template>
<el-button type="primary" @click="dialogRegisterVisible = true">注册</el-button>
<el-dialog v-model="dialogRegisterVisible" title="用户注册" width="500">
<el-form :model="registerForm" :rules="rules" ref="registerFormRef">
<el-form-item label="账号" label-width="60px" prop="account">
<el-input v-model="registerForm.account" autocomplete="off" clearable/>
</el-form-item>
<el-form-item label="密码" label-width="60px">
<el-input v-model="registerForm.password" type="password" clearable autocomplete="off"/>
</el-form-item>
<el-form-item label="邮箱" label-width="60px">
<el-input v-model="registerForm.email" clearable autocomplete="off"/>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button @click="dialogRegisterVisible = false">取消</el-button>
<el-button type="primary" @click="registerUser()">
注册
</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import {reactive, ref} from 'vue'
let dialogRegisterVisible = ref(false)
const registerFormRef= ref(null)
const registerForm = reactive({
account: '',
password: '',
email: '',
})
const rules = {
account: [
{required: true, message: '账号必填', trigger: 'blur'},
{ min: 5, max: 10, message: '账号必须是5-10位字符', trigger: 'blur' }
],
password: [
{
pattern: /^\S{6,15}$/,
message: '密码必须是6-15位非空字符',
trigger: 'blur'
}
]
}
function registerUser() {
registerFormRef.value.validate((valid) => {
if (valid) {
// 业务逻辑
}
});
}
</script>
上传图片
上传单个图片
在使用 Element Plus 的 <el-upload>
组件时,如果你设置了 :show-file-list="false"
, 默认情况下不会显示文件列表以及移除按钮。但是,你仍然可以通过自定义上传区域来实现移除图标的显示。
html
<template>
<el-upload
class="avatar-uploader"
list-type="picture-card"
:show-file-list="false"
:http-request="uploadFile"
>
<div v-if="imageUrl" class="preview-container">
<img :src="imageUrl" class="avatar" />
<el-icon @click.stop="handleRemove" class="remove-icon"><Close /></el-icon>
</div>
<el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
</el-upload>
</template>
<script setup>
import { ref } from 'vue'
import { Plus,Close } from '@element-plus/icons-vue'
const imageUrl = ref('')
//图片上传
let uploadFile = (params) => {
console.log(params)
console.log(URL.createObjectURL(params.file))
imageUrl.value = URL.createObjectURL(params.file)
}
//移除图片
const handleRemove = (uploadFile) => {
console.log(uploadFile)
imageUrl.value = '';
}
</script>
<style scoped>
.avatar-uploader .avatar {
width: 100%;
height: 100%;
display: block;
}
.preview-container {
position: relative;
width: 148px;
height: 148px;
}
.remove-icon {
position: absolute;
top: 0px;
right: 0px;
background-color: #fff;
border-radius: 50%;
padding: 4px;
cursor: pointer;
}
</style>
上传多个图片
vue
<template>
<el-upload
v-model:file-list="fileList"
list-type="picture-card"
:limit="5"
:on-preview="handlePictureCardPreview"
:http-request="uploadFile"
:on-remove="handleRemove"
>
<el-icon><Plus /></el-icon>
</el-upload>
<el-dialog v-model="dialogVisible">
<img w-full :src="dialogImageUrl" alt="Preview Image" />
</el-dialog>
</template>
<script setup>
import { ref } from 'vue'
import { Plus } from '@element-plus/icons-vue'
const fileList = ref([
{
url: 'https://dummyimage.com/200x100&text=PIC1',
},
{
url: 'https://dummyimage.com/200x100&text=PIC2',
},
{
url: 'https://dummyimage.com/200x100&text=PIC3',
},
])
const dialogImageUrl = ref('')
const dialogVisible = ref(false)
const handleRemove = (uploadFile, uploadFiles) => {
console.log(uploadFile, uploadFiles,fileList)
}
//图片上传 ,因为组件默认会增加本地图片,所以,需要先删除掉默认的图片,加入成功上传到服务器的图片
let uploadFile = (params) => {
fileList.value = fileList.value.filter(m => m.uid !== params.file.uid)
// 需要换成真实的上传接口,接口上传成功获取url
// uploadFileApi(params.file).then(res => {
// if (res.code === 200) {
// fileList.value.push({
// url: res.data
// })
// }
// })
console.log(params,fileList)
}
//预览图片
const handlePictureCardPreview = (uploadFile) => {
dialogImageUrl.value = uploadFile.url
dialogVisible.value = true
}
</script>
封装的上传组件
父组件
vue
<script>
import UploadImages from "@/components/UploadImages/index.vue";
//表单属性
let form = ref({
id: null,
name: '',
url: '',
img:'',
})
//编辑回显用的
const imgList = ref([])
//获取组件图片的url
const getImageList = (imgList) => {
form.value.img = imgList?.[0]?.url ?? ''
}
</script>
<template>
<UploadImages :imgList="imgList" :limit="5" @getImageList="getImageList"/>
</template>
UploadImages.vue
vue
<script setup>
import {defineProps, ref,defineEmits} from 'vue'
import { imageUpload } from '@/api/upload'
// 使用defineEmits来接收来自父组件的方法
const emit = defineEmits(['getImageList'])
// 声明props
const props = defineProps({
imgList: {
type: Array,
default: () => {
return []
}
},
limit:{
type: Number,
default: () => {
return 1
}
}
});
//图片列表
const fileList = ref(props.imgList ?? [])
const dialogImageUrl = ref('')
const dialogVisible = ref(false)
//图片上传
let uploadFile = (params) => {
fileList.value = fileList.value.filter(m => m.uid !== params.file.uid)
// 根据后台需求数据格式
const formImg = new FormData()
// 文件对象
formImg.append('file', params.file)
imageUpload(formImg).then(res => {
if (res.code === 200) {
fileList.value.push({
url: res.data.url,
name: res.data.filename
})
//调用父级的方法
emit('getImageList', fileList.value)
}
})
}
//预览图片
const handlePictureCardPreview = (uploadFile) => {
dialogImageUrl.value = uploadFile.url
dialogVisible.value = true
}
//移除图片
const handleRemove = (uploadFile, uploadFiles) => {
console.log(uploadFile, uploadFiles)
//调用父级的方法
emit('getImageList', fileList.value)
}
</script>
<template>
<el-upload
v-model:file-list="fileList"
list-type="picture-card"
:limit="limit"
:on-preview="handlePictureCardPreview"
:http-request="uploadFile"
:on-remove="handleRemove"
>
<el-icon><Plus /></el-icon>
</el-upload>
<el-dialog v-model="dialogVisible">
<img w-full :src="dialogImageUrl" alt="Preview Image" />
</el-dialog>
</template>
<style scoped lang="scss">
</style>
upload.js 上传接口
js
import request from '@/utils/system/request'
// 上传文件接口
export function imageUpload(data) {
return request({
url: '/upload/file',
method: 'post',
// baseURL: '/mock',
headers: {
'Content-Type': 'multipart/form-data'
},
data
})
}
自定义Icon图标
新建组件 CustomIcon.vue
vue
<template>
<div :style="iconStyle">
<img :src="iconSrc" alt="icon" class="custom-icon" />
</div>
</template>
<script>
export default {
name: 'CustomIcon',
props: {
iconSrc: {
type: String,
required: true,
},
size: {
type: Number,
default: 24,
},
},
computed: {
iconStyle() {
return {
width: `${this.size}px`,
height: `${this.size}px`,
display: 'inline-block',
};
},
},
};
</script>
<style scoped>
.custom-icon {
width: 100%;
height: 100%;
object-fit: contain;
}
</style>
使用
html
<CustomIcon iconSrc="/favicon.ico" :size="32" />
element-plus分页组件改中文
1、引入官方的语言包
2、在App.vue中进行设置
vue3
<el-config-provider :locale="zhCn">
<router-view></router-view>
</el-config-provider>
<script setup lang="ts">
import zhCn from "element-plus/lib/locale/lang/zh-cn";
//如果报错,可以试下下面的
//import zhCn from 'element-plus/es/locale/lang/zh-cn'
</script>
自定义语言包
cn.js
js
// src/locales/zh-cn.js
export default {
el: {
pagination: {
goto: '跳转到',
pageClassifier: '页',
total:'共 {total} 条记录'
},
},
};
在main.js中进行引入
js
import locale from "path/cn";
配置语言
js
app.use(ElementPlus, {
locale: locale // 一定要加上,不然无效
})
完整代码
js
import locale from "path/cn";
const app = createApp(App)
app.use(ElementPlus, {
locale: locale // 一定要加上,不然无效
})
app.mount('#app')