Keepalive en vue2 limpia manualmente la memoria y hay un problema de que la memoria de subenrutamiento no se puede recuperar

causa

Recientemente, los clientes a menudo informan el problema de los bloqueos del sistema, especialmente por la tarde. Después de la autocomprobación, descubrí que la memoria del sistema no se recupera después de cerrar la pestaña. Ya lo he solucionado. Después de cerrar la pestaña, manualmente clear the keep-alive No debería haber fugas de memoria en el caché interno Parece que hay otros cachés que no se han limpiado.

problema de posicionamiento

1. Restaurando la escena

El proyecto de la empresa es una aplicación de una sola página, y todas las operaciones se realizan en una pestaña del navegador. Toda la página se presenta a través de Layou + sub-enrutamiento. El nivel de enrutamiento alcanza el nivel 4, y el negocio es complejo y engorroso. Necesidad de reconstruir una escena de restauración de proyecto puro

2. Escribe una demostración

Cree un proyecto usando vue-cli, [email protected],[email protected]

principal.js

import Vue from 'vue'
import App from './App.vue'
import router from './router'
Vue.config.productionTip = false

new Vue({render: h => h(App),router
}).$mount('#app') 

aplicación.vue

<template><router-view></router-view>
</template>

<script> export default {name: "App",
}; </script> 

ver/Página1, ver/Página2, ver/A1, ver/A2

<template><div>Page1<router-view></router-view></div>
</template>

<script> export default {name: "Page1",
}; </script>

<template><div>Page2<router-view></router-view></div>
</template>

<script> export default {name: "Page2",
}; </script>

