在上章 “Vue.js 动态组件” 中,我们在一个多标签的界面中使用 is 属性来切换不同的组件,如下:
<!-- 动态组件,根据 currentTab 中的值(组件)动态加载组件 --> <component v-bind:is="currentTab"></component>
当在这些组件之间切换的时候,你有时会想保持这些组件的状态,以避免反复重新渲染导致的性能问题。例如一个多标签界面:
你会注意到,如果在 Home 标签中勾选了复选框,切换到 Posts 或 Archive 标签,然后再切换回 Home 标签,你会发现 Home 标签中的复选框没有被勾选。这是因为你每次切换新标签的时候,Vue 都创建了一个新的 currentTab 实例。
重新创建动态组件的行为通常是非常有用的,但是在这个示例中,我们更希望那些标签的组件实例能够被在它们第一次被创建的时候缓存下来。为了解决这个问题,我们可以用一个 <keep-alive> 元素将其动态组件包裹起来。例如:
<!-- 失活的组件将会被缓存!--> <keep-alive> <!-- 动态组件,根据 currentTab 中的值(组件)动态加载组件 --> <component v-bind:is="currentTab"></component> </keep-alive>
修改后的效果如下图:
现在这个 Home 标签保持了它的状态 (被选中的复选框) 甚至当它未被渲染时也是如此。
注意:这个 <keep-alive> 要求被切换到的组件都有自己的名字,不论是通过组件的 name 选项还是局部/全局注册。
<html> <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>Vue</title> <!-- 使用 CDN 引入 Vue 库 --> <!-- <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script> --> <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.7.9/vue.js"></script> </head> <body> <div id="app"> <div> <button type="button" v-on:click="currentTab='tab-home'">Home</button> <button type="button" v-on:click="currentTab='tab-posts'">Posts</button> <button type="button" v-on:click="currentTab='tab-archive'">Archive</button> </div> <div style="border:solid 1px #000;padding:20px;"> <!-- 失活的组件将会被缓存!--> <keep-alive> <!-- 动态组件,根据 currentTab 中的值(组件)动态加载组件 --> <component v-bind:is="currentTab"></component> </keep-alive> </div> </div> <script type="text/javascript"> Vue.component("tab-home", { template: ` <div> <input type="checkbox" /> Home component </div> ` }); Vue.component("tab-posts", { template: ` <div> <input type="checkbox" /> Posts component </div> ` }); Vue.component("tab-archive", { template: ` <div> <input type="checkbox" /> Archive component </div> ` }); var app = new Vue({ el: "#app", data: { currentTab: "tab-home" } }); </script> </body> </html>