Vue 从列表页面进入详情页面,再次返回原页面,不清空查询条件或滚动位置

www.jswusn.com Other 2025-01-09 09:44:01 9次浏览

问题描述

当我们在列表页面进行了搜索操作,进入详情页面后再返回,我们会发现列表页面的搜索条件被清空了。第一时间我们想到的肯定是使用,Store存储搜索栏中的数据,当页面返回的时候再重新显示搜索数据,当然这没有问题,但相比于使用keep-alive 就显得有些多余了。在移动端,在进入详情页面之后,保留列表页面的状态是更为常见的需求。

keep-alive 解决问题的原理很简单,keep-alive是vue中的内置组件,能在组件切换过程中将状态保留在内存中,防止重复渲染DOM,关于keep-alive更多使用方法可以查看keep-alive官方文档。

下面我们就使用 keep-alive 来更优雅的解决这个问题。

解决方法

我们的需求并不是每个页面都需要进行缓存,通常只有下面的情况我们需要缓存:

从首页–>列表页–>商详页–>返回到列表页(需要缓存)–>返回到首页(需要缓存)–>再次进入列表页(不需要缓存)。

这时候可以按需来控制页面的keep-alive,我们可以在配置路由的时候添加 isKeepAlive属性来实现。

const router = new VueRouter({  
  routes:[     
      {         
        path:'/',       
        name:'home',      
        component:home,      
        meta:{isKeepAlive:true}    
      },      
    {        
      path:'/news',     
      name:'news',        
      component:news,        
      meta:{isKeepAlive:true}   
    },      
    {      
      path:'/play',    
      component:play,     
      meta:{isKeepAlive:false}    
    },     
    ......   
  ]
})

在渲染页面的时候,再根据isKeepAlive的配置来使用<keep-alive>对页面进行缓存。

<keep-alive  v-if="route.meta.isKeepAlive"> 
  <router-view  :key="route.path"  />
</keep-alive>
<router-view  :key="route.path"  v-else  />

如果你的每一个路由都是配置的不同页面组件,上面的代码已经你能完全满足需求了,不同的组件会根据 isKeepAlive 配置进行缓存。

但如果你遇到的问题也像我们的项目一样,每个页面都是通过动态生成的,也就是说所有的路由都指向同一组件 @/views/index.vue ,那就会出现所以页面都会被同时缓存或者同时不被缓存的情况,这显然不是我们配置想要达到对效果。

const  router =  new  VueRouter({    
  routes:[       
      {               
        path:'/',       
        name:'home',          
        component:  () =>  import('@/views/index.vue'),        
        meta:{isKeepAlive:true}         
      },        
    {        
      path:'/news',       
      name:'news',        
      component:  () =>  import('@/views/index.vue'),      
      meta:{isKeepAlive:true}        
    },        
    {       
      path:'/play',      
      component:  () =>  import('@/views/index.vue'),       
      meta:{isKeepAlive:false}        
    },        
    ......    
  ]
})

为了解决这个问题可以在原组件外包装一层,使用路径作为唯一标识。通过isKeepAlive将需要缓存的页面添加到cacheRoutes实现不同页面的缓存。

import  { h, ref }  from  'vue'
import  {  type  RouteLocationNormalizedLoadedGeneric }  from  'vue-router'
// 用来存已经创建的组件
const storeComponents  = new Map()
// 用来存需要缓存的路由
const cacheRoutes = ref<string[]>([])
// 原组件包里面
function formatComponent(component:  object, route: RouteLocationNormalizedLoadedGeneric) { 
  let afterComponent  
  if  (component) {   
    const path = route.path   
    if  (storeComponents.has(path)) {   
      afterComponent = storeComponents.get(path)   
    }  else  {     
      afterComponent = {    
        name: path,      
        render() {      
          return  h(component)       
        },      
      }      
      if  (route.meta.isKeepAlive) 
        cacheRoutes.value.push(path)
      //进行缓存     
      storeComponents.set(path, afterComponent)   
    }    
    return  h(afterComponent) 
  }
}

页面代码也需要改成了下面的样子,通过include指定需要缓存的组件名称。

<router-view  v-slot="{ Component, route }">
  <keep-alive  :include="cacheRoutes">   
    <component  :is="formatComponent(Component, route)"  /> </keep-alive>
</router-view>

结语

keep-alive 可以保证页面不刷新,不仅可以解决搜索框被清空的问题,还可以解决滚动了页面滚动条,进入其他页面后再返回,滚动条又回到了顶部的问题。

上面就是我对这个问题的最佳实践了,希望能对你有所帮助。


技术分享

苏南名片

  • 联系人:吴经理
  • 电话:152-1887-1916
  • 邮箱:message@jswusn.com
  • 地址:江苏省苏州市相城区

热门文章

Copyright © 2018-2025 jswusn.com 版权所有

技术支持:苏州网站建设  苏ICP备18036849号