展示详情组件
用来展示详情信息
1
props介绍
info展示的内容对象
col全局在行中显示的列数 默认为3
labelWidth展示的title宽度
colon是否展示引号
infoConfig数组 内部是每个item的参数
infoConfig介绍
key当前读取的属性
label展示的title
type现在有两种类型 一种是 line 一种是 item
show控制展示 一种是 boolean 一种是函数
customRender自定义渲染函数 参数返回为 (当前值,传入的item,传入的info)
labelCustomRenderlabel自定义渲染函数 参数返回为 (当前值,传入的item,传入的info)
slotName插槽名字 可以通过slot渲染
wrap结果是否可以换行 默认不换行
ellipsis是否对value 进行title提示
positiontype为line的时候label的显示位置 默认为左边
col当前属性的在行中显示的列数 默认为 全局 col
调用代码展示
vue
<template>
<el-badge :value="+isShow">
<el-button type="default" @click="handleIsShow">{{
isShow ? "show is show" : "show is hide"
}}</el-button>
</el-badge>
<DetailInfo :info="info" labelWidth="180px" :col="col" :infoConfig="infoConfig">
<template #slotName="{ value, item, info }">
<span>{{ value }}</span>
</template>
</DetailInfo>
</template>
<script setup lang="ts">
import DetailInfo from "./index.vue";
import { ref, reactive } from "vue";
import type { infoConfigItem } from "docs/types";
const col = ref(2);
const isShow = ref(true);
const info = reactive({
colon: "是否展示引号",
labelWidth: "展示的title宽度",
col: "全局在行中显示的列数 默认为3",
infoConfig: "数组 内部是每个item的参数",
info: "展示的内容对象",
key: "当前读取的属性",
label: "展示的title",
type: "现在有两种类型 一种是 line 一种是 item",
show: "控制展示 一种是 boolean 一种是函数",
customRender: "自定义渲染函数 参数返回为 (当前值,传入的item,传入的info) ",
labelCustomRender:
"label自定义渲染函数 参数返回为 (当前值,传入的item,传入的info) ",
slotName: "插槽名字 可以通过slot渲染",
wrap: "结果是否可以换行 默认不换行",
ellipsis: "是否对value 进行title提示",
position: "type为line的时候label的显示位置 默认为左边",
itemCol: "当前属性的在行中显示的列数 默认为 全局 col",
});
const infoConfig: Array<infoConfigItem> = [
{
label: "props介绍",
key: "props",
type: "line",
position: "center",
},
{
label: "info",
key: "info",
},
{
label: "col",
key: "col",
col: 1,
},
{
label: "labelWidth",
key: "labelWidth",
},
{
label: "colon",
key: "colon",
},
{
label: "infoConfig",
key: "infoConfig",
col: 1,
},
{
label: "infoConfig介绍",
key: "infoConfig介绍",
type: "line",
position: "center",
},
{
label: "key",
key: "key",
},
{
label: "label",
key: "label",
},
{
label: "type",
key: "type",
col: 1,
},
{
label: "show",
key: "show",
show: (value: any, item: infoConfigItem, info: any) => {
return isShow.value;
},
col: 1,
},
{
label: "customRender",
key: "customRender",
customRender: (value: any, item: infoConfigItem, info: any) => {
return info[item[`key`]];
},
col: 1,
},
{
label: "labelCustomRender",
key: "labelCustomRender",
labelCustomRender: (
label: string,
value: any,
item: infoConfigItem,
info: any
) => {
return label;
},
ellipsis: true,
col: 1,
},
{
label: "slotName",
key: "slotName",
ellipsis: true,
slotName: "slotName",
col: 1,
},
{
label: "wrap",
key: "wrap",
wrap: true,
},
{
label: "ellipsis",
key: "ellipsis",
ellipsis: true,
},
{
label: "position",
key: "position",
ellipsis: true,
col: 1,
},
{
label: "col",
key: "itemCol",
col: 1,
},
];
const handleIsShow = () => {
isShow.value = !isShow.value;
};
</script>
组件源码
vue
<!--
/** author:YanJinke
time:2023-04-17 14:00:16
*/
-->
<template>
<div class="detailInfo">
<template v-for="item in infoConfig">
<template v-if="item.type === 'line'">
<Line v-if="show(info[item.key], item, info)" style="width: 100%; margin-bottom: 12px" :key="item.key"
:title="item.label" :position="item.position"></Line>
</template>
<div :key="item.key" class="detail-info-item" :style="{ width: `${100 / (item.col || col)}%` }"
v-else-if="show(info[item.key], item, info)">
<span :style="{ width: `${labelWidth}` }" :class="['label', { colon: colon }]">{{
item.labelCustomRender
? item.labelCustomRender(item.label, info[item.key], item, info)
: item.label
}}</span>
<span v-if="item.slotName" style="flex: 1">
<slot :name="item.slotName" :value="info[item.key]" :item="item" :info="info"></slot>
</span>
<span v-else :class="['value', 'nowrap', { wrap: item.wrap }]"
:title="item.ellipsis ? valueCustomRender(item) : ''" v-html="valueCustomRender(item)"></span>
</div>
</template>
</div>
</template>
<script setup lang="ts">
import Line from "../Line/Line.vue";
import type { infoConfigItem } from "docs/types/index.ts";
defineOptions({
name: "DetailInfo",
});
const props = withDefaults(
defineProps<{
infoConfig: Array<infoConfigItem>;
info: any;
col?: number;
labelWidth?: string;
colon?: boolean;
}>(),
{
infoConfig: () => [],
info: () => { },
col: 3,
labelWidth: "80px",
colon: true,
}
);
const show = (
text: string,
item: infoConfigItem,
info: { [key: string]: any }
): Boolean => {
if (typeof item.show === "function") {
return item.show(text, item, info);
} else {
return item.show === undefined ? true : item.show;
}
};
const valueCustomRender = (item: infoConfigItem): string => {
const { key, customRender } = item;
return customRender
? customRender(props.info[key], item, props.info)
: [null, undefined, ""].includes(props.info[key])
? "--"
: props.info[key];
};
</script>
<style lang="scss" scoped>
.detailInfo {
padding: 16px;
display: flex;
flex-wrap: wrap;
align-content: flex-start;
.detail-info-item {
display: flex;
margin: 6px 0;
.label {
position: relative;
text-align: right;
color: var(--vp-c-text-2);
padding-right: 16px;
}
.colon {
&::after {
content: ":";
position: absolute;
right: 10px;
top: 0;
}
}
.value {
flex: 1;
color: var(--vp-c-text-1);
padding-right: 24px;
&.nowrap {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
&.wrap {
white-space: pre-wrap;
}
}
}
}
</style>