乐趣区

关于前端:手摸手教你实现移动端滚动记忆带分页

前戏:

在挪动端网页中的列表如何实现滚动和搜寻条件的记忆,相似微信文章一样,浏览到文章的某一个地位,在下次关上的时候仍然能滚动到上次浏览的地位持续浏览。本篇文章介绍的是带分页的列表,如果你当初需要是不带分页的文章或列表当然也能够参考,实现形式根本是差不多的。

因为这里应用了 mui 的下拉刷新的列表组件,要在 tab 切换时须要默认把滚动条重置到最顶部(从头开始浏览),refreshContainer为对应列表 id
mui 列表组件相干的代码能够参考我之前的文章:
【mui 多个 tab 页实现下拉刷新上拉加载】https://segmentfault.com/a/11…

mui("#refreshContainer").scroll().scrollTo(0, 0, 0);//tab 切换时默认滚到顶部

在页面加载实现时定义一些工具函数:
localGet 就是 localStorage.getItem 的一个简略封装

  if (localGet("woAppInfo") == null){// 首次加载读取上一次的查问条件
     saveWoAppInfo({
       tabId: "untreated",
       scrollTop: 0,
     });
     }

/**
 * 防抖函数
 * @param {须要防抖的函数} func
 * @param {防抖时间段} delay
 */
function debounce(fn, wait) {
  var timer = null;
  return function () {if (timer !== null) {clearTimeout(timer);
    }
    timer = setTimeout(fn.bind(this), wait);
  };
}
function saveWoAppInfo(woappInfo){localStorage.setItem("woAppInfo", JSON.stringify(woappInfo));
}

当列表数据渲染实现时执行 autoScrollTo 滚动到上次地位

function autoScrollTo() {setTimeout(function () {
    var scrollTop1 =
      localGet("woAppInfo") && JSON.parse(localGet("woAppInfo")).scrollTop;
    
    // mui("#refreshContainer").scroll().scrollTo(0, -1000, 0);
    // $("#refreshContainer").scrollTop(scrollTop);
      
    mui("#refreshContainer").pullRefresh().scrollTo(0, scrollTop1, 0);
  }, 500);
}

留神点:

列表分页的代码逻辑因为不是文章次要内容就在这里就不给大家阐明了,大抵逻辑是用户滚动到底部(最初一条记录)-> 触发 mui 列表的上拉回调函数 -> 通过以后分页数据对下一页数据持续进行获取 ->append 到列表前面实现分页

queryObj对象是在搜寻和 tab 切换的的时候把搜寻条件以 key-value 的模式存到外面,当在下次页面关上时就默认应用 AppInfo 中的搜寻条件达到搜寻条件记忆的成果。
scroll.y为以后滚动条间隔到页面列表顶部的高度数值,因为在顶部往上拉时滚动条超出顶部就有可能是正数所以须要应用绝对值 Math.abs
滚动事件初始化(autoScrollInit)这里也要给组件的默认滚动到上次地位:

function autoScrollInit() {var scroll = mui("#refreshContainer").scroll({
    scrollY: true, // 是否竖向滚动
    scrollX: false, // 是否横向滚动
    startY:
      localGet("woAppInfo") && JSON.parse(localGet("woAppInfo")).scrollTop,
    indicators: false,
  });

  document.querySelector("#refreshContainer").addEventListener(
    "scroll",
    debounce(function () {var href = $(".A-tab span.active").attr("href");
      var queryObj = JSON.parse(localGet("woAppInfo")).queryObj || {};
      var pageSize = pages[href].pageSize;
      var listItemHeight = 110;// 列表中单条记录的高度
      queryObj.pageCount =
        Math.floor(Math.abs(scroll.y) / (pageSize * listItemHeight) + 1) *
        pageSize; // 每页数量 = 以后下拉的间隔长度 /(一页的长度) * pageSize
      saveWoAppInfo({
        tabId: href,
        queryObj: queryObj,
        scrollTop: Number(scroll.y.toFixed()),
      });
    }, 1000)
  );
}