<template><div>组件view A1</div>
</template>
<script> export default {name: "A1",data() {return {a: new Array(20000000).fill(1), //大概80mb};},
}; </script>

<template><div>组件view A2</div>
</template>
<script> export default {name: "A2",data() {return {a: new Array(20000000).fill(1), //大概80mb};},
}; </script> 

vista/Layout.vue

<template><div><h1>Layout</h1><div class="box"><p>二级路由</p><router-link :to="{ name: 'A' }">A</router-link><br /><router-link :to="{ name: 'B' }">B</router-link></div><div class="box"><p>三级路由</p><router-link :to="{ name: 'AA' }">Page1</router-link><br /><router-link :to="{ name: 'BB' }">Page2</router-link></div><div class="box"><button @click="includeRemove()">清理keepalive缓存</button><br /><router-link to="/home">Home</router-link><br /></div><h1>keep-alive</h1>缓存页面:{
   
   { include }}<keep-alive :include="include"><router-view ref="alive"></router-view></keep-alive></div>
</template>

<script> export default {name: "Layout",data() {return {include: [],};},watch: {'$route'(val) {const name = val.meta.nameif (name && !this.include.includes(name)) {this.include.push(name);}}},methods: {includeRemove() {this.include = [];},},mounted() {},
}; </script>
<style> .box {margin-bottom: 20px;
} </style> 

enrutador/index.js

import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)

const router = new Router({mode: "hash",routes: [{path: "/",redirect: "/home",component: () => import("../view/Layout.vue"),children: [{path: "home",component: () => import("../view/Home.vue"),},],},{path: "/a",component: () => import("../view/Layout.vue"),children: [{path: "a",name: "A",meta: {name: 'A1'},component: () => import("../view/A1.vue"),},],},{path: "/b",component: () => import("../view/Layout.vue"),children: [{path: "b",name: "B",meta: {name: 'A2'},component: () => import("../view/A2.vue"),},],},{path: "/a",component: () => import("../view/Layout.vue"),children: [{path: "page1",name: "Page1",component: () => import("../view/Page1.vue"),children: [{path: "a",name: "AA",meta: {name: 'Page1'},component: () => import("../view/A1.vue"),},],},],},{path: "/b",component: () => import("../view/Layout.vue"),children: [{path: "page2",name: "Page2",component: () => import("../view/Page2.vue"),children: [{path: "b",name: "BB",meta: {name: 'Page2'},component: () => import("../view/A2.vue"),},],},],},],
});

export defaultrouter 

resultado de ejecución

3. Reproducir el problema

Se puede ver que en el caso inicial, el uso de memoria es de aproximadamente 7,7 MB

1. Después de hacer clic en A y B, la memoria ocupa 168 MB

2. Haga clic en Inicio para asegurarse de que el enrutamiento no ocupe los componentes A y B al borrar el caché, y haga clic nuevamente para borrar el caché de actividad.

Después de la GC manual, se descubrió que el uso de la memoria había cambiado a 7,9 MB, lo que indica que los componentes A y B se lanzaron con éxito. Esto simuló la situación en la que la empresa solo tenía un enrutamiento secundario en la etapa inicial del proyecto. el problema del bloqueo del sistema no existía, lo cual se acaba de confirmar aquí.

3. Haga clic en Página 1, Página 2, el uso de memoria es de 168 MB

4. Haga clic en Inicio, haga clic nuevamente para borrar el caché de mantenimiento

Se produjo un problema en este momento, la memoria no se liberó correctamente, se encontró el problema

4. Análisis

Primero registre el uso de memoria en el caso inicial

Abra la página 1 y la página 2, cambie a la página de inicio, borre la memoria caché de mantenimiento y grabe la instantánea de la memoria actual

Se puede ver en la figura que el componente A1 todavía existe, y vue-router hace referencia a él, y nameMap guarda toda la información de enrutamiento, por lo que se encuentra el problema

Información de enrutamiento en el estado inicial

Abra la página 1 y la página 2, cambie a la página de inicio y borre la información de enrutamiento después de la caché de mantenimiento.

Pruebe otra situación, no cambie a Inicio antes de limpiar el caché keepalive, en este caso, la memoria se puede liberar con éxito.

5. Conclusión

1. Si la pestaña está cerrada en la ruta actual, y luego se borra el caché de actividad, la memoria se puede reciclar normalmente.
2. Si la ruta inactiva se cierra en otras rutas, los componentes de enrutamiento de segundo nivel se pueden reciclar normalmente. y la recuperación de la memoria de las rutas de nivel inferior es anormal, suponiendo que la información en la ruta inactiva emparejada ha cambiado. Después de todo, es un modo singleton, lo cual tiene sentido. ¿Por qué es normal que la ruta activa elimine el ¿cache?

3. Solucione el problema

1. Idea

1. Obtener y cerrar la pestaña actual enrutamiento relación padre-hijo
2. A través de toda la información de enrutamiento, atravesar y eliminar el instances.defaultvalor del enrutamiento relacionado

2. Implementación de código específico

includeRemove() {this.include = [];// 为啥vue-router不开放直接获取nameMap的接口 淦const routes = this.$router.getRoutes()const nameMap = new Map()for (let index = 0; index < routes.length; index++) {const r = routes[index];nameMap.set(r.name, r)}// 假设我这边获取到了当前移除的tab页签,具体代码根据具体项目实现const rList = ['AA', 'BB']for (let index = 0; index < rList.length; index++) {const name = rList[index];const r = nameMap.get(name)if (r) r.instances.default = undefined}
} 

Después de la modificación del código, vuelva a realizar el proceso, el uso de la memoria es el siguiente y el problema se resuelve con éxito

Por fin

Recientemente, también clasifiqué una nota de JavaScript y ES, un total de 25 puntos de conocimiento importantes, y expliqué y analicé cada punto de conocimiento. Puede ayudarlo a dominar rápidamente el conocimiento relevante de JavaScript y ES, y mejorar la eficiencia del trabajo.



Amigos necesitados, puede hacer clic en la tarjeta a continuación para recibir y compartir gratis

Supongo que te gusta

Origin blog.csdn.net/web22050702/article/details/128713589
Recomendado
Clasificación