js onscroll android,JavaScript触发onScroll事件的函数节流详解

5268f80b9b1e01f982625ef6fac83ca1.png

问题描述

常见的网站布局,顶部一个导航栏,我们假设本页面共有四个栏目:分别为A、B、C、D,我们点击A,锚点跳转至A栏目,同时顶部的A按钮高亮;点击B,锚点跳转至B栏目,同时顶部的B按钮高亮;我们在Main组件里面滚动,滚动到B模块时,B按钮高亮。以上是我们经常会在开发中遇到的一个模型。如果是在以前,用jQuery作前端开发的话,实在是太熟悉不过了。

解决方案

主要想谈谈在React组件化开发中的性能优化方法。

我们的页面结构是这样的

className={style.main}

id="main"

ref={(main) => { this.main = main; }}

onScroll={

((/detail/.test(this.props.location.pathname))) ? (() => this.throttle()()) : null

}

>

{this.props.children}

我们在main组件里设定onScroll事件,在这个事件中,我们触发action,通过redux将状态的变化传递到子组件。

我的scroll事件触发函数是这样的(忽略一长串的if else,这是一个解决了一下午的bug的终极解决方案,此文不做累述)handleScroll() {

const { changeScrollFlag } = this.props.actions;

// 根据滚动距离修改TitleBox的样式

const { basicinformation, holderinformation, mainpeople, changerecord } = {

basicinformation: document.getElementById('basicinformation').offsetTop - 121,

holderinformation: document.getElementById('holderinformation').offsetTop - 121,

mainpeople: document.getElementById('mainpeople').offsetTop - 121,

changerecord: document.getElementById('changerecord').offsetTop - 121,

};

if (window.screen.availHeight > this.main.scrollTop) {

document.getElementById('gototop').style.display = 'none';

} else {

document.getElementById('gototop').style.display = 'block';

}

// 得到基础信息区域、股东信息区域、主要人员区域、变更记录区域的offsetTop,我们把它用来跟main的scrollTop比较

// 比较的结果触发action,改变TitleBox组件样式

if (this.main.scrollTop < holderinformation) {

// 基础信息区域

if (basicinformation === -121) {

// 如果基础信息模块不存在,我们什么也不做(当然理论上基础信息模块应该是会有的)

return;

}

changeScrollFlag(1);

return;

} else if (this.main.scrollTop < mainpeople) {

// 股东信息区域

changeScrollFlag(2);

if (holderinformation === -121) {

// 如果股东信息栏目不存在,在滚动的时候我们不应该强行把TileBox的高亮按钮设置为holderinformation

// 因为holdinformation并不存在,我们跳到前一个按钮,让基础信息按钮高亮

changeScrollFlag(1);

return;

}

return;

} else if (this.main.scrollTop < changerecord) {

// 主要人员区域

changeScrollFlag(3);

if (mainpeople === -121) {

// 如果主要人员栏目不存在,在滚动的时候我们不应该强行把TileBox的高亮按钮设置为mainpeople

// mainpeople并不存在,我们跳到前一个按钮,让基础信息按钮高亮

changeScrollFlag(2);

if (holderinformation === -121) {

// 如果主要人员栏目不存在,而且连股东信息栏目也没有,我们跳到高亮基础信息栏目

changeScrollFlag(1);

return;

}

return;

}

return;

} else if (this.main.scrollTop > changerecord) {

// 与上面同理

// 变更记录区域

changeScrollFlag(4);

if (changerecord === -121) {

changeScrollFlag(3);

if (mainpeople === -121) {

changeScrollFlag(2);

if (holderinformation === -121) {

changeScrollFlag(1);

return;

}

return;

}

return;

}

return;

}

}

其中,changeScrollFlag()函数是我们的action处理函数。

我们的函数节流throttle() {

// onScroll函数节流

let previous = 0;

// previous初始设置上一次调用 onScroll 函数时间点为 0。

let timeout;

const wait = 250;

// 250毫秒触发一次

return () => {

const now = Date.now();

const remaining = wait - (now - previous);

if (remaining <= 0) {

if (timeout) {

window.clearTimeout(timeout);

}

previous = now;

timeout = null;

this.handleScroll();

} else if (!timeout) {

timeout = window.setTimeout(this.handleScroll, wait);

}

};

}

我们的节流函数返回一个函数,设定一个时间戳,如果我们时间戳的差值较小,我们什么也不做,但我们的时间戳的差值较大,清除定时器,触发scroll函数。这样看起来似乎挺简单,对,确实是挺简单的。

那么在子组件我们还需要怎么做呢?

接收action

二级容器型组件接收action,通过二级容器型组件传递props至三级展示型组件。

我们一定要在componentWillReceiveProps接收到这个props。

记住,在componentWillReceiveProps里使用this.props是并不能够接收到props的变化的!!!组件生命周期函数含有一个自己的参数。componentWillReceiveProps(nextProps) {

// 在compoWillReceiveProps里接收到Main组件里所触发onScroll事件的改变activebtn样式的index

// 并且设置为本组件的state

this.setState({

activebtn: nextProps.scrollFlag.scrollIndex,

});

}

我们的state控制我们高亮的按钮是第几个,它是一个数字。

更改导航条的样式

className={classnames({

[style.informationactive]: (this.state.activebtn === 1),

})}

onClick={() => this.handleClick(1, 'basicinformation')}

>

在此,我们完成了一次从顶层组件触发事件,并做到函数节流,将事件一层层传递至底层展示型组件的一个过程。

最近一些关于前端开发的感慨

不要在组件中反复调用一个函数,这样会造成巨大的消耗!我们可以通过三元运算符、模板字符串做到的事情,请勿写一个新的函数。

jsx不要太过于冗余。我们尽量写成变量的形式,不然页面结构复杂,不易于我们捕捉bug。

减少后端请求,能存cookie则存cookie,能存localStorge则存localStorge。

简单的组件尽量自己写,请勿使用别人的组件,否则在需求更改、样式调整上会出现巨大困难并做一些无意义的事儿。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流。

更多JavaScript触发onScroll事件的函数节流详解相关文章请关注PHP中文网!

1428d0e076c3959ab11d28a39bc84fab.png

5268f80b9b1e01f982625ef6fac83ca1.png

本条技术文章来源于互联网,如果无意侵犯您的权益请点击此处反馈版权投诉

本文系统来源:php中文网

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值