var woAppInfo = localGet("woAppInfo") && JSON.parse(localGet("woAppInfo"));
var tabId = woAppInfo.tabId;
// 主动抉择上一次的顶部 tab 页
if (tabId){$('span[href="' + tabId + '"]').addClass("active");
  $(".list[id='" + tabId + "']").addClass("active");
}else{$('span[href="untreated"]').addClass("active");
    $(".list[id='untreated']").addClass("active");
}   

分页滚动记忆原理:

listItemHeight 为单条记录的高度,能够本人依据单条记录的高度来设定,有了这个高度而后通过以后列表中的滚动条 y 轴地位到顶部数值计算出滚动条到第一条记录的列表条数(pagecount)Math.floor(Math.abs(scroll.y) / (pageSize * listItemHeight) + 1) * pageSize;
这样做的起因是咱们列表是分页加载的数据,所以为了下次可能滚到记忆的地位所以这里要计算一下记忆须要的记录条数和搜寻条件,而后保留到 AppInfo 中,在下次获取数据时通过 pageCount 每页数量去申请数据间接就能还原出上次的数据量这样能力和 scroll.y 的地位匹配得上。(因为如果上次滚动条地位是几百条的 y 轴地位,但这次记忆滚动的时候却才加载了几条数据,所以就导致因为数据有余天然就没方法滚动到几百条的地位)
在列表数据申请时(搜寻或者初始加载),如果是一般的初始进入的加载才进行记忆,在列表渲染实现后首先初始化监听列表的滚动事件,而后再还原上次滚动条的地位(autoScrollTo间接主动滚动到对应地位),并在滚动时取出以后的搜寻条件和 tab 的 id 用于保留,留神这里为了性能问题须要设置防抖,抖到 1s 后再保留数据

执行 saveWoAppInfo 后的 AppInfo 存储状况:

以下是列表申请的代码:


var woAppInfo =
 localGet("woAppInfo") && JSON.parse(localGet("woAppInfo"));
 if (woAppInfo.queryObj && woAppInfo.queryObj.pageCount) {data.data.pageCount = woAppInfo.queryObj.pageCount;}

  ajax(data, {success: function (json) {
         var woAppInfo =
           localGet("woAppInfo") && JSON.parse(localGet("woAppInfo"));
               if (data.data.isSearch) {
                // 当携带查问条件时默认滚到顶部
                 mui("#refreshContainer").scroll().scrollTo(0, 0, 0);
                 mui("#refreshContainer").pullRefresh().scrollTo(0, 0, 0);
               }
            if (
              data.data.isSearch == undefined &&
              woAppInfo.tabId === data.data.href
            ) {// 当首次进入时对以后 tab 进行滚动记忆
                  autoScrollInit();
                  autoScrollTo();}
       
    },
    fail: function (json) {...},
    error: function (e) {...},
  });

当列表触发下拉刷新回调时从新革除搜寻条件(因为相当于从新加载列表 不算上条件了),并保留以后 tabid:

// 清空查问参数
function clearSearchParams() {
  cacheObj = {
    // 存储搜寻时的搜寻条件
    xxxx: "",
    aaa: "",
    id: href === "all" ? user.id : "",
  };
 saveWoAppInfo({tabId: href, scrollTop: 0});
}

    function pulldownRefresh() {var href = $(".A-tab span.active").attr("href");

      clearSearchParams(href);
    fetchData(function () {// 加载列表
      mui("#refreshContainer").pullRefresh().endPulldownToRefresh();
    });
  }

总结:

本篇次要阐明了挪动端 h5 中的分页列表如何进行滚动的记忆
简略来说就是通过浏览器的 Scroll 事件对列表滚动条的 y 轴地位保留到 localStorage 中,在下次加载再通过主动滚动的办法滚动到上次地位,然而留神要通过计算还原出上次所记忆的数据量,因为须要足够的 y 轴空间去滚动。
如果感觉好的话心愿大家给个赞~ 非常感谢

【手摸手教你实现页面 tab 和导航菜单记忆性能】https://segmentfault.com/a/11…

退出移动版