keep-alive是Vue的内置组件,当它包裹动态组件时,会缓存不活动的组件实例,而不是销毁。我会以keepAlive的概念、使用keepAlive新增的钩子,使用场景,优点、缓存的方式有几种、引出的其他问题来串联keepAlive这个问题
概念:
keep-alive 是 Vue 的内置组件,当它包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。keep-alive 是一个抽象组件:它自身不会渲染成一个 DOM 元素,也不会出现在父组件中。
新增钩子:
被包含在 keep-alive 中创建的组件,会多出两个生命周期的钩子: activated(组件激活时使用) 与 deactivated(组价失活(离开)时调用)
使用场景:
例如有一个商品页面和一个详情页面,这样在两个页面切换的时候就可以用到keep-alive,在切换到详情的时候,把状态保留在内存中,而不是销毁,从而提高一个性能的优化,
优点:
优点是在组件切换过程中,把切换出去的组件保留在内存中,防止重复渲染DOM,减少加载时间及性能消耗,提高用户体验性,
缓存的方式有几种:
如果需要缓存整个项目,直接在app.vue中用keep-alive包裹router-view即可。
如果缓存部分页面,第一种是使用使用新增属性include/exclude,缓存部分页面,首先在data中定义,isKeep:[‘组件1’,‘组件2’],在keepAlive上用::include="iskeep",注意一定要在路由和被缓存的组件加上name否则缓存会失效
第二种是结合Router,router/index.js中通过设置路由元信息,指定属性缓存属性值为true,不缓存属性值为fasle,在app.vue中用keepAlive包裹要缓存的router-view,通过$router.meta.设置的路由原信息属性值获取,在keepAlive外在用v-if取反判断,v-if和v-else不是配套使用吗?为什么不使用v-else,v-if和v-else之间要挨着使用不然会报错!
V-if和v-show区别问题引出回流和重绘:
相同点都是动态控制元素的显示和隐藏
不同处v-if是动态的操作ui结构,比如新增元素、删除元素,而v-show是利用样式display:的值是不是none控制,适应场景,频繁的显示隐藏使用v-show,筛选和初始值用v-if,初始值是从头开始渲染一个元素,所以v-if更适合初始值
v-show触发了浏览器的重绘,v-if触发了浏览器的回流,
重绘:重绘是重新绘制页面外观,例如修改颜色属性
回流:回流是重新构建页面结构,例如新增标签 、删除标签等
外观改变不一定会重新构建页面结构,也就是我们常说的`重绘不一定回流`,
你把一个问题答道这种程度,在面试官眼中你就是
这个
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <div id="app"> <button @click="com = 'com1'">显示组件一</button> <button @click="com = 'com2'">显示组件二</button> <!-- is属性绑定的时当前需要使用的组件 --> <keep-alive> <component :is="com"></component> </keep-alive> <!--keep-alive会缓存当前组件而不是销毁它们,他自身不会渲染成dom元素,适用场景不需要变动的两个组件只是切换频繁,节省性能 --> </div> <script src="./js/vue.js"></script> <script> // 组件 1 const com1 = { template: ` <div>这是组件一的内容</div> `, created() { console.log('组件一创建了'); }, activated() { console.log('组件一激活了') }, deactivated() { console.log('组件一失活了') }, beforeDestroy() { console.log('组件一销毁之前') }, destroyed() { console.log('组件一销毁之后') }, } // 组件 2 const com2 = { template: ` <div>这是组件二的内容</div> `, created() { console.log('组件二创建了'); }, activated() { console.log('组件二激活了') }, deactivated() { console.log('组件二失活了') }, beforeDestroy() { console.log('组件二销毁之前') }, destroyed() { console.log('组件二销毁之后') }, } new Vue({ components: { com1, com2 }, data: { // 1 默认显示 com1组件 com: 'com1' }, }).$mount('#app') </script> </body> </html>
项目动态组件
上面我写在一个html中 没用cli,下面我再用项目创建一个动态组件
第一:新建两个子组件如下图
第二 :在父组件引入 注册 使用 ,在data定义默认显示的组件 例如 com, 在动态组件上写 :is="com"
<keep-alive> <component :is="com"></component> </keep-alive> </div> data() { return { com: "com", }; },
如图所示
效果
keep-alive会缓存当前组件而不是销毁它们,他自身不会渲染成dom元素,所以log的销毁钩子函数不起作用