前因

事实上这一功能一开始并不在需求中有描述,初期和后端进行联调时,产品看着页面的数据忽然提出了这个问题,于是实现这个功能的漫长过程就开始了。

构思及问题

关于上拉加载

基于 h5 这种方式实现的上拉加载并不能很好的完美达到要求,只能说是有这一功能罢了。(也可能是我不会。)

初步的构思是监听页面的滚动距离,即获取页面的总高度、可视区的高度以及滚动的高度,这样当:滚动的高度 + 可视区高度 + h >= 总高度(h为一个预设的固定值,确保可以让等号左边一定大于右边)即视为可以去触发 fetch 请求,加载下一页的数据。

let clientHeight = dom.clientHeight; // 可视区高度
let scrollHeight = dom.scrollHeight; // 总高度
let scrollTop = dom.scrollTop || window.pageYOffset || document.body.scrollTop; // 滚动高度

// 滚动高度 + 可视区高度 + 100 >= 总高度 即视为到底
if (scrollTop + clientHeight + 100 >= scrollHeight) {
    // do somethings
}

然后我们在 useEffect() 中监听页面滚动事件,相应的我们要根据数据的变动去触发对应的页面变化,所以第二个参数填写了3条。

useEffect(() => {
    document.addEventListener('scroll', debounceFunc);
    return () => {
        document.removeEventListener('scroll', debounceFunc);
    };
}, [concatActive, concatCarData, noConcatCarData]);

但这也产生了一个问题,就是每次页面执行对应的 fetch 请求都会执行3次,我们又不能再去引入另外的 state 去存储对应的 true or false 用以管理所执行的 fetch 方法,因为对应的 state 都需要被添加到 useEffect() 参数中,这样只会导致状态更加混乱。

这里不得不引入了额外的全局变量对对应页面的 fetch 请求进行管理。

let loading1 = false
let loading2 = false

...

if (tmp1 < pageCount1 && !loading1 && concatActive) {
    setL1(true);
    tmp1 += 1;
    loading1 = !!1;
    dropDownFetch(tmp1); // fetch 方法
}

...

const dropDownFetch = () => {
    fetch().then(data => {
        if (data.respCode == 0) {
            ...
        
            loading1 = false // 请求到下一页数据,重新设定为 false
        }
    })
}

本来到这里,上拉加载其实可以告一段落了,这时产品又要求在页面到底部的时候添加上对应的 loading 标志,因为是临时的要求,所以并没有对应的设计,只能自行手绘了一个。

<style>
ul {
    display: flex;
}

ul li {
    list-style: none;
    background: #ED4C67;
    border-radius: 50%;
    width: 8px;
    height: 8px;
    margin: 6px;
    animation: animate .7s infinite linear alternate;
}

@keyframes animate {
    0% {
        transform: scale(0);
    }

    100% {
        transform: scale(1);
    }
}

ul li:nth-child(2) {
    animation-delay: -.15s;
}

ul li:nth-child(3) {
    animation-delay: -.3s;
}
</style>

<div className="xiansuo-loading">
    <ul>
        <li></li>
        <li></li>
        <li></li>
    </ul>
    or 
    "·我是有底线的·"
</div>

这里需要在页面初次进入时显示 ul 对应的 loading 效果,在页面上拉加载时没有后续数据的时候显示相应的文字,于是再一次引入了另外的全局变量,这里对变量进行了如下判断,如果当前页码不是最后一页则一直展示 loading 。

if (pageIndex < pageCount) {
    setL1(true)
} else {
    setL1(false)
}

存在的问题

目前页面只能说是可以使用,但是现有的逻辑比较混乱,方法没有进行抽离,且页面存在大量的全局变量,同时也设定了多个功能相对重复的 state 用以管理,后续待抽离相应的方法,理顺页面逻辑,同时考虑使用更好的方式去管理状态以及多余的全局变量。

结语

实际上这两天处理问题时候远没有我现在写的这么清晰,一方面需要考虑开发平台:PC端正常显示、Android端正常显示、IOS端无法显示,另一方面因为一直处于焦急的状态,所以代码写的十分混乱,同样由于对 hooks 以及移动端 的不够熟悉,coding过程中还是出现了很多意料之外的问题。

后续继续努力,调整心态,好好开发。

Last modification:November 15th, 2020 at 05:36 pm
如果觉得我的文章对你有用,请随意赞赏