存在el-form的页面切换之后内存还在被占用,操作久了之后内存占用越来越大
一个vue3的两个页面都只含有el-form和el-table,无定时器和监听器,当操作久了之后发现内存一直在增长,然后去除掉table,发现只要含有el-form,页面频繁切换内存会增长且不会释放,不知道如何去释放这个被占用的内存,像echarts有dispose方法,但form没听说过,而且没有明白为什么form会造成内存一直占用。
补充问题,代码如下:
切换的页面就是InspectionReportVue、StatisticalReportVue、DefectReportVue这几个组件,这几个组件里只有form和table。另外index.vue也不是一个路由页面,它是嵌套在路由页面A里面的一个组件,同样也是被v-if来控制显示与否的。我不知道是不是我写的这个插槽有问题导致内存泄漏的
//index.vue
<template>
<TableLayoutSelf title="XXX" :menuList="menuList">
<template v-slot="data">
<InspectionReportVue key="666" v-if="data.active === '1'" />
<StatisticalReportVue key="777" v-if="data.active === '2'" />
<DefectReportVue key="888" v-if="data.active === '3'" />
</template>
</TableLayoutSelf>
</template>
<script setup name="ReportForm">
import TableLayoutSelf from '../components/TableLayoutSelf/index.vue'
import InspectionReportVue from './inspectionReport.vue'
import StatisticalReportVue from './statisticalReport.vue'
import DefectReportVue from './defectReport.vue'
import nav1 from './images/nav1.png'
import nav2 from './images/nav2.png'
import nav3 from './images/nav3.png'
const menuList = ref([
{
id: '1',
img: nav1,
text: 'XXX',
},
{
id: '2',
img: nav2,
text: 'XXX',
},
{
id: '3',
img: nav3,
text: 'XXX',
},
])
</script>
<style scoped lang="scss">
</style>
//TableLayoutSelf.vue
<template>
<div class="layout">
<div class="aside">
<div class="title">{{ title }}</div>
<div class="menu">
<div class="item" v-for="item in menuList" :key="item.id" :id="item.id" @click="handleClick" :class="{'active': item.id === activeId}">
<img :src="item.img" :id="item.id" />
<span :id="item.id">{{ item.text }}</span>
</div>
</div>
</div>
<div class="content">
<slot :active="activeId"></slot>
</div>
</div>
</template>
<script setup name="TableLayoutSelfSelf">
const props = defineProps({
title: String,
menuList: Array,
})
const { menuList } = toRefs(props)
const activeId = ref('1')
const handleClick = (e) => {
activeId.value = e.target.id
}
</script>
<style scoped lang="scss">
.layout {
display: flex;
height: calc(100vh - vh(150));
.aside {
width: vw(240);
flex-shrink: 0;
.title {
line-height: vh(55);
text-align: center;
background: #2d3e5b;
color: #fff;
font-size: vw(17);
}
.menu {
.item {
line-height: vh(76);
border: 1px solid #22467e;
display: flex;
align-items: center;
padding-left: vw(25);
> img {
width: vw(36);
height: vh(38);
}
> span {
margin-left: vw(25);
font-size: vw(18);
color: #fff;
}
}
.item:hover,
.active {
background: linear-gradient(to right, #174a93, rgba(0, 0, 0, 0));
}
.item:not(:last-child) {
border-bottom: 0;
}
}
}
.content {
width: calc(100% - vw(240));
}
}
</style>
//InspectionReport.vue
<template>
<div class="table">
<el-form class="search" :model="queryParams" ref="queryRef" v-show="showSearch" :inline="true" label-width="68px">
<el-form-item label="设备类型" prop="deviceType">
<el-select v-model="queryParams.deviceType" placeholder="设备类型" style="width: 200px" @change="getDeviceName">
<el-option v-for="item in typeOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item label="告警设备" prop="deviceName">
<el-select v-model="queryParams.deviceName" placeholder="告警设备" style="width: 200px">
<el-option v-for="item in deviceMap" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="任务状态" prop="status">
<el-select v-model="queryParams.status" placeholder="任务状态" style="width: 200px">
<el-option v-for="item in statusOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item label="任务开始时间" style="width: 458px" label-width="98px">
<el-date-picker v-model="dateRange" type="datetimerange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" value-format="YYYY-MM-DD HH:mm:ss" :clearable="false"></el-date-picker>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<div class="content">
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" icon="Download" @click="handleExport" :loading="btnload">导出</el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="list">
<el-table-column label="设备" align="center" prop="deviceName" />
<el-table-column label="巡检任务" align="center" prop="task_name" :show-overflow-tooltip="true" />
<el-table-column label="巡检状态" align="center" prop="status">
<template #default="scope">
<dict-tag :options="taskStatus" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="开始时间" align="center" prop="task_begin_time" width="180" />
<el-table-column label="结束时间" align="center" prop="task_end_time" width="180" />
<el-table-column label="持续时长" align="center" prop="timeCount" :show-overflow-tooltip="true" />
<el-table-column label="报告生成时间" align="center" prop="roportCreateTime" :show-overflow-tooltip="true" />
<el-table-column label="巡检点个数" align="center" prop="pointSum" />
<el-table-column label="缺陷个数" align="center" prop="quxianSum" />
<el-table-column label="操作" align="center" width="160" class-name="small-padding fixed-width">
<template #default="scope">
<el-button link type="primary" @click="handleDownload(scope.row)">下载</el-button>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
</div>
</div>
</template>
<script setup name="InspectionReport">
import dayjs from 'dayjs'
import { saveAs } from 'file-saver'
import { ElMessageBox } from 'element-plus'
import { queryDeviceName, inspectList, exportInspect, downloadExcel, getHttpServerRoportAddr } from '@/api/control/monitor/reportForm'
const { proxy } = getCurrentInstance()
const { taskStatus } = proxy.useDict('taskStatus')
const showSearch = ref(true)
const list = ref([])
const loading = ref(false)
const total = ref(0)
const dateRange = ref([dayjs().subtract(1, 'day').format('YYYY-MM-DD 00:00:00'), dayjs().format('YYYY-MM-DD 23:59:59')])
const deviceMap = ref([]) //告警设备列表
const btnload = ref(false) //导出按钮加载中
const data = reactive({
form: {},
queryParams: {
pageNum: 1,
pageSize: 10,
deviceType: '0',
deviceName: undefined,
status: '',
},
})
const { queryParams, form } = toRefs(data)
const typeOptions = [
{
value: '0',
label: '机器人',
},
{
value: '6',
label: '定点摄像头',
},
]
const statusOptions = [
{
value: '',
label: '所有',
},
{
value: '2',
label: '已执行',
},
{
value: '3',
label: '取消',
},
]
onMounted(() => {
getDeviceName('init')
})
const getDeviceName = (flag) => {
queryDeviceName({ deviceType: queryParams.value.deviceType }).then((res) => {
if (res.code === 200) {
deviceMap.value = res.deviceNameMapList
queryParams.value.deviceName = deviceMap.value[0]?.id
if (flag === 'init') {
getList()
}
}
})
}
const getList = () => {
loading.value = true
inspectList(proxy.addDateRange(queryParams.value, dateRange.value))
.then((res) => {
if (res.code === 200) {
list.value = res.rows
total.value = res.total
}
})
.finally(() => {
loading.value = false
})
}
const handleExport = () => {
ElMessageBox.confirm('确定导出所有巡检报告吗?', '系统提示', {
confirmButtonText: '确认',
cancelButtonText: '取消',
}).then(() => {
btnload.value = true
exportInspect(proxy.addDateRange(queryParams.value, dateRange.value)).then((res) => {
if (res.code === 200) {
downloadExcel({ fileName: res.msg }).then((data) => {
btnload.value = false
const blob = new Blob([data])
saveAs(blob, res.msg)
})
}
})
})
}
const handleDownload = (row) => {
const { device_id, report_url } = row
if (report_url.indexOf('http:') == -1) {
getHttpServerRoportAddr({ robotId: device_id }).then((res) => {
if (res.code === 200) {
const url = `http://${res.http_server_addr}/${report_url}`
window.open(url)
}
})
} else {
window.open(report_url)
}
}
const handleQuery = () => {
queryParams.value.pageNum = 1
getList()
}
const resetQuery = () => {
proxy.resetForm('queryRef')
dateRange.value = [dayjs().subtract(1, 'day').format('YYYY-MM-DD 00:00:00'), dayjs().format('YYYY-MM-DD 23:59:59')]
getDeviceName('init')
}
</script>
<style scoped lang="scss">
.table {
background: #f3f3f4;
width: 100%;
height: 100%;
padding: vh(10) vw(20);
overflow: auto;
.search,
.content {
background: #fff;
border-radius: 6px;
box-shadow: 1px 1px 3px rgba(0, 0, 0, 0.2);
}
.search {
padding: vh(20) vw(20) 0;
margin-bottom: vh(15);
}
.content {
padding: vh(20) vw(20);
}
}
</style>
快照图片如下:存在增量,但是不知道如何通过这个去分析定位具体代码
先看看切换页面有没有使用<keep-alive>
如果无从入手,可以直接用开发者工具拍几个内存快照对比一下切换页面前后的内存变化,直接追踪堆中的对象引用