效果圖
?寫在前面
由于vue使用的版本太低,vue element UI 的描述列表不生效,但是有時(shí)候又不想換版本的可以自定義一個(gè)描述列表。
實(shí)現(xiàn)哪些功能
1、每行的高度根據(jù)改行中某一列的最大高度自動(dòng)撐開
2、列寬度自動(dòng)補(bǔ)全,避免最后一列出現(xiàn)殘缺的情況
3、支持純文本與HTML插槽
4、支持每行幾列的設(shè)置
5、支持每列寬度自定義
6、支持動(dòng)態(tài)數(shù)據(jù)重繪
組件設(shè)計(jì)
1、使用父子組件嵌套實(shí)現(xiàn),父組件為 el-descriptions, 子組件為 el-descriptions-item。
2、e-desc-item傳遞props的label 和 插槽的value
3、利用 el-row 和 el-col 來實(shí)現(xiàn)整體組件布局
封裝el-descriptions組件
<template>
<div class="desc" :style="{margin}">
<!-- 標(biāo)題 -->
<h1 v-if="title" class="desc-title" v-html="title"></h1>
<el-row class="desc-row" ref='elRow'>
<slot/>
</el-row>
</div>
</template>
<script>
export default {
name: 'ElDescriptions',
// 通過provide提供給子組件
provide () {
return {
labelWidth: this.labelWidth,
column: this.column,
size: this.size
}
},
props: {
// 標(biāo)題
title: {
type: String,
default: ''
},
// 邊距
margin: {
type: String,
default: '0'
},
// label寬度
labelWidth: {
type: String,
default: '120px',
},
column: {
// 每行顯示的項(xiàng)目個(gè)數(shù)
type: [Number, String],
default: 4
},
size: {
// 大小
type: String,
default: '0'
}
},
data () {
return {
// 監(jiān)聽插槽變化
observe: new MutationObserver(this.computedSpan)
}
},
mounted () {
this.$nextTick(() => {
this.computedSpan()
this.observe.observe(this.$refs.elRow.$el, { childList: true })
})
},
methods: {
computedSpan () {
// 篩選出子組件e-desc-item
const dataSource = this.$slots.default
const dataList = []
dataSource.forEach(item => {
if (item.componentOptions && item.componentOptions.tag === 'e-desc-item') {
dataList.push(item.componentInstance)
}
})
// 剩余span
let leftSpan = this.column
const len = dataList.length
dataList.forEach((item, index) => {
// 處理column與span之間的關(guān)系
// 剩余的列數(shù)小于設(shè)置的span數(shù)
const hasLeft = leftSpan <= (item.span || 1)
// 當(dāng)前列的下一列大于了剩余span
const nextColumnSpan = (index < (len - 1)) && (dataList[index + 1].span >= leftSpan)
// 是最后一行的最后一列
const isLast = index === (len - 1)
if (hasLeft || nextColumnSpan || isLast) {
// 滿足以上條件,需要自動(dòng)補(bǔ)全span,避免最后一列出現(xiàn)殘缺的情況
item.selfSpan = leftSpan
leftSpan = this.column
} else {
leftSpan -= item.span || 1
}
})
}
},
beforeDestroy () {
this.observer.disconnect()
}
}
</script>
<style scoped lang="scss">
.desc{
.desc-title {
margin-bottom: 10px;
color: #333;
font-weight: 700;
font-size: 16px;
line-height: 1.5715;
}
.desc-row{
display: flex;
flex-wrap: wrap;
border-radius: 2px;
border: 1px solid #EBEEF5;
border-bottom: 0;
border-right: 0;
width: 100%;
}
}
</style>
封裝e-desc-item組件
<template>
<el-col :span="computedSpan" class="desc-item">
<div class="desc-item-content" :class="size">
<label class="desc-item-label" :style="{width: labelWidth}" v-html="label"></label>
<div class="desc-item-value" v-if="$slots">
<slot/>
</div>
</div>
</el-col>
</template>
<script>
export default {
name: 'ElDescriptionsItem',
inject: ['labelWidth', 'column', 'size'],
props: {
span: {
type: [Number, String],
required: false,
default: 0
},
label: {
type: String,
required: false,
default: ''
}
},
data () {
return {
// 子組件自己的span
selfSpan: 0
}
},
computed: {
computedSpan () {
// 子組件自己的span,用于父組件計(jì)算修改span
if (this.selfSpan) {
return 24 / this.column * this.selfSpan
} else if (this.span) {
// props傳遞的span
return 24 / this.column * this.span
} else {
// 未傳遞span時(shí),取column
return 24 / this.column
}
}
}
}
</script>
<style scoped lang="scss">
.desc-item {
border-right: 1px solid #EBEEF5;
border-bottom: 1px solid #EBEEF5;
.desc-item-content {
display: flex;
justify-content: flex-start;
align-items: center;
color: rgba(0,0,0,.65);
font-size: 14px;
line-height: 1.5;
width: 100%;
background-color: #fafafa;
height: 100%;
.desc-item-label{
border-right: 1px solid #EBEEF5;
display: inline-block;
padding: 12px 16px;
flex-grow: 0;
flex-shrink: 0;
color: rgba(0, 0, 0, 0.6);
font-weight: 400;
font-size: 14px;
line-height: 1.5;
height: 100%;
display: flex;
align-items: center;
}
.desc-item-value{
background: #fff;
padding: 12px 16px;
flex-grow: 1;
overflow: hidden;
word-break: break-all;
height: 100%;
display: flex;
align-items: center;
color: #444;
span{
color: #aaa;
}
// 空數(shù)據(jù)時(shí)展示的內(nèi)容
&:empty::after {
content: '--';
}
}
&.small {
.desc-item-label,
.desc-item-value {
padding: 10px 14px;
}
}
}
}
</style>
使用方式
<template>
<div class="mod-contracts">
<el-descriptions
margin="0 12px"
label-width="100px"
v-loading="dataListLoading"
v-model="userInfo"
v-if="userInfo"
>
<el-descriptions-item label="合同編號(hào)" :span="2">{{
userInfo.num
}}</el-descriptions-item>
<el-descriptions-item label="合同名稱" :span="2">
{{ userInfo.title }}</el-descriptions-item
>
<el-descriptions-item label="姓名" :span="2">
{{ userInfo.userName }}</el-descriptions-item
>
<el-descriptions-item label="公司名稱" :span="2">
{{ userInfo.companyName }}</el-descriptions-item
>
<el-descriptions-item label="合同類型" :span="2">
<span v-if="userInfo.type == 0">試用期合同</span>
<span v-if="userInfo.type == 1">正式員工合同</span>
<span v-if="userInfo.type == 2">外包合同</span>
</el-descriptions-item>
<el-descriptions-item label="薪資" :span="2">{{
userInfo.salary
}}</el-descriptions-item>
<el-descriptions-item label="崗位" :span="2">{{
userInfo.post
}}</el-descriptions-item>
<el-descriptions-item label="合同狀態(tài)" :span="2">
<template>
<el-tag
v-if="userInfo.state === 0 && !isCurrentTimeLater"
size="small"
type="info"
>未確認(rèn)</el-tag
>
<el-tag v-if="userInfo.state === 1" size="small">生效</el-tag>
<el-tag
v-if="userInfo.state === 2 || isCurrentTimeLater"
size="small"
type="danger"
>作廢</el-tag
>
</template>
</el-descriptions-item>
<el-descriptions-item label="身份證號(hào)碼" :span="2">{{
userInfo.idNum
}}</el-descriptions-item>
<el-descriptions-item label="家庭住址" :span="2">{{
userInfo.address
}}</el-descriptions-item>
<el-descriptions-item label="聯(lián)系電話" :span="2">{{
userInfo.mobile
}}</el-descriptions-item>
<el-descriptions-item label="合同生效時(shí)間" :span="2">{{
userInfo.effectTime
}}</el-descriptions-item>
<el-descriptions-item label="合同失效時(shí)間" :span="2">{{
userInfo.lostEffectTime
}}</el-descriptions-item>
<el-descriptions-item label="合同人所屬部門" :span="2">
<el-row v-for="item in deptList" :key="item.id">
<span v-if="item.id == userInfo.deptId">{{ item.label }}</span>
</el-row>
</el-descriptions-item>
<el-descriptions-item label="合同結(jié)束時(shí)間" :span="4">{{
userInfo.endTime
}}</el-descriptions-item>
<el-descriptions-item label="詳情" :span="4" style="height: auto">
甲乙雙方經(jīng)平等協(xié)商。共同決定建立勞務(wù)關(guān)系。本服務(wù)協(xié)議屬于勞務(wù)協(xié)議,不在《中華人民共和國芳動(dòng)法》調(diào)整范圍內(nèi),而在《中華人民共和國民法通則》、
《中華人民共和國合同法》的調(diào)整之中。甲乙雙方在充分明確這一法律關(guān)系的基礎(chǔ)上,根據(jù)《民法通則》、《合同法》和其他相關(guān)法律、法規(guī),自愿簽訂本協(xié)議,共同道守協(xié)議所列條款。
</el-descriptions-item>
<el-descriptions-item
label="操作"
:span="4"
v-if="userInfo.state == 0 && !isCurrentTimeLater"
>
<template>
<el-button size="small" type="primary" @click="update(userInfo.id)"
>確認(rèn)合同</el-button
>
</template>
</el-descriptions-item>
</el-descriptions>
<el-descriptions v-else>
<template>暫無合同,請(qǐng)聯(lián)系管理員</template>
</el-descriptions>
<el-button v-if="userInfo" style="margin-top: 10px;margin-left: 10px;" type="danger" @click="downloadExcel(userInfo.id)">導(dǎo)出合同</el-button>
<update
v-if="UpdateVisible"
ref="updateView"
@refreshData="getContractsInfo"
></update>
</div>
</template>
<script>
import ElDescriptions from "../../common/e-desc.vue";
import ElDescriptionsItem from "../../common/e-desc-item.vue";
import Update from "./contracts-update.vue";
export default {
components: {
ElDescriptions,
ElDescriptionsItem,
Update,
},
data() {
return {
userInfo: {
id: 0,
userId: 0,
roleName: "",
username: "",
deptId: "",
lostEffectTime: "",
},
currentTime: new Date(),
deptList: [],
dataList:[],
dataListLoading: false,
UpdateVisible: false,
};
},
mounted() {
this.getDeptDataList();
this.getContractsInfo();
setInterval(() => {
this.currentTime = new Date();
}, 1000);
},
computed: {
isCurrentTimeLater() {
this.currentTime.setHours(0, 0, 0, 0);
this.lostEffectTime = new Date(this.userInfo.lostEffectTime);
return this.currentTime > this.lostEffectTime;
},
},
methods: {
getContractsInfo() {
this.dataListLoading = true;
this.$http({
url: this.$http.adornUrl(`/contracts/info`),
method: "get",
params: this.$http.adornParams(),
}).then(({ data }) => {
if (data && data.code === 0) {
this.userInfo = data.contracts;
this.dataList.push(data.contracts);
} else {
this.userInfo = [];
this.totalPage = 0;
}
this.dataListLoading = false;
});
},
// 獲取部門數(shù)據(jù)列表
getDeptDataList() {
this.dataListLoading = true;
this.$http({
url: this.$http.adornUrl("/sys/dept/tree"),
method: "get",
params: this.$http.adornParams(),
}).then(({ data }) => {
this.deptList = data;
});
},
//完善合同
update(id) {
this.UpdateVisible = true;
this.$nextTick(() => {
this.$refs.updateView.init(id);
});
},
//導(dǎo)出全部
downloadExcel(id) {
var ids=this.dataList.map(item => item.id);
this.$confirm(`確定對(duì)[id=${ids.join(",")}]進(jìn)行導(dǎo)出操作?`, "提示", {
confirmButtonText: "確定",
cancelButtonText: "取消",
type: "warning",
}).then(() => {
// 發(fā)送 HTTP 請(qǐng)求以下載 Excel 文件
this.$http({
url: this.$http.adornUrl("/contracts/download"),
method: "post",
data: this.$http.adornData(ids, false),
responseType: "blob", // 設(shè)置響應(yīng)類型為二進(jìn)制流
})
.then((response) => {
// 創(chuàng)建一個(gè) URL 對(duì)象,指向返回的二進(jìn)制數(shù)據(jù)
const url = window.URL.createObjectURL(new Blob([response.data])); // 創(chuàng)建一個(gè) <a> 元素,設(shè)置其屬性,模擬點(diǎn)擊下載
const link = document.createElement("a");
link.href = url;
link.setAttribute("download", "data.xlsx"); // 設(shè)置下載文件的默認(rèn)名稱
document.body.appendChild(link);
link.click(); // 清理創(chuàng)建的 URL 對(duì)象
window.URL.revokeObjectURL(url);
})
.catch((error) => {
console.error("下載失敗", error);
});
});
},
},
};
</script>
參數(shù)說明
?文章來源:http://www.zghlxwxcb.cn/news/detail-777728.html
?至此,代碼就寫完啦,描述列表不生效的問題應(yīng)該就解決了文章來源地址http://www.zghlxwxcb.cn/news/detail-777728.html
到了這里,關(guān)于Vue Element UI 自定義描述列表組件的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!