feb-alive

github地址
体验链接

使用理由

  • 开发者无需因为动态路由或者普通路由的差异而将数据初始化逻辑写在不同的钩子里beforeRouteUpdate或者activated
  • 开发者无需手动缓存页面状态,例如通过localStorage或者sessionStorage缓存当前页面的数据
  • feb-alive会帮你处理路由meta信息的存储与恢复

为什么开发feb-laive?

当我们通过Vue开发项目时候,是否会有以下场景需求?

  • /a跳转到/b
  • 后退到/a时候,希望从缓存中恢复页面
  • 再次跳转到/b时,分两种情况
    • 情况一: 通过链接或者push跳转,则希望重新创建/b页面,而不是从缓存中读取
    • 情况二: 如果点击浏览器自带前进按钮,则还是从缓存中读取页面。

这个场景需求着重强调了缓存,缓存带来的好处是,我上次页面的数据及状态都被保留,无需在从服务器拉取数据,使用户体验大大提高。

尝试用keep-alive实现页面缓存

<keep-alive>
 <router-view></router-view>
</keep-alive>

so easy但是理想很完美,现实很残酷

存在问题

-/a跳到/b,再跳转到/a 的时候,页面中的数据是第一次访问的/a页面,明明是链接跳转,确出现了缓存的效果,而我们期望的是像app一样开启一个新的页面。

  • 同理动态路由跳转/page/1->/page/2因为两个页面引用的是同一个组件,所以跳转时页面就不会有任何改变,因为keep-alive的缓存的key是根据组件来生成的(当然Vue提供了beforeRouteUpdate钩子供我们刷新数据)
  • 总结:keep-alive的缓存是==组件级别==的,而不是==页面级别==的。

举个应用场景

例如浏览文章页面,依次访问3篇文章

  • /artical/1
  • /artical/2
  • /artical/3

当我从/artical/3后退到/artical/2时候,由于组件缓存,此时页面还是文章3的内容,所以必须通过beforeRouteUpdate来重新拉取页面2的数据。(注意此处后退不会触发组件的activated钩子,因为两个路由都渲染同个组件,所以实例会被复用,不会执行reactivateComponent)

如果你想从/artical/3后退到/artical/2时,同时想恢复之前在/artical/2中的一些状态,那么你还需要自己针对/artical/2中的所有状态数据进行存储和恢复。

综上:keep-alive实现的组件级别的缓存和我们想象中的缓存还是有差距的,keep-alive并不能满足我们的需求。

==针对这些问题,所以feb-alive插件诞生了==

由于feb-alive是基于keep-alive实现的,所以我们先简单分析一下keep-alive是如何实现缓存的

export default {
 name: 'keep-alive',
 abstract: true,

 props: {
 include: patternTypes,
 exclude: patternTypes,
 max: [String, Number]
 },

 created () {
 this.cache = Object.create(null)
 this.keys = []
 },

 destroyed () {
 for (const key in this.cache) {
  pruneCacheEntry(this.cache, key, this.keys)
 }
 },

 mounted () {
 this.$watch('include', val => {
  pruneCache(this, name => matches(val, name))
 })
 this.$watch('exclude', val => {
  pruneCache(this, name => !matches(val, name))
 })
 },

 render () {
 // 获取默认插槽
 const slot = this.$slots.default
 // 获取第一个组件,也就和官方说明的一样,keep-alive要求同时只有一个子元素被渲染,如果你在其中有 v-for 则不会工作。
 const vnode: VNode = getFirstComponentChild(slot)
 // 判断是否存在组件选项,也就是说只对组件有效,对于普通的元素则直接返回对应的vnode
 const componentOptions: "htmlcode">
created () {
 // 存储组件缓存
 this.cache = Object.create(null)
 this.keys = []
}

由于路由切换并不会销毁keep-alive组件,所以缓存是一直存在的(嵌套路由中,子路由外层的keep-alive情况会不一样,后续会提到)

继续看下keep-alive在缓存的存储和读取的具体实现,先用一个简单的demo来描述keep-alive对于组件的缓存以及恢复缓存的过程

let Foo = {
 template: '<div class="foo">foo component</div>',
 name: 'Foo'
}
let Bar = {
 template: '<div class="bar">bar component</div>',
 name: 'Bar'
}
let gvm = new Vue({
 el: '#app',
 template: `
  <div id="#app">
   <keep-alive>
    <component :is="renderCom"></component>
   </keep-alive>
   <button @click="change">切换组件</button>
  </div>
 `,
 components: {
  Foo,
  Bar
 },
 data: {
  renderCom: 'Foo'
 },
 methods: {
  change () {
   this.renderCom = this.renderCom === 'Foo' "htmlcode">
function anonymous(
) {
 with(this){return _c('div',{attrs:{"id":"#app"}},[_c('keep-alive',[_c(renderCom,
                                    

《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线

暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。

艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。

《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。