zoukankan      html  css  js  c++  java
  • vue——keepAlive第一次无效问题及解决方法

    搬运自:https://segmentfault.com/a/1190000019610283?utm_source=tag-newest

    vue官方API: https://cn.vuejs.org/v2/api/#keep-alive

    例:

    router.js:

    
    
    {
        path: '/home',
          name: 'Home',
          meta: {
            index: 0,
            keepAlive: true,
            title: '首页'
          },
          component: resolve => require(['../../../modules/Home'], resolve)
    },
    {
        path: '/list',
          name: 'List',
          meta: {
            index: 1,
            keepAlive: true,
            title: '列表页'
          },
          component: resolve => require(['../../../modules/List'], resolve)
    },
    {
          path: '/detail',
          name: 'Detail',
          meta: {
            index: 2,
            keepAlive: false,
            title: '详情页'
          },
          component: resolve => require(['../../../modules/Detail'], resolve)
    }

    问题:列表页进详情页时,首先第一次打开页面的时候并不缓存,即第一次从列表页跳到详情页,再回来并没有缓存。后面再进入详情页才会被缓存,并且只会缓存第一次进入的状态,不会重新请求数据。如果当首页选中一个分类跳到列表页,再从列表页面跳往详情页,此时会缓存这个状态,并且以后再从首页的其他分类跳到列表页都不会重新被缓存,以至于每次从详情页返回列表页都会跳第一次缓存的状态。当你的项目只有一种状态需要缓存,可以考虑使用这种方法。

    解决:使用 include + beforeRouteLeave 或者使用 include + beforeRouteLeave + vuex。

    方法一:使用 include + beforeRouteLeave 

    1、在创建router实例的时候加上scrollBehavior方法

    export default new Router({
      routes,
      scrollBehavior (to, from, savedPosition) {
        if (savedPosition) {
          return savedPosition
        } else {
          return {
            x: 0,
            y: 0
          }
        }
      }
    })

    2、将需要缓存的组件加在include属性里

    <keep-alive :include="['home','list','search']">
          <router-view></router-view>
    </keep-alive>

    3、在beforeRouteEnter的next回掉函数里,对返回A页面不需要缓存的的情况初始化,即将本来需要写在created里的东西写在这里;注意一定要将所有的需要初始化的数据要写一遍,不然会有bug;所以不太推荐

    beforeRouteEnter (to, from, next) {
        next(vm => {
          // 通过 `vm` 访问组件实例
          if (from.path !== '/goods_detail') { // 一定是从A进到B页面才刷新
            vm.titleText = vm.$route.query.name
            vm.categoryUpper = vm.$route.query.categoryUpper
            vm.goods = []
            vm.page = 1
            vm.catsIndex = 0
            vm.is_search = false
            vm.getCats2()// 是本来写在created里面的各种
          }
        })
      }

    方法二:使用 include + beforeRouteLeave + vuex 与方法一相似,不同的地方在于,将需要缓存的组件保存到全局变量,可以在路由的钩子函数里灵活的控制哪些组件需要缓存,那些不需要缓存;跟方法一相比,不需要每次再重新初始化数据,但是需要在vuex中保存数据;

    1、在创建router实例的时候加上scrollBehavior方法

    export default new Router({
      routes,
      scrollBehavior (to, from, savedPosition) {
        if (savedPosition) {
          return savedPosition
        } else {
          return {
            x: 0,
            y: 0
          }
        }
      }
    })

    2、将需要缓存的组件加在include属性里

    <keep-alive :include="catch_components">
          <router-view></router-view>
    </keep-alive>

    3、在store里加入需要缓存的的组件的变量名,和相应的方法;

    export default new Vuex.Store({
      state: {
        catch_components: []
      },
    mutations:{
        GET_CATCHE_COMPONENTS (state, data) {
          state.catch_components = data
        }
    }
    })

    4、在beforeRouteLeave钩子函数里控制需要缓存的组件

    beforeRouteLeave (to, from, next) { //要在离开该组件的时候控制需要缓存的组件,否则将出现第一次不缓存的情况
        this.busy = true
        if (to.path === '/goods_detail') { // 去往详情页的时候需要缓存组件,其他情况下不需要缓存
          this.$store.commit('GET_CATCHE_COMPONENTS', ['home']) //注意,'home'将匹配首先检查组件自身的 name 选项(非router.js里的),如果 name 选项不可用,则匹配它的局部注册名称 (父组件 components 选项的键值)。匿名组件不能被匹配。
        } else {
          this.$store.commit('GET_CATCHE_COMPONENTS', [])
        }
        next()
    }

     

  • 相关阅读:
    【干货分享】C# 实体类生成工具
    ASP.NET Core部署系列二:发布到CentOS上
    ASP.NET Core部署系列一:发布到IIS上
    微信公众号开发:用户管理
    微信公众号开发:自定义菜单
    像使用SQL一样对List对象集合进行排序
    使用JRebel插件实现SpringBoot应用代码热加载
    Java Stream函数式编程图文详解(二):管道数据处理
    SpringBoot生命周期管理之停掉应用服务几种方法
    本月16日SpringBoot2.2发布,有哪些变化先知晓
  • 原文地址:https://www.cnblogs.com/linjiangxian/p/12214745.html
Copyright © 2011-2022 走看看