keep-alive一般被用来缓存组件实例.当从一个组件切换到另一个时, 这个组件不会被销毁, 而会被保存起来供下次调用时使用.
遗憾的是, 如果被keep-alive包裹的组件中有滚动元素,keep-alive不会储存滚动位置.
需要在滚动时储存位置, 然后在组件被激活时还原.
keep-alive 组件有两个特殊的生命周期钩子: activated和deactivated.
activated在keep-alive组件激活时调用.
deactivated在keep-alive组件被停用时调用.
API — Vue.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| { mounted() { const page = this.$el; page.addEventListener("scroll", () => { this.scrollTop = page.scrollTop; }); }, activated() { if (this.scrollTop) { const page = this.$el; page.scrollTop = this.scrollTop; } }, deactivated() {} };
|
另外,可以将这段代码储存为mixin, 需要时调用即可.
See the Pen
[Vue] 记录keep-alive内组件的滚动位置 by aaronbird (@aaronbird)
on CodePen.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.9/vue.min.js"> <div class="app"> <div class="main"> <keep-alive> <component :is="componentName"> </keep-alive> </div> <div class="navs"> <div class="nav" @click="componentName = tag" v-for="tag of tags"> {{tag}} </div> </div> </div>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| body { margin: 0; font-size: 20px; }
@mixin pin() { position: absolute; top: 0; left: 0; right: 0; bottom: 0; overflow: auto; }
.app { height: 100vh; display: flex; flex-direction: column; .main { position: relative; flex: 1 1 auto; overflow: hidden; text-align: center; .home { color: red; background: blue; @include pin(); } .shop { color: blue; background: red; @include pin(); } } .navs { display: flex; flex: 0 0 50px; background: #ffa; align-items: center; .nav { flex: 1 1 auto; height: 100%; line-height: 50px; text-align: center; border-right: 1px solid rgba(0, 0, 0, 0.2); &:last-child { border-right: none; } } } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| const keepScrollTop = { mounted() { const page = this.$el; page.addEventListener("scroll", () => { this.scrollTop = page.scrollTop; }); }, activated() { if (this.scrollTop) { const page = this.$el; page.scrollTop = this.scrollTop; } }, deactivated() {} };
Vue.component("home", { mixins: [keepScrollTop], template: ` <div class="home"> <div v-for="i of 50">{{i}}</div> </div> ` });
Vue.component("shop", { mixins: [keepScrollTop], template: ` <div class="shop"> <div v-for="i of 50">{{i}}</div> </div> ` });
const app = new Vue({ el: ".app", data: { tags: ["home", "shop"], componentName: "home" } });
|