vue动态表格以及搜索内容高亮显示
展示效果
需求
表格根据后端返回的数据,动态展示行和列
输入搜索内容后,对对应的文本进行高亮显示
左侧可以筛选要展示的列
实现
表格样式
<!-- 头部-->
<div style="background: #f3f6fb">
<template v-for="(item, index) in listHeader.list">
<div
:key="index"
class="table-content table-title-container"
:title="listHeader.title[index]"
:style="{ width: `${changeWidth(item) ? changeWidth(item) : headerWidth}` }"
>
<div style="display: inline-block">{ { item }}</div>
<div
@click="sortList(item)"
style="
display: inline-block;
position: relative;
width: 10px;
height: 10px;
cursor: pointer;
"
v-if="item.indexOf('timestamp') !== -1 || item.indexOf('timeStamp') !== -1"
>
<svg-icon class="table-title-svg" icon-class="topic-sort"></svg-icon>
</div>
</div>
</template>
</div>
<!-- 表格内容-->
<template v-for="(item, index) in searchList.list">
<div class="line-content" :key="index + '-'" v-if="Object.entries(item).length > 0">
<div class="line-height" :style="{ width: `${listWidth + 'px'}` }">
<template v-for="(item1, index1) in listHeader.list">
<div
:key="index1"
class="table-content"
:style="{ width: `${changeWidth(item1) ? changeWidth(item1) : headerWidth}` }"
>
<div
class="table-newline"
v-if="item1.indexOf('timestamp') !== -1 || item1.indexOf('timeStamp') !== -1"
style="color: #3096ff"
v-html="switchPosition(item, item1)"
/>
<div class="table-newline" v-else v-html="switchPosition(item, item1)"></div>
</div>
</template>
</div>
<a-divider class="table-divider" :style="{ width: `${listWidth + 'px'}` }"></a-divider>
</div>
</template>
css样式
.table-content {
text-align: center;
position: relative;
display: inline-block;
}
.table-title-container {
background: #f3f6fb;
padding: 10px 0;
}
.table-title-svg {
width: 16px;
height: 16px;
position: absolute;
left: 0;
}
.line-content {
max-height: 401px;
margin: 5px 0;
}
.line-height {
max-height: 400px;
overflow-y: auto;
overflow-x: hidden;
}
.table-newline {
padding: 8px 8px;
height: 95%;
display: flex;
flex-direction: column;
word-break: break-word;
white-space: normal;
}
.table-divider {
margin: 5px 0;
}
表格内容排列
switchPosition(value, header) {
let res = '--';
Object.entries(value).forEach((item) => {
if (item[0] === header) {
res = item[1];
} else if (item[1] && typeof item[1] === 'object') {
Object.entries(item[1]).forEach((items) => {
if (items[0] === header) {
res = items[1];
}
});
}
});
if (res != null) {
return this.brightenKeyword(res, this.content);
} else return '--';
},
changeWidth(value) {
if (this.listWidth === this.screenWidth) {
this.headerWidth = (this.screenWidth - this.width) / this.length + 'px';
} else {
return value.length * 10 + 'px';
}
},
表格搜索高亮
//搜索高亮
brightenKeyword(val, keyword) {
if (
Object.prototype.toString.call(val) !== '[object Array]' &&
Object.prototype.toString.call(val) !== '[object Object]'
) {
return this.replaceWord(val, keyword);
} else if (
Object.prototype.toString.call(val) === '[object Array]' ||
Object.prototype.toString.call(val) === '[object Object]'
) {
return this.replaceWord(JSON.stringify(val), keyword);
} else return val;
},
replaceWord(val, keyword) {
val = val + '';
if (val.indexOf(keyword) !== -1 && keyword !== '') {
//关键词替换
val = val.replace(
new RegExp(keyword, 'g'),
'<span style="background-color: #FFAD0F">' + keyword + '</span>'
);
//解决文字换行问题
val = '<span>' + val.replace(/\n/g, '</span> <span>') + '</span>';
return val;
} else return val;
},
数据格式处理
后端返回的数据格式
this.searchList = {
"_hik_ingest_timestamp":"2021-08-13T07:25:31.545045Z",
"brake_system_status":{
"brake_padel":1
}
"exterior_lights":{
"all_lights_off":0,
"automatic_light_control":0,
"daytime_running_lights":0,
"fog_lights":0,
"high_beam_head_lights":0
}
"motion":{
"speed":22.222222
}
"obuEsn":"27567864",
"obuId":"obu_123"
}
解析json格式
生成表头和对应内容
this.searchList.forEach((item) => {
Object.entries(item).forEach((items) => {
if (items[1] && Object.prototype.toString.call(items[1]) === '[object Object]') {
Object.entries(items[1]).forEach((item1) => {
if (this.listHeader.list.indexOf(item1[0]) === -1) {
this.listHeader.list.push(item1[0]);
this.listHeader.title.push(items[0] + '.' + item1[0]);
}
});
} else if (this.listHeader.list.indexOf(items[0]) === -1) {
this.listHeader.list.push(items[0]);
this.listHeader.title.push(items[0]);
}
});
});
表头字段筛选功能
//增加选定字段
pushField(item) {
this.chooseField.push(item);
this.fieldList.splice(this.fieldList.indexOf(item), 1);
this.queryParams.fields.push(item.fieldName);
this.getSearchList();
this.onSearch();
},
//删除选定字段
popField(item) {
this.fieldList.push(item);
this.chooseField.splice(this.chooseField.indexOf(item), 1);
this.queryParams.fields.splice(this.queryParams.fields.indexOf(item.fieldName), 1);
this.getSearchList();
this.onSearch();
},
//字段搜索
onSearch() {
if (this.field) {
let newArr = [],
chooseArr = [];
this.fieldList.forEach((item) => {
if (item.fieldName.indexOf(this.field) !== -1) {
newArr.push(item);
}
});
this.searchFieldList = newArr;
this.chooseField.forEach((item) => {
if (item.fieldName.indexOf(this.field) !== -1) {
chooseArr.push(item);
}
});
this.searchChooseField = chooseArr;
} else {
this.searchFieldList = this.fieldList;
this.searchChooseField = this.chooseField;
}
},