5 分钟带你实现一个多页签返回定位的列表组件

简介: 实现一个多页签返回定位的列表组件

a429aaef1bd8b9ccc59a1619ce30f16.png

项目地址(持续迭代中):github.com/jyliyue/vit…

系列文章:

前言

移动端有个常见的业务场景,在列表页滑动进入某一个详情页,回退的时候希望列表能够停留在原先访问的位置,本篇便针对这一需求,带大家一起完善我们的列表组件,顺便结合这个列表组件 实现一个多标签列表返回定位 的案例

思路

这一功能的实现网上已有很多相关案例,但大多都使用了监听滚动事件,动态的记录滚动位置,但分析下来这一功能实现实际上并不需要实时监听,只需要在 离开页面时记录滚动位置 ,重新进入页面时赋值就好了

按照这个思路,我们需要完成三步:

  • 缓存组件,即切换页面时页面组件不会被销毁
  • 记录位置,页面离开时记录滚动条位置
  • 重新定位,重新进入页面时定位到之前记录的位置

缓存组件

这里我们可以用之前已经实现的 <app-router-view> 组件来实现,借助 keepAlive 帮助我们实现页面离开时缓存页面的状态

a9c6a300cbc591882e8dfba58a6ff0c.png

关于 keepAlive 的相关讲解大家可以阅读我的另一篇文章,这里就不赘述了

传送门:5 分钟带你实现一个可控制缓存销毁的 keepAlive 组件

记录位置

这里使用我们之前封装好的列表组件 <app-list> 来进行改造

我们写一个通用方法 useScrollCache 来完成整一块滚动定位缓存这一需求的逻辑,首先我们定义一个 listRef 来获取我们列表盒子的 dom 元素,然后通过路由钩子 onBeforeRouteLeave 当页面离开前,把当前的滚动位置 listRef.value.scrollTop 记录下来,这样就完成了位置记录

<script setup>
import { onBeforeRouteLeave } from 'vue-router'
const { listRef } = useScrollCache()
/**
 * @description: 滚动定位缓存
 */
function useScrollCache() {
    const listRef = ref(null)
    let scrollTop = 0
    onBeforeRouteLeave(() => {
        scrollTop = listRef.value.scrollTop
    })
    return {
        listRef
    }
}
</script>
<template>
    <div class="app-list" ref="listRef">
        <van-pull-refresh
            v-model="refreshing"
            :success-text="successText"
            @refresh="onRefresh"
        >
            <van-list
                v-model:loading="loading"
                @load="onLoad"
                :finished="finished"
                :finished-text="finishedText"
                :offset="100"
            >
                <slot name="content" :list="list"> </slot>
            </van-list>
        </van-pull-refresh>
    </div>
</template>
<style lang="scss" scoped>
.app-list {
    height: 100%;
    overflow-y: auto;
}
</style>
复制代码

重新定位

因为我们使用了keepAlive,当我们离开重新进入页面时,会触发 onActivated 生命周期,我们只要在这里把之前记录的位置重新赋值给列表就可以了

完整代码

<script setup>
import { onBeforeRouteLeave } from 'vue-router'
const { listRef } = useScrollCache()
/**
 * @description: 滚动定位缓存
 */
function useScrollCache() {
    const listRef = ref(null)
    let scrollTop = 0
    onActivated(() => {
        // 激活时重新定位
        listRef.value.scrollTop = scrollTop
    })
    onBeforeRouteLeave(() => {
        // 离开记录位置
        scrollTop = listRef.value.scrollTop
    })
    return {
        listRef
    }
}
</script>
复制代码

这样,我们一个简单的列表返回记录位置的功能就实现啦,来看看效果

e00668fe9aeeb8bb40c82ed463412a0.png

做一个多 Tab 列表切换案例

现在来一起使用我们封装的组件实现一个多页签列表的案例

我们使用 <van-tab> 来做多标签,使用 setTimeout 来模拟数据请求,这里需要注意一点需要把 :animated="true" 设置一下,由于不开启动画效果的话,<app-list> 实例在切换时会被销毁掉,这样处理起来逻辑就变复杂了,这里我们使用动画过度,操作体验也会更友好一点

<script setup>
// This starter template is using Vue 3 <script setup> SFCs
const options1 = {
    getData: () => {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve({
                    data: new Array(20),
                    total: 30
                })
            }, 1000)
        })
    }
}
const options2 = {
    getData: () => {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve({
                    data: new Array(20),
                    total: 30
                })
            }, 1000)
        })
    }
}
const activeName = ref('a')
</script>
<template>
    <app-page>
        <van-tabs
            class="app-tab-list"
            v-model:active="activeName"
            :animated="true"
        >
            <van-tab title="标签 1" name="a">
                <app-list :options="options1">
                    <template #content="{ list }">
                        <van-cell
                            v-for="(item, index) in list"
                            :key="index"
                            :title="index"
                        />
                    </template>
                </app-list>
            </van-tab>
            <van-tab title="标签 2" name="b">
                <app-list :options="options2">
                    <template #content="{ list }">
                        <van-cell
                            v-for="(item, index) in list"
                            :key="index"
                            :title="index"
                        />
                    </template>
                </app-list>
            </van-tab>
            <van-tab title="标签 3" name="c"> c </van-tab>
        </van-tabs>
    </app-page>
</template>
复制代码

大家来一起看看效果

b48a1b0c9f64753adb33d4ad023d300.png

好了,本篇的内容比较简单也比较实用,希望能对大家完成需求有所帮助,下一篇,我们将对 Vue 自定义指令相关的知识点做讲解,并带大家一起实现一些移动端常用的指令,例如防抖截流,长按事件监听,点击复制文本等等,敬请期待!

相关文章
|
2月前
|
存储 移动开发 JavaScript
使用vuex记住当前页面页码信息,以便从详情页返回列表页时能还原到上一次页面
使用vuex记住当前页面页码信息,以便从详情页返回列表页时能还原到上一次页面
37 0
|
7月前
|
数据采集 JSON 小程序
小程序警告:根据 sitemap 的规则[0],当前页面 [pagesindexindex] 将被索引
这是一个警告的提示,至于是否影响性能,这个我不太清除。 根据官方文档的说法:微信已开放小程序内搜索,开发者可以通过 sitemap.json 配置,或者管理后台页面收录开关来配置其小程序页面是否允许微信索引。当开发者允许微信索引时,微信会通过爬虫的形式,为小程序的页面内容建立索引。 就是说用户可以根据微信吧爬虫给你提供的索引更快的搜索到你。 最简单的方法就是你直接把配置关了不让他索引:
144 0
|
8月前
|
数据处理 网络架构
ElementUI - 主页面--动态树&右侧内容管理
ElementUI - 主页面--动态树&右侧内容管理
54 0
|
8月前
|
前端开发
Bootstrap tab页签刷新加载不显示,只有点击其他标签后第一个才显示
Bootstrap tab页签刷新加载不显示,只有点击其他标签后第一个才显示
|
10月前
|
JavaScript
vue项目:商品列表页的渲染,删除,搜索,面包屑导航
vue项目:商品列表页的渲染,删除,搜索,面包屑导航
90 0
|
前端开发
前端列表页+element-puls实现列表数据弹窗功能
前端列表页+element-puls实现列表数据弹窗功能
309 0
|
小程序 API
【小程序】案例 - 本地生活(列表页面)
【小程序】案例 - 本地生活(列表页面)
122 0
【小程序】案例 - 本地生活(列表页面)
|
前端开发 开发者
评论列表案例-创建 CmtList 组件并渲染基本页面结构|学习笔记
快速学习评论列表案例-创建 CmtList 组件并渲染基本页面结构
125 0
评论列表案例-创建 CmtList 组件并渲染基本页面结构|学习笔记
ionic3 导航栏返回按钮事件设置 多级页面返回到指定的页面
ionic3 导航栏返回按钮事件设置 多级页面返回到指定的页面
|
前端开发
评论列表案例-创建CmtList组件并渲染基本页面结构
评论列表案例-创建CmtList组件并渲染基本页面结构
评论列表案例-创建CmtList组件并渲染基本页面结构