玩游戏直播丢帧高为什么 玩CF和LOL不到100帧,,,,驱动都更新了。之前都300帧

《穿越火线》是一款全球火爆的第一人称射击游戏的网络游戏,也是最为大众化的FPS网游,玩家体验到的不仅仅体验到了开枪的爽快感,更是来自相互合作及默契带来的战略意义。人物快速移动和瞄准、开枪的打击感洋溢着快节奏FPS游戏的趣味。特别是通过确认玩家的出生点和交战地带后计算最佳路线来不断挖掘地图,并从中得到乐趣。下面小编将使用雷柏V210的强大驱动宏定义,让你也能玩转幽灵模式。FPS游戏最注重的就是鼠标的精准度,雷柏V210采用了安华高A3050光学引擎,支持最高3000DPI的分辨率,玩家可以通过驱动在500~3000DPI之间任选三档DPI值。小编将鼠标的分辨率调节为个人习惯的500DPI,鼠标移动平稳,瞄准时稳定精准,没有丢帧、发飘现象。当然,每个人的打法和习惯不同,要找到自己鼠标在CF里灵敏度的值,这样玩起来就顺畅许多。什么是鬼跳?幽灵模式是《穿越火线》中最特殊的模式,所谓鬼跳,就是在穿越火线游戏中幽灵模式下选择幽灵时的一种让保卫者看不见你的行动轨迹,只能听见你呼吸声的一种跳跃方法。对于幽灵一方来说,"鬼跳"几乎是一门必须掌握的基础课,它可以让你在移动的时候不发出声音使敌人无法察觉,从而迅速的消灭目标。而什么是宏设置,简单的说,就是你完成一个鬼步,要先蹲着一直不松,按一下s键,然后起跳并松开s,当跳在空中时再按s不松,然后如此重复…这个办法看似简单但是实际操作起来很考验个人手速,对于"手残党"玩家,估计随时会要了亲命。而宏定义要做的就是提高你的战斗力,轻轻松松可以消灭目标。雷柏V210驱动宏编辑中没有CF的相关设置,但是玩家可以通过宏编辑新建招式,成为合格狙击手不再是梦。我们以"一键鬼跳"为例,设置一个宏命令。首先我们在"玩家自定义"下新建一个宏命令------"一键鬼跳"。将"一键鬼跳"的一系列操作进行录制。点击开始录制,选择"录制鼠标按键",开始一些列操作"按下空格→弹起空格→按下空格→弹起空格→按下ctrl→弹起ctrl"。接下来对录制内容进行编辑,选择需要修改的事件,点击修改,在编辑处开始编辑,这里小编设置的事件是1:修改按下Space的延迟时间100ms;2:修改弹起Space的延迟时间529ms;3:修改按下Space的延迟时间200ms;4:修改弹起Space的延迟时间100ms。5:修改按下ctrl键的延迟时间为400秒。设置好一键鬼跳一系列动作之后,回到主要设置页面,点击任何一个可以编程的按键,雷柏V210一共具有7键可编,以左键为例,在设置页面,点击宏编辑,选择刚才设置好的"一键鬼跳"命令,点击"确定"后,点击"OK"进行应用,即可使用。设置完成后,就可以开启你的CF之旅了,解放柔弱的小拇指,只要经过合理的设置,雷柏V210也能成为一款可以让你弹无虚发的FPS利器!在幽灵模式下行云流水一般流畅自如的利用鬼跳靠近敌人秒杀。老牌实力大厂,国产外设领军品牌雷柏(RAPOO)近期发布的这款电竞级光学游戏鼠标,拥有1600万色的智能感应功能,手一靠近,就能开启灯光之旅。是要智能光谱循环,APM呼吸循环,呼吸模式,又或是灯光常亮,还是就想它当一个本色鼠标,也可以选择关闭灯光。一键设置,任你喜欢。搭载2000万次欧姆龙微动开光以及A3050游戏光学引擎,保证点击的清脆;板载内存、编织线材、镀金USB接口、特氟龙材质脚垫,优秀的工业设计与表面材质保证了长时间游戏的舒适度。市场售价169元,一定会成为你的首选游戏利器,给你无与伦比的游戏操作体验。  雷柏VPRO系列:游戏梦想制造家天猫雷柏旗舰店:https://rapoo.tmall.com/京东雷柏旗舰店:http://vpro.jd.com/
点击查看更多内容
热门手机应用罗技G300和微软IE3.0哪个比较好,打cf好啊? 我纠结死了_百度知道
罗技G300和微软IE3.0哪个比较好,打cf好啊? 我纠结死了
描述他们的优缺点 要细致
能不能细致点
我有更好的答案
秒 原版有6000帧/秒,在FPS游戏快速移动中绝对不会丢帧缺点是鼠标DPI低只有450,不过FPS游戏足够,而且有点过时了G300优点是按键多,但在FPS游戏里太鸡肋,几乎没用无明显缺点,但FPS游戏用这个鼠标实在浪费钱IE3.0比G300大,IE3.0是人体工学打FPS游戏选IE3,复刻版有9000帧&#47,G300是对称人体工学打FPS游戏的话这两款都不推荐,这个价位再加点还是炼狱蝰蛇性价比更高.0.0是以前的殿堂级CS鼠标优点是定位精准,IE3
采纳率:49%
罗技是专业的。不过玩cf的话,建议你买个雷柏吧。我就用雷柏的。
IE比300稳,但是在平时屏幕移动的时候IE不能调节DPI所以用着会不爽,300可两用
楼主建议你用IE3.0的鼠标,这款鼠标稳定性极高,是CF.CS的神器阿!
还有,复刻版的和正品银光鲨用起来是一样的,但价格上复刻版的会便宜一百来块钱!建议复刻版的就可以了!如果你钱多的话那我没话说!
其他1条回答
为您推荐:
其他类似问题
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。电脑附近没有接线盒怎样才能玩cf_百度知道
电脑附近没有接线盒怎样才能玩cf
您的回答被采纳后将获得:
系统奖励15(财富值+成长值)+难题奖励30(财富值+成长值)
我有更好的答案
对图像显示效果和视觉感观产生不好的影响,高级,监视器,屏幕刷新率调到75以上,这里要说的是很多玩CS的朋友甚至把屏幕刷新率搞到了200。  不过即使不下DX10显卡驱动,经过上面的5步,打5V5也应该不成问题了:右键“我的电脑”,属性?有没有遇到过准心回缩较慢的情况,下面几个简单有效的方法大家可以试试,  玩游戏,游戏里的每一帧就是一幅静止画面,对方却没掉血的情况,每秒填充的帧数就越多,那么画面就越流畅,配置比较低的电脑甚至可以考虑用16位色,有没有遇到过画面一卡一卡的现象,而“FPS”值越高也就是“刷新率”越高。“FramesPerSecond”在计算机图像范畴内被翻译为:“每秒传输帧数” 很高兴为你回答问题。当显卡能提供的“FPS”值不足以满足游戏的“FPS”时玩家就会感觉丢帧,都会注意到“刷新率”。一般我们设置缺省刷新率都在75Hz(即75帧&#47,其实适当的调整下自己的电脑对你水平的发挥是有很大帮助的,当然也许会遇到FPS不稳定的情况,要解决这种情况,就去下个支持XP系统的DX10的显卡驱动吧,玩3D类游戏,尤其是3D竞技类游戏,技术固然关键,决定这一切的就是FPS。所以在CS。更确切的解释,就是“每秒中填充图像的帧数(帧/秒)“。这里的“FPS”就是我们常在CS,不连贯,人的肉眼已经分辨不出来画面的流畅度区别了。  另外?有没有遇到过明明打到人、CF这样的第一视角射击类游戏,“FPS”值的高低对游戏的画面,乃至游戏效果都有至关重要的影响!  OK,进入正题,如何提高自己在游戏中的FPS呢(NB配置的电脑除外),这里就不多说了,其实没有必要,因为屏幕刷新率75以上时,我们都力求达到最好的游戏画面和最好的游戏效果。那么配置强的机器就不用发愁了:  第一:将桌面的背景图片(壁纸)取消掉,因为他会很大程度的影响图像刷新率,具体电脑显示器具体分析。  第二:将电脑的分辨率适当调小些、CF中,经过上面5步后,但如果没有硬件配置的支持,那水平将大打折扣,没有那种驱动普遍都会出现FPS不稳定的情况,因为稍有不慎会降低显卡寿命:桌面属性,设置,配置弱的机器就需要调整各种画面参数来优化FPS值。所以对于CS,即75帧/秒。而当刷新率太低时我们肉眼都能感觉到屏幕的闪烁,到时大家就要找我来赔显卡了。在FPS游戏例如CS、CF中也是一样的。  第三:强行关闭显卡的垂直同步,这是必要的。  第四,桌面的文件越少越好,也就是画面不连贯,以至影响游戏操作结果、CF游戏里说的“FPS”值,能有效的提高自己游戏中的FPS,选择“最佳性能”。  第五;秒)以上(XP锁定在60Hz),看看你的FPS提高了多少,玩起来应该很爽了,至于更深层的关于调整显卡选项来提高FPS的,也可以理解为我们常说的“刷新率(Hz)”。我们在装机选购显卡和显示器的时候。例如:75Hz的刷新率刷也就是指屏幕一秒内只扫描75次?等等诸如此类的问题,高级,性能,玩游戏前问下自己,是不是已经将自己的电脑调制好了呢?  很多朋友都是上手就进游戏,对电脑的调试毫不在意,什么是FPS?稍微专业点的玩家都应该知道,但我还是再解释一下,方便新人吧!  在计算机图像领域中,“FPS”是词组“FramesPerSecond”的缩写,OK,进游戏吧
为您推荐:
其他类似问题
接线盒的相关知识
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。&figure&&img src=&https://pic1.zhimg.com/v2-f2cc7dbeebce20225ff92f_b.jpg& data-rawwidth=&730& data-rawheight=&300& class=&origin_image zh-lightbox-thumb& width=&730& data-original=&https://pic1.zhimg.com/v2-f2cc7dbeebce20225ff92f_r.jpg&&&/figure&&p&&!--假装此处有一个段子作为引子--&&/p&&h2&TL;DR&/h2&&p&1. chrome devtool 是诊断页面滚动性能的有效工具&/p&&p&2. 提升滚动时性能,就是要达到fps高且稳。&/p&&p&3. 具体可以从以下方面着手&/p&&ul&&li&使用web worker分离无页面渲染无关的逻辑计算&/li&&li&触发监听事件时使用函数节流与函数去抖&/li&&li&使用requestAnimationFrame与requestIdleCallback代替定时器&/li&&li&避免强制重排&/li&&li&提升合成层&/li&&/ul&&hr&&h2&场景&/h2&&p&滚动行为无时无刻不出现在我们浏览网页的行为中,在许多场景中,我们有有意识地、主动地去使用滚动操作,比如:&/p&&ul&&li&懒加载&/li&&li&loadmore&/li&&li&affix&/li&&li&回到顶部&/li&&/ul&&p&以上场景伴随着滚动事件的监听操作,一不留神可能就让页面的滚动不再“如丝般顺滑”。&/p&&p&&i&不择手段打造一个卡顿的scroll场景:&/i&&/p&&p&&br&&/p&&figure&&img src=&http://pic1.zhimg.com/v2-ffa983bbbfa192f73107a8c_b.jpg& class=&content_image&&&/figure&&figure&&img src=&http://pic3.zhimg.com/v2-d25945cbfd8c95f3db11d5e6a5ff347e_b.jpg& class=&content_image&&&/figure&&p&&br&&/p&&p&作为一名优秀的前端工程师(未来的),怎么能容许出现这种情况!不就性能优化吗,撩起袖子就是干!&/p&&hr&&h2&原理&/h2&&p&在一个流畅的页面变化效果中(动画或滚动),&b&渲染帧&/b&,指的是浏览器从js执行到paint的一次绘制过程,帧与帧之间快速地切换,由于人眼的残像错觉,就形成了动画的效果。那么这个“快速”,要达到多少才合适呢?&/p&&p&我们都知道,下层建筑决定了上层建筑。受限于目前大多数屏幕的刷新频率——&b&60次/s&/b&,浏览器的渲染更新的页面的&b&标准帧率&/b&也为&b&60次/s&/b&--&b&60FPS&/b&(frames/per second)。&/p&&ul&&li&高于这个数字,在一次屏幕刷新的时间间隔&b&16.7ms&/b&(1/60)内,就算浏览器渲染了多次页面,屏幕也只刷新一次,这就造成了性能的浪费。&/li&&li&低于这个数字,帧率下降,人眼就可能捕捉到两帧之间变化的滞涩与突兀,表现在屏幕上,就是页面的抖动,大家通常称之为&b&卡顿&/b&&/li&&/ul&&p&来个比喻。快递每天整理包裹,并一天一送。如果某天包裹太多,整理花费了太多时间,来不及当日(帧)送到收件人处,那就延期了(丢帧)。&/p&&p&那么在这16.7ms之内,浏览器都干了什么呢?&/p&&p&浏览器内心OS:不要老抱怨我延期(丢帧),我也很忙的好伐?&/p&&p&&br&&/p&&p&&b&帧维度解释帧渲染过程&/b&&/p&&p&浏览器渲染页面的&b&Renderer&/b&进程里,涉及到了两个线程,二者之间通过名为Commit的消息保持同步:&/p&&ul&&li&Main线程:浏览器渲染的主要执行步骤,包含从JS执行到Composite合成的一系列操作(下文会介绍)&/li&&li&Compositor线程:接收用户的一些交互操作(比如滚动) =& 唤起Main线程进行操作 =& 接收Main线程的操作结果 =& commit给真正把页面draw到屏幕上的GPU进程&/li&&/ul&&p&&b&标准渲染帧:&/b&&/p&&figure&&img src=&http://pic3.zhimg.com/v2-e893a683add1fe8e77e6e6d_b.jpg& class=&content_image&&&/figure&&p&在一个标准帧渲染时间16.7ms之内,浏览器需要完成Main线程的操作,并commit给Compositor进程&/p&&p&&b&丢帧:&/b&&/p&&figure&&img src=&http://pic2.zhimg.com/v2-70a86a3d3bd195b08a5179_b.jpg& class=&content_image&&&/figure&&p&主线程里操作太多,耗时长,commit的时间被推迟,浏览器来不及将页面draw到屏幕,这就丢失了一帧&/p&&p&那么Main线程里都有些什么操作会导致延时呢?&/p&&p&&br&&/p&&p&&b&进一步解释浏览器主要执行步骤&/b&&/p&&figure&&img src=&http://pic4.zhimg.com/v2-ef008fd1bf3_b.jpg& data-caption=&& data-rawwidth=&1093& data-rawheight=&167& class=&origin_image zh-lightbox-thumb& width=&1093& data-original=&http://pic4.zhimg.com/v2-ef008fd1bf3_r.jpg&&&/figure&&ul&&li&JavaScript:包含与视觉变化效果相关的&b&js操作&/b&。包括并不限于:dom更新、元素样式动态改变、jQuery的animate函数等。&/li&&li&Style:样式计算。这个过程,浏览器根据css选择器计算哪些元素应该应用哪些规则,然后将样式规则落实到每个元素上去,确定每个元素具体的样式。&/li&&li&Layout:布局。在知道对一个元素应用哪些规则之后,浏览器即可开始计算它要占据的空间大小及其在屏幕的位置。&/li&&li&Painting:绘制。绘制是填充像素的过程。它涉及绘出文本、颜色、图像、边框和阴影,基本上包括元素的每个可视部分。绘制一般是在多个表面(通常称为层)上完成的。(paint和draw的区别:paint是把内容填充到页面,而draw是把页面反映到屏幕上)&/li&&li&Composite:合成。由于页面的各部分可能被绘制到多层,由此它们需要按正确顺序绘制到屏幕上,以便正确渲染页面。对于与另一元素重叠的元素来说,这点特别重要,因为一个错误可能使一个元素错误地出现在另一个元素的上层。&/li&&/ul&&p&理论上,每次标准的渲染,浏览器Main线程需要执行JavaScript =& Style =& Layout =& Paint =& Composite五个步骤,但是实际上,要分场景。&/p&&figure&&img src=&http://pic4.zhimg.com/v2-7e3dda9991548cdc4738bf_b.jpg& data-caption=&& data-rawwidth=&878& data-rawheight=&418& class=&origin_image zh-lightbox-thumb& width=&878& data-original=&http://pic4.zhimg.com/v2-7e3dda9991548cdc4738bf_r.jpg&&&/figure&&p&&b&指路&a href=&http://link.zhihu.com/?target=https%3A//developers.google.com/web/fundamentals/performance/rendering/%3Fhl%3Dzh-cn& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&官网&/a&&/b&&/p&&p&&br&&/p&&p&&b&再进一步解释浏览器渲染流程&/b&&/p&&figure&&img src=&http://pic3.zhimg.com/v2-dc215f24f675d36e32fd052f56191b4a_b.jpg& class=&content_image&&&/figure&&p&&br&&/p&&p&流程:&/p&&p&1.Compositor线程接收一个vsync信号,表示这一帧开始&/p&&p&2.Compositor线程接收用户的交互输入(比如touchmove、scroll、click等)。然后commit给Main线程,这里有两点规则需要注意:&/p&&ul&&li&并不是所有event都会commit给Main线程,部分操作比如单纯的滚动事件,打字等输入,不需要执行JS,也没有需要重绘的场景,Compositor线程就自己处理了,无需请求Main线程&/li&&li&同样的事件类型,不论一帧内被Compositor线程接收多少次,实际上commit给Main线程的,只会是一次,意味着也只会被执行一次。(HTML5标准里scroll事件是每帧触发一次)&/li&&/ul&&p&3.Main线程执行从JavaScript到Composite的过程,也有两点需要注意:&/p&&ul&&li&注意红线,意思是可能会在JS里强制重排,当访问scrollWidth系列、clientHeight系列、offsetTop系列、ComputedStyle等属性时,会触发这个效果,导致Style和Layout前移到JS代码执行过程中。&/li&&li&实际上图中省略了Renderer进程中的其他线程,比如当Main线程走到js执行这一步时,会调起单独的js线程来执行。另外还有如HTML解释线程等。&/li&&/ul&&p&4.当Main线程完成最后合成之后,与Compositor线程使用commit进行通信,Compositor调起Compositor Tile Work(s)来辅助处理页面。Rasterize意为光栅化,想深入了解什么是光栅的小伙伴可以戳这里了解:&a href=&http://link.zhihu.com/?target=https%3A//chuckliu.me/%23%21/posts/58ea6af15dc74& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&浏览器渲染详细过程:重绘、重排和composite只是冰山一角&/a&&/p&&p&5.页面paint结束之后,这一帧就结束了。GPU进程里的GPU线程负责把Renderer进程操作好的页面,交由GPU,调用GPU内方法,由GPU把页面draw到屏幕上。&/p&&p&6.屏幕刷新,我们就在浏览器(屏幕)上看到了新页面。&/p&&p&接下来,简要介绍一下,如何使用chrome devtool分析页面性能。&/p&&p&示意图(&i&chrome version: 61&/i&):&/p&&figure&&img src=&http://pic2.zhimg.com/v2-af364bda782aabe862c89_b.jpg& class=&content_image&&&/figure&&ul&&li&帧率概览。看顶端绿色长条,越高代表帧率越高,高低起伏多代表帧率变化不稳定,越坑坑洼洼代表容易产生视觉上的卡顿。&/li&&li&分析具体某一帧。如果发现,有哪一帧帧率特别低,可以在中间那一栏找到耗时长的那一帧,点击进行具体的活动分析。&/li&&li&分析个活动耗时。自由选择某一段或某一帧观察这段时间内各项活动的耗时来诊断页面。(注意颜色)&/li&&/ul&&p&应该注意,我们可以看见,很少有帧的时间准确卡在了16.7s,实际上每帧达到60fps的帧率,只是一个理想化的数字,浏览器执行过程中可能受到各种情况的干扰。而我们人眼也没有那么灵敏,只要达到20帧以上,页面看起来就比较流畅了。尤其是结构复杂,数据较多的页面,盲目追求60fps只是钻牛角尖。所以,以我浅见,稳定的fps更能影响scroll效果。&/p&&p&关于&b&更加具体地&/b&如何使用chome devtool分析页面性能,戳:&a href=&http://link.zhihu.com/?target=https%3A//developers.google.com/web/tools/chrome-devtools/evaluate-performance/reference& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Performance Analysis Reference&/a&&/p&&hr&&h2&解决方案&/h2&&p&我们的目标很明确,就是拒绝卡顿!具体说来就是尽量赶在16.7ms之内让浏览器完成五项工作,压缩每个步骤时间。&/p&&p&&b&使用web worker&/b&&/p&&p&当我们了解了浏览器渲染时执行的过程,并且清楚浏览器内核处理方式(处理js的线程与GUI页面渲染线程互斥)之后,我们很容易假想出这样一种状况:如果js大量的计算和逻辑操作霸占着浏览器,使页面渲染得不到处理,怎么办?&/p&&p&这种情况,很容易造成scroll的卡顿,甚至浏览器假死,就像alert()出现一样。&/p&&p&想象一下吧,本来大家好好地按照生理周期一个接一个上厕所,突然小j便秘了!你说排在他后面的小g急不急,可急死了!&/p&&p&web worker是什么?&/p&&blockquote&Web Worker为Web内容在后台线程中运行脚本提供了一种简单的方法。线程可以执行任务而不干扰用户界面。&/blockquote&&p&这就好像,给容易“便秘”的小j,单独搭了个简易厕所。&/p&&p&之所以说这是一个简易厕所,因为它有一些限制&/p&&ul&&li&无法访问DOM节点&/li&&li&无法访问全局变量或是全局函数&/li&&li&无法调用alert()或者confirm之类的函数&/li&&li&无法访问window、document之类的浏览器全局变量&/li&&/ul&&blockquote&主线程和 worker 线程之间通过这样的方式互相传输信息:两端都使用 postMessage() 方法来发送信息, 并且通过 onmessage 这个 event handler来接收信息。 (传递的信息包含在 Message 这个事件的数据属性内) 。数据的交互是通过传递副本,而不是直接共享数据。&/blockquote&&p&&b&使用案例 - 判断素数&/b&&/p&&p&案例来自&a href=&http://link.zhihu.com/?target=https%3A//dzone.com/articles/web-workers-responsive& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Web Workers, for a responsive JavaScript application&/a&&/p&&blockquote&素数,定义为在大于1的自然数中,除了1和它本身以外不再有其他因数。判断算法为,以2到它的平方根为界取整数做循环判断,用它和这个数字求余数,只要中间任意一次计算得到余数为零,则能够确认这个数字不是质数。&/blockquote&&p&&b&code&/b&&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&c1&&// in html&/span&
&span class=&o&&&&/span&&span class=&nx&&script&/span& &span class=&nx&&type&/span&&span class=&o&&=&/span&&span class=&s2&&&text/javascript&&/span&&span class=&o&&&&/span&
&span class=&c1&&// we will use this function in-line in this page&/span&
&span class=&kd&&function&/span& &span class=&nx&&isPrime&/span&&span class=&p&&(&/span&&span class=&nx&&number&/span&&span class=&p&&)&/span&
&span class=&p&&{&/span&
&span class=&k&&if&/span& &span class=&p&&(&/span&&span class=&nx&&number&/span& &span class=&o&&===&/span& &span class=&mi&&0&/span& &span class=&o&&||&/span& &span class=&nx&&number&/span& &span class=&o&&===&/span& &span class=&mi&&1&/span&&span class=&p&&)&/span& &span class=&p&&{&/span&
&span class=&k&&return&/span& &span class=&kc&&true&/span&&span class=&p&&;&/span&
&span class=&p&&}&/span&
&span class=&kd&&var&/span& &span class=&nx&&i&/span&&span class=&p&&;&/span&
&span class=&k&&for&/span& &span class=&p&&(&/span&&span class=&nx&&i&/span& &span class=&o&&=&/span& &span class=&mi&&2&/span&&span class=&p&&;&/span& &span class=&nx&&i&/span& &span class=&o&&&=&/span& &span class=&nb&&Math&/span&&span class=&p&&.&/span&&span class=&nx&&sqrt&/span&&span class=&p&&(&/span&&span class=&nx&&number&/span&&span class=&p&&);&/span& &span class=&nx&&i&/span&&span class=&o&&++&/span&&span class=&p&&)&/span& &span class=&p&&{&/span&
&span class=&k&&if&/span& &span class=&p&&(&/span&&span class=&nx&&number&/span& &span class=&o&&%&/span& &span class=&nx&&i&/span& &span class=&o&&===&/span& &span class=&mi&&0&/span&&span class=&p&&)&/span& &span class=&p&&{&/span&
&span class=&k&&return&/span& &span class=&kc&&false&/span&&span class=&p&&;&/span&
&span class=&p&&}&/span&
&span class=&p&&}&/span&
&span class=&k&&return&/span& &span class=&kc&&true&/span&&span class=&p&&;&/span&
&span class=&p&&}&/span&
&span class=&c1&&// a large number, so that the computation time is sensible&/span&
&span class=&kd&&var&/span& &span class=&nx&&number&/span& &span class=&o&&=&/span& &span class=&s2&&&1111&&/span&&span class=&p&&;&/span&
&span class=&c1&&// including the worker's code&/span&
&span class=&kd&&var&/span& &span class=&nx&&w&/span& &span class=&o&&=&/span& &span class=&k&&new&/span& &span class=&nx&&Worker&/span&&span class=&p&&(&/span&&span class=&s1&&'webworkers.js'&/span&&span class=&p&&);&/span&
&span class=&c1&&// the callback for the worker to call&/span&
&span class=&nx&&w&/span&&span class=&p&&.&/span&&span class=&nx&&onmessage&/span& &span class=&o&&=&/span& &span class=&kd&&function&/span&&span class=&p&&(&/span&&span class=&nx&&e&/span&&span class=&p&&)&/span& &span class=&p&&{&/span&
&span class=&k&&if&/span& &span class=&p&&(&/span&&span class=&nx&&e&/span&&span class=&p&&.&/span&&span class=&nx&&data&/span&&span class=&p&&)&/span& &span class=&p&&{&/span&
&span class=&nx&&alert&/span&&span class=&p&&(&/span&&span class=&nx&&number&/span& &span class=&o&&+&/span& &span class=&s1&&' is prime. Now I\'ll try calculating without a web worker.'&/span&&span class=&p&&);&/span&
&span class=&kd&&var&/span& &span class=&nx&&result&/span& &span class=&o&&=&/span& &span class=&nx&&isPrime&/span&&span class=&p&&(&/span&&span class=&nx&&number&/span&&span class=&p&&);&/span&
&span class=&k&&if&/span& &span class=&p&&(&/span&&span class=&nx&&result&/span&&span class=&p&&)&/span& &span class=&p&&{&/span&
&span class=&nx&&alert&/span&&span class=&p&&(&/span&&span class=&s1&&'I am sure, it is prime. '&/span&&span class=&p&&);&/span&
&span class=&p&&}&/span&
&span class=&p&&}&/span& &span class=&k&&else&/span& &span class=&p&&{&/span&
&span class=&nx&&alert&/span&&span class=&p&&(&/span&&span class=&nx&&number&/span& &span class=&o&&+&/span& &span class=&s1&&' is not prime.'&/span&&span class=&p&&);&/span&
&span class=&p&&}&/span&
&span class=&p&&};&/span&
&span class=&c1&&// sending a message to the worker in order to start it&/span&
&span class=&nx&&w&/span&&span class=&p&&.&/span&&span class=&nx&&postMessage&/span&&span class=&p&&(&/span&&span class=&nx&&number&/span&&span class=&p&&);&/span&
&span class=&o&&&&/span&&span class=&err&&/script&&/span&
&span class=&o&&&&/span&&span class=&nx&&p&/span& &span class=&nx&&style&/span&&span class=&o&&=&/span&&span class=&s2&&&height: 200 width: 400 overflow:&&/span&&span class=&o&&&&/span&
&span class=&nx&&Lorem&/span& &span class=&nx&&ipsum&/span& &span class=&nx&&dolor&/span& &span class=&nx&&sit&/span& &span class=&nx&&amet&/span&&span class=&p&&,&/span& &span class=&nx&&consectetur&/span& &span class=&nx&&adipiscing&/span& &span class=&nx&&elit&/span&&span class=&p&&.&/span& &span class=&nx&&Fusce&/span& &span class=&nx&&blandit&/span& &span class=&nx&&tristique&/span& &span class=&nx&&risus&/span&&span class=&p&&,&/span& &span class=&nx&&a&/span& &span class=&nx&&rhoncus&/span& &span class=&nx&&nisl&/span& &span class=&nx&&posuere&/span& &span class=&nx&&sed&/span&&span class=&p&&.&/span& &span class=&nx&&Praesent&/span& &span class=&nx&&vel&/span& &span class=&nx&&risus&/span& &span class=&nx&&turpis&/span&&span class=&p&&,&/span& &span class=&nx&&et&/span& &span class=&nx&&fermentum&/span& &span class=&nx&&lectus&/span&&span class=&p&&.&/span& &span class=&nx&&Ut&/span& &span class=&nx&&lacinia&/span& &span class=&nx&&nunc&/span& &span class=&nx&&dui&/span&&span class=&p&&.&/span& &span class=&nx&&Sed&/span& &span class=&nx&&a&/span& &span class=&nx&&velit&/span& &span class=&nx&&orci&/span&&span class=&p&&.&/span& &span class=&nx&&Maecenas&/span& &span class=&nx&&quis&/span& &span class=&nx&&diam&/span& &span class=&nx&&neque&/span&&span class=&p&&.&/span& &span class=&nx&&Vestibulum&/span& &span class=&nx&&id&/span& &span class=&nx&&arcu&/span& &span class=&nx&&purus&/span&&span class=&p&&,&/span& &span class=&nx&&quis&/span& &span class=&nx&&cursus&/span& &span class=&nx&&arcu&/span&&span class=&p&&.&/span& &span class=&nx&&Etiam&/span& &span class=&nx&&luctus&/span&&span class=&p&&,&/span& &span class=&nx&&risus&/span& &span class=&nx&&eu&/span& &span class=&nx&&scelerisque&/span& &span class=&nx&&scelerisque&/span&&span class=&p&&,&/span& &span class=&nx&&sapien&/span& &span class=&nx&&felis&/span& &span class=&nx&&tincidunt&/span& &span class=&nx&&ante&/span&&span class=&p&&,&/span& &span class=&nx&&vel&/span& &span class=&nx&&pellentesque&/span& &span class=&nx&&eros&/span& &span class=&nx&&nunc&/span& &span class=&nx&&at&/span& &span class=&nx&&magna&/span&&span class=&p&&.&/span& &span class=&nx&&Nam&/span& &span class=&nx&&tincidunt&/span& &span class=&nx&&mattis&/span& &span class=&nx&&velit&/span& &span class=&nx&&ut&/span& &span class=&nx&&condimentum&/span&&span class=&p&&.&/span& &span class=&nx&&Vivamus&/span& &span class=&nx&&ipsum&/span& &span class=&nx&&ipsum&/span&&span class=&p&&,&/span& &span class=&nx&&venenatis&/span& &span class=&nx&&vitae&/span& &span class=&nx&&placerat&/span& &span class=&nx&&eu&/span&&span class=&p&&,&/span& &span class=&nx&&convallis&/span& &span class=&nx&&quis&/span& &span class=&nx&&metus&/span&&span class=&p&&.&/span& &span class=&nx&&Quisque&/span& &span class=&nx&&tortor&/span& &span class=&nx&&sapien&/span&&span class=&p&&,&/span& &span class=&nx&&dapibus&/span& &span class=&nx&&non&/span& &span class=&nx&&vehicula&/span& &span class=&nx&&quis&/span&&span class=&p&&,&/span& &span class=&nx&&dapibus&/span& &span class=&nx&&at&/span& &span class=&nx&&purus&/span&&span class=&p&&.&/span& &span class=&nx&&Nunc&/span& &span class=&nx&&posuere&/span&&span class=&p&&,&/span& &span class=&nx&&ligula&/span& &span class=&nx&&sed&/span& &span class=&nx&&facilisis&/span& &span class=&nx&&sagittis&/span&&span class=&p&&,&/span& &span class=&nx&&justo&/span& &span class=&nx&&massa&/span& &span class=&nx&&placerat&/span& &span class=&nx&&nulla&/span&&span class=&p&&,&/span& &span class=&nx&&nec&/span& &span class=&nx&&pellentesque&/span& &span class=&nx&&libero&/span& &span class=&nx&&erat&/span& &span class=&nx&&ut&/span& &span class=&nx&&ligula&/span&&span class=&p&&.&/span& &span class=&nx&&Aenean&/span& &span class=&nx&&molestie&/span&&span class=&p&&,&/span& &span class=&nx&&urna&/span& &span class=&nx&&quis&/span& &span class=&nx&&molestie&/span& &span class=&nx&&auctor&/span&&span class=&p&&,&/span& &span class=&nx&&lorem&/span& &span class=&nx&&purus&/span& &span class=&nx&&hendrerit&/span& &span class=&nx&&nisi&/span&&span class=&p&&,&/span& &span class=&nx&&vitae&/span& &span class=&nx&&tincidunt&/span& &span class=&nx&&metus&/span& &span class=&nx&&massa&/span& &span class=&nx&&et&/span& &span class=&nx&&dolor&/span&&span class=&p&&.&/span& &span class=&nx&&Sed&/span& &span class=&nx&&leo&/span& &span class=&nx&&velit&/span&&span class=&p&&,&/span& &span class=&nx&&iaculis&/span& &span class=&nx&&tristique&/span& &span class=&nx&&elementum&/span& &span class=&nx&&tincidunt&/span&&span class=&p&&,&/span& &span class=&nx&&ornare&/span& &span class=&nx&&et&/span& &span class=&nx&&tellus&/span&&span class=&p&&.&/span& &span class=&nx&&Quisque&/span& &span class=&nx&&lacinia&/span& &span class=&nx&&felis&/span& &span class=&nx&&at&/span& &span class=&nx&&est&/span& &span class=&nx&&faucibus&/span& &span class=&k&&in&/span& &span class=&nx&&facilisis&/span& &span class=&nx&&dui&/span& &span class=&nx&&consectetur&/span&&span class=&p&&.&/span& &span class=&nx&&Phasellus&/span& &span class=&nx&&sed&/span& &span class=&nx&&ante&/span& &span class=&nx&&id&/span& &span class=&nx&&tortor&/span& &span class=&nx&&pretium&/span& &span class=&nx&&ornare&/span&&span class=&p&&.&/span& &span class=&nx&&Aliquam&/span& &span class=&nx&&ante&/span& &span class=&nx&&justo&/span&&span class=&p&&,&/span& &span class=&nx&&aliquam&/span& &span class=&nx&&ut&/span& &span class=&nx&&mollis&/span& &span class=&nx&&semper&/span&&span class=&p&&,&/span& &span class=&nx&&mattis&/span& &span class=&nx&&sit&/span& &span class=&nx&&amet&/span& &span class=&nx&&urna&/span&&span class=&p&&.&/span& &span class=&nx&&Pellentesque&/span& &span class=&nx&&placerat&/span&&span class=&p&&,&/span& &span class=&nx&&diam&/span& &span class=&nx&&nec&/span& &span class=&nx&&consectetur&/span& &span class=&nx&&blandit&/span&&span class=&p&&,&/span& &span class=&nx&&libero&/span& &span class=&nx&&metus&/span& &span class=&nx&&placerat&/span& &span class=&nx&&massa&/span&&span class=&p&&,&/span& &span class=&nx&&quis&/span& &span class=&nx&&mattis&/span& &span class=&nx&&metus&/span& &span class=&nx&&metus&/span& &span class=&nx&&nec&/span& &span class=&nx&&lorem&/span&&span class=&p&&.&/span&
&span class=&o&&&&/span&&span class=&err&&/p&&/span&
&span class=&c1&&// in webworkers.js&/span&
&span class=&kd&&function&/span& &span class=&nx&&isPrime&/span&&span class=&p&&(&/span&&span class=&nx&&number&/span&&span class=&p&&)&/span&
&span class=&p&&{&/span&
&span class=&k&&if&/span& &span class=&p&&(&/span&&span class=&nx&&number&/span& &span class=&o&&===&/span& &span class=&mi&&0&/span& &span class=&o&&||&/span& &span class=&nx&&number&/span& &span class=&o&&===&/span& &span class=&mi&&1&/span&&span class=&p&&)&/span& &span class=&p&&{&/span&
&span class=&k&&return&/span& &span class=&kc&&true&/span&&span class=&p&&;&/span&
&span class=&p&&}&/span&
&span class=&kd&&var&/span& &span class=&nx&&i&/span&&span class=&p&&;&/span&
&span class=&k&&for&/span& &span class=&p&&(&/span&&span class=&nx&&i&/span& &span class=&o&&=&/span& &span class=&mi&&2&/span&&span class=&p&&;&/span& &span class=&nx&&i&/span& &span class=&o&&&=&/span& &span class=&nb&&Math&/span&&span class=&p&&.&/span&&span class=&nx&&sqrt&/span&&span class=&p&&(&/span&&span class=&nx&&number&/span&&span class=&p&&);&/span& &span class=&nx&&i&/span&&span class=&o&&++&/span&&span class=&p&&)&/span& &span class=&p&&{&/span&
&span class=&k&&if&/span& &span class=&p&&(&/span&&span class=&nx&&number&/span& &span class=&o&&%&/span& &span class=&nx&&i&/span& &span class=&o&&===&/span& &span class=&mi&&0&/span&&span class=&p&&)&/span& &span class=&p&&{&/span&
&span class=&k&&return&/span& &span class=&kc&&false&/span&&span class=&p&&;&/span&
&span class=&p&&}&/span&
&span class=&p&&}&/span&
&span class=&k&&return&/span& &span class=&kc&&true&/span&&span class=&p&&;&/span&
&span class=&p&&}&/span&
&span class=&c1&&// this is the point of entry for the workers&/span&
&span class=&nx&&onmessage&/span& &span class=&o&&=&/span& &span class=&kd&&function&/span&&span class=&p&&(&/span&&span class=&nx&&e&/span&&span class=&p&&)&/span& &span class=&p&&{&/span&
&span class=&c1&&// you can support different messages by checking the e.data value&/span&
&span class=&nx&&number&/span& &span class=&o&&=&/span& &span class=&nx&&e&/span&&span class=&p&&.&/span&&span class=&nx&&data&/span&&span class=&p&&;&/span&
&span class=&nx&&result&/span& &span class=&o&&=&/span& &span class=&nx&&isPrime&/span&&span class=&p&&(&/span&&span class=&nx&&number&/span&&span class=&p&&);&/span&
&span class=&c1&&// calling back the main thread&/span&
&span class=&nx&&postMessage&/span&&span class=&p&&(&/span&&span class=&nx&&result&/span&&span class=&p&&);&/span&
&span class=&p&&};&/span&
&/code&&/pre&&/div&&p&代码说明:&/p&&ul&&li&使用web worker对一个较大数字(1111)进行素数判断&/li&&li&得到结果之后alert(number + ' is prime. Now I'll try calculating without a web worker.')&/li&&li&在不使用web worker的情况下,对相同数字进行素数判断,完成后alert('I am sure, it is prime. ')&/li&&li&从页面标签里的内容的滚动情况判断两次计算对浏览器/页面造成的影响&/li&&/ul&&p&现场还原:&/p&&figure&&img src=&https://pic2.zhimg.com/v2-4d2a65d13d3ea6ac043073_b.jpg& data-thumbnail=&http://pic4.zhimg.com/v2-4d2a65d13d3ea6ac043073_b.jpg& class=&content_image&&&/figure&&p&&a href=&http://link.zhihu.com/?target=http%3A//7xw3pf.com1.z0.glb.clouddn.com/scroll-performance_15-56-48.gif& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&不动戳我&/a&&/p&&p&&b&案例总结&/b&:&br&从两次alert之后的段落滚动情况(第二次根本动不了),足以看出大量繁杂的js计算对页面的影响。恰当地使用web worker,&b&能有效缓解页面scroll阻塞的情况&/b&。&/p&&p&而且它的支持率也良好~&/p&&figure&&img src=&http://pic3.zhimg.com/v2-1eead5006ae_b.jpg& class=&content_image&&&/figure&&p&&br&&/p&&p&在应用方面,Angular已经做了一些尝试。&/p&&p&&a href=&https://zhuanlan.zhihu.com/p/& class=&internal&&解密Angular WebWorker Renderer (一)&/a&:想办法打破web worker本身不能操作dom元素等限制,利用web worker执行渲染操作&/p&&p&&b&&a href=&http://link.zhihu.com/?target=https%3A//developer.mozilla.org/zh-CN/docs/Web/API/Web_Workers_API/Using_web_workers& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Learn more about web worker&/a&&/b&&/p&&p&&br&&/p&&p&&b&函数节流与函数去抖&/b&&/p&&p&针对scroll事件中的回调,思路之一是对事件进行“稀释”,减少事件回调的执行次数。&/p&&p&这就涉及到两个概念:函数节流和函数去抖&/p&&ul&&li&函数节流(throttle):让函数在指定的时间段内&b&周期性地间断&/b&执行&/li&&li&函数去抖(debounce):让函数只有在过完一段时间后并且&b&该段时间内不被调用&/b&才会被执行&/li&&/ul&&p&有人这样比喻:&/p&&blockquote&就像一窝蜂的人去排队看演出,队伍很乱,看门的老大爷每隔1秒,让进一个人,这个叫throttle,如果来了这一窝蜂的人,老大爷一次演出只让进一个人,下次演出才让下一个人进,这个就叫debounce&/blockquote&&p&OK, text is long, show you code.&/p&&p&以下code来自&a href=&http://link.zhihu.com/?target=https%3A//github.com/jashkenas/underscore/blob/master/underscore.js& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&underscore.js&/a&(类似jQuery的库,封装了一些方法)&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&c1&&// Returns a function, that, when invoked, will only be triggered at most once&/span&
&span class=&c1&&// during a given window of time. Normally, the throttled function will run&/span&
&span class=&c1&&// as much as it can, without ever going more than once per `wait`&/span&
&span class=&c1&&// but if you'd like to disable the execution on the leading edge, pass&/span&
&span class=&c1&&// `{leading: false}`. To disable execution on the trailing edge, ditto.&/span&
&span class=&nx&&_&/span&&span class=&p&&.&/span&&span class=&nx&&throttle&/span& &span class=&o&&=&/span& &span class=&kd&&function&/span&&span class=&p&&(&/span&&span class=&nx&&func&/span&&span class=&p&&,&/span& &span class=&nx&&wait&/span&&span class=&p&&,&/span& &span class=&nx&&options&/span&&span class=&p&&)&/span& &span class=&p&&{&/span&
&span class=&kd&&var&/span& &span class=&nx&&timeout&/span&&span class=&p&&,&/span& &span class=&nx&&context&/span&&span class=&p&&,&/span& &span class=&nx&&args&/span&&span class=&p&&,&/span& &span class=&nx&&result&/span&&span class=&p&&;&/span&
&span class=&c1&&// 标记时间戳&/span&
&span class=&kd&&var&/span& &span class=&nx&&previous&/span& &span class=&o&&=&/span& &span class=&mi&&0&/span&&span class=&p&&;&/span&
&span class=&c1&&// options可选属性 leading: true/false 表示第一次事件马上触发回调/等待wait时间后触发&/span&
&span class=&c1&&// options可选属性 trailing: true/false 表示最后一次回调触发/最后一次回调不触发&/span&
&span class=&k&&if&/span& &span class=&p&&(&/span&&span class=&o&&!&/span&&span class=&nx&&options&/span&&span class=&p&&)&/span& &span class=&nx&&options&/span& &span class=&o&&=&/span& &span class=&p&&{};&/span&
&span class=&kd&&var&/span& &span class=&nx&&later&/span& &span class=&o&&=&/span& &span class=&kd&&function&/span&&span class=&p&&()&/span& &span class=&p&&{&/span&
&span class=&nx&&previous&/span& &span class=&o&&=&/span& &span class=&nx&&options&/span&&span class=&p&&.&/span&&span class=&nx&&leading&/span& &span class=&o&&===&/span& &span class=&kc&&false&/span& &span class=&o&&?&/span& &span class=&mi&&0&/span& &span class=&o&&:&/span& &span class=&nx&&_&/span&&span class=&p&&.&/span&&span class=&nx&&now&/span&&span class=&p&&();&/span&
&span class=&nx&&timeout&/span& &span class=&o&&=&/span& &span class=&kc&&null&/span&&span class=&p&&;&/span&
&span class=&nx&&result&/span& &span class=&o&&=&/span& &span class=&nx&&func&/span&&span class=&p&&.&/span&&span class=&nx&&apply&/span&&span class=&p&&(&/span&&span class=&nx&&context&/span&&span class=&p&&,&/span& &span class=&nx&&args&/span&&span class=&p&&);&/span&
&span class=&k&&if&/span& &span class=&p&&(&/span&&span class=&o&&!&/span&&span class=&nx&&timeout&/span&&span class=&p&&)&/span& &span class=&nx&&context&/span& &span class=&o&&=&/span& &span class=&nx&&args&/span& &span class=&o&&=&/span& &span class=&kc&&null&/span&&span class=&p&&;&/span&
&span class=&p&&};&/span&
&span class=&kd&&var&/span& &span class=&nx&&throttled&/span& &span class=&o&&=&/span& &span class=&kd&&function&/span&&span class=&p&&()&/span& &span class=&p&&{&/span&
&span class=&c1&&// 记录当前时间戳&/span&
&span class=&kd&&var&/span& &span class=&nx&&now&/span& &span class=&o&&=&/span& &span class=&nx&&_&/span&&span class=&p&&.&/span&&span class=&nx&&now&/span&&span class=&p&&();&/span&
&span class=&c1&&// 如果是第一次触发且选项设置不立即执行回调&/span&
&span class=&k&&if&/span& &span class=&p&&(&/span&&span class=&o&&!&/span&&span class=&nx&&previous&/span& &span class=&o&&&&&/span& &span class=&nx&&options&/span&&span class=&p&&.&/span&&span class=&nx&&leading&/span& &span class=&o&&===&/span& &span class=&kc&&false&/span&&span class=&p&&)&/span&
&span class=&c1&&// 将记录的上次执行的时间戳置为当前&/span&
&span class=&nx&&previous&/span& &span class=&o&&=&/span& &span class=&nx&&now&/span&&span class=&p&&;&/span&
&span class=&c1&&// 距离下次触发回调还需等待的时间&/span&
&span class=&kd&&var&/span& &span class=&nx&&remaining&/span& &span class=&o&&=&/span& &span class=&nx&&wait&/span& &span class=&o&&-&/span& &span class=&p&&(&/span&&span class=&nx&&now&/span& &span class=&o&&-&/span& &span class=&nx&&previous&/span&&span class=&p&&);&/span&
&span class=&nx&&context&/span& &span class=&o&&=&/span& &span class=&k&&this&/span&&span class=&p&&;&/span&
&span class=&nx&&args&/span& &span class=&o&&=&/span& &span class=&nx&&arguments&/span&&span class=&p&&;&/span&
&span class=&c1&&// 等待时间 &= 0或者不科学地 & wait(异常情况)&/span&
&span class=&k&&if&/span& &span class=&p&&(&/span&&span class=&nx&&remaining&/span& &span class=&o&&&=&/span& &span class=&mi&&0&/span& &span class=&o&&||&/span& &span class=&nx&&remaining&/span& &span class=&o&&&&/span& &span class=&nx&&wait&/span&&span class=&p&&)&/span& &span class=&p&&{&/span&
&span class=&k&&if&/span& &span class=&p&&(&/span&&span class=&nx&&timeout&/span&&span class=&p&&)&/span& &span class=&p&&{&/span&
&span class=&c1&&// 清除定时器&/span&
&span class=&nx&&clearTimeout&/span&&span class=&p&&(&/span&&span class=&nx&&timeout&/span&&span class=&p&&);&/span&
&span class=&c1&&// 解除引用&/span&
&span class=&nx&&timeout&/span& &span class=&o&&=&/span& &span class=&kc&&null&/span&&span class=&p&&;&/span&
&span class=&p&&}&/span&
&span class=&c1&&// 将记录的上次执行的时间戳置为当前&/span&
&span class=&nx&&previous&/span& &span class=&o&&=&/span& &span class=&nx&&now&/span&&span class=&p&&;&/span&
&span class=&c1&&// 触发回调&/span&
&span class=&nx&&result&/span& &span class=&o&&=&/span& &span class=&nx&&func&/span&&span class=&p&&.&/span&&span class=&nx&&apply&/span&&span class=&p&&(&/span&&span class=&nx&&context&/span&&span class=&p&&,&/span& &span class=&nx&&args&/span&&span class=&p&&);&/span&
&span class=&k&&if&/span& &span class=&p&&(&/span&&span class=&o&&!&/span&&span class=&nx&&timeout&/span&&span class=&p&&)&/span& &span class=&nx&&context&/span& &span class=&o&&=&/span& &span class=&nx&&args&/span& &span class=&o&&=&/span& &span class=&kc&&null&/span&&span class=&p&&;&/span&
&span class=&p&&}&/span&
&span class=&c1&&// 在定时器不存在且选项设置最后一次触发需要执行回调的情况下&/span&
&span class=&c1&&// 设置定时器,间隔remaining时间后执行later&/span&
&span class=&k&&else&/span& &span class=&k&&if&/span& &span class=&p&&(&/span&&span class=&o&&!&/span&&span class=&nx&&timeout&/span& &span class=&o&&&&&/span& &span class=&nx&&options&/span&&span class=&p&&.&/span&&span class=&nx&&trailing&/span& &span class=&o&&!==&/span& &span class=&kc&&false&/span&&span class=&p&&)&/span&
&span class=&p&&{&/span&
&span class=&nx&&timeout&/span& &span class=&o&&=&/span& &span class=&nx&&setTimeout&/span&&span class=&p&&(&/span&&span class=&nx&&later&/span&&span class=&p&&,&/span& &span class=&nx&&remaining&/span&&span class=&p&&);&/span&
&span class=&p&&}&/span&
&span class=&k&&return&/span& &span class=&nx&&result&/span&&span class=&p&&;&/span&
&span class=&p&&};&/span&
&span class=&nx&&throttled&/span&&span class=&p&&.&/span&&span class=&nx&&cancel&/span& &span class=&o&&=&/span& &span class=&kd&&function&/span&&span class=&p&&()&/span& &span class=&p&&{&/span&
&span class=&nx&&clearTimeout&/span&&span class=&p&&(&/span&&span class=&nx&&timeout&/span&&span class=&p&&);&/span&
&span class=&nx&&previous&/span& &span class=&o&&=&/span& &span class=&mi&&0&/span&&span class=&p&&;&/span&
&span class=&nx&&timeout&/span& &span class=&o&&=&/span& &span class=&nx&&context&/span& &span class=&o&&=&/span& &span class=&nx&&args&/span& &span class=&o&&=&/span& &span class=&kc&&null&/span&&span class=&p&&;&/span&
&span class=&p&&};&/span&
&span class=&k&&return&/span& &span class=&nx&&throttled&/span&&span class=&p&&;&/span&
&span class=&p&&};&/span&
&/code&&/pre&&/div&&p&&br&&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&c1&&// Returns a function, that, as long as it continues to be invoked, will not&/span&
&span class=&c1&&// be triggered. The function will be called after it stops being called for&/span&
&span class=&c1&&// N milliseconds. If `immediate` is passed, trigger the function on the&/span&
&span class=&c1&&// leading edge, instead of the trailing.&/span&
&span class=&nx&&_&/span&&span class=&p&&.&/span&&span class=&nx&&debounce&/span& &span class=&o&&=&/span& &span class=&kd&&function&/span&&span class=&p&&(&/span&&span class=&nx&&func&/span&&span class=&p&&,&/span& &span class=&nx&&wait&/span&&span class=&p&&,&/span& &span class=&nx&&immediate&/span&&span class=&p&&)&/span& &span class=&p&&{&/span&
&span class=&kd&&var&/span& &span class=&nx&&timeout&/span&&span class=&p&&,&/span& &span class=&nx&&result&/span&&span class=&p&&;&/span&
&span class=&c1&&// 定时器设置的回调,清除定时器,执行回调函数func&/span&
&span class=&kd&&var&/span& &span class=&nx&&later&/span& &span class=&o&&=&/span& &span class=&kd&&function&/span&&span class=&p&&(&/span&&span class=&nx&&context&/span&&span class=&p&&,&/span& &span class=&nx&&args&/span&&span class=&p&&)&/span& &span class=&p&&{&/span&
&span class=&nx&&timeout&/span& &span class=&o&&=&/span& &span class=&kc&&null&/span&&span class=&p&&;&/span&
&span class=&k&&if&/span& &span class=&p&&(&/span&&span class=&nx&&args&/span&&span class=&p&&)&/span& &span class=&nx&&result&/span& &span class=&o&&=&/span& &span class=&nx&&func&/span&&span class=&p&&.&/span&&span class=&nx&&apply&/span&&span class=&p&&(&/span&&span class=&nx&&context&/span&&span class=&p&&,&/span& &span class=&nx&&args&/span&&span class=&p&&);&/span&
&span class=&p&&};&/span&
&span class=&c1&&// restArgs函数将传入的func的参数改造成Rest Parameters —— 一个参数数组&/span&
&span class=&kd&&var&/span& &span class=&nx&&debounced&/span& &span class=&o&&=&/span& &span class=&nx&&restArgs&/span&&span class=&p&&(&/span&&span class=&kd&&function&/span&&span class=&p&&(&/span&&span class=&nx&&args&/span&&span class=&p&&)&/span& &span class=&p&&{&/span&
&span class=&k&&if&/span& &span class=&p&&(&/span&&span class=&nx&&timeout&/span&&span class=&p&&)&/span& &span class=&nx&&clearTimeout&/span&&span class=&p&&(&/span&&span class=&nx&&timeout&/span&&span class=&p&&);&/span&
&span class=&k&&if&/span& &span class=&p&&(&/span&&span class=&nx&&immediate&/span&&span class=&p&&)&/span& &span class=&p&&{&/span&
&span class=&c1&&// 立即触发的条件:immediate为true且timeout为空&/span&
&span class=&kd&&var&/span& &span class=&nx&&callNow&/span& &span class=&o&&=&/span& &span class=&o&&!&/span&&span class=&nx&&timeout&/span&&span class=&p&&;&/span&
&span class=&nx&&timeout&/span& &span class=&o&&=&/span& &span class=&nx&&setTimeout&/span&&span class=&p&&(&/span&&span class=&nx&&later&/span&&span class=&p&&,&/span& &span class=&nx&&wait&/span&&span class=&p&&);&/span&
&span class=&k&&if&/span& &span class=&p&&(&/span&&span class=&nx&&callNow&/span&&span class=&p&&)&/span& &span class=&nx&&result&/span& &span class=&o&&=&/span& &span class=&nx&&func&/span&&span class=&p&&.&/span&&span class=&nx&&apply&/span&&span class=&p&&(&/span&&span class=&k&&this&/span&&span class=&p&&,&/span& &span class=&nx&&args&/span&&span class=&p&&);&/span&
&span class=&p&&}&/span& &span class=&k&&else&/span& &span class=&p&&{&/span&
&span class=&c1&&// _.delay方法实际上是setTimeout()包裹了一层参数处理的逻辑&/span&
&span class=&nx&&timeout&/span& &span class=&o&&=&/span& &span class=&nx&&_&/span&&span class=&p&&.&/span&&span class=&nx&&delay&/span&&span class=&p&&(&/span&&span class=&nx&&later&/span&&span class=&p&&,&/span& &span class=&nx&&wait&/span&&span class=&p&&,&/span& &span class=&k&&this&/span&&span class=&p&&,&/span& &span class=&nx&&args&/span&&span class=&p&&);&/span&
&span class=&p&&}&/span&
&span class=&k&&return&/span& &span class=&nx&&result&/span&&span class=&p&&;&/span&
&span class=&p&&});&/span&
&span class=&nx&&debounced&/span&&span class=&p&&.&/span&&span class=&nx&&cancel&/span& &span class=&o&&=&/span& &span class=&kd&&function&/span&&span class=&p&&()&/span& &span class=&p&&{&/span&
&span class=&nx&&clearTimeout&/span&&span class=&p&&(&/span&&span class=&nx&&timeout&/span&&span class=&p&&);&/span&
&span class=&nx&&timeout&/span& &span class=&o&&=&/span& &span class=&kc&&null&/span&&span class=&p&&;&/span&
&span class=&p&&};&/span&
&span class=&k&&return&/span& &span class=&nx&&debounced&/span&&span class=&p&&;&/span&
&span class=&p&&};&/span&
&/code&&/pre&&/div&&p&对比以上代码,我们可以发现,两种方法应用的场景时有差别的&/p&&ul&&li&函数节流:适用于多次提交(commit)的场景,如点击按钮提交发送请求的情况&/li&&li&函数去抖:适用于scroll/resize等场景&/li&&/ul&&p&相对于多次触发只执行一次的debounce,间隔地执行回调的throttle更能满足“稀释”scroll事件的需求。&/p&&p&至于wait的设定值,到底多久执行一次比较合适?很大部分还是取决于具体的场景&代码复杂度,但是这里有一个例子可以参考:&a href=&http://link.zhihu.com/?target=https%3A//johnresig.com/blog/learning-from-twitter/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Learning from Twitter&/a&&/p&&p&2011年Twitter出现过滚动性能差到严重影响用户体验的案例,原因是&/p&&blockquote&It’s a very, very, bad idea to attach handlers to the window scroll event.&br&&br&Always cache the selector queries that you’re re-using.&/blockquote&&p&最后采用了函数节流的办法:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&var outerPane = $details.find(&.details-pane-outer&),
didScroll =
$(window).scroll(function() {
didScroll =
setInterval(function() {
if ( didScroll ) {
didScroll =
// Check your page position and then
// Load in more results
&/code&&/pre&&/div&&p&示例中给出的数字250,可以给大家参考一下~&/p&&p&&br&&/p&&p&&b&去定时器&/b&&/p&&p&为什么定时器会引起掉帧?&/p&&figure&&img src=&http://pic4.zhimg.com/v2-cdcb2c952c7e1cf989d3_b.jpg& class=&content_image&&&/figure&&p&如你所见,定时器导致掉帧的原因,就在于无法准确控制回调执行的时机。&/p&&p&即使给定时器设置延时时间wait恰好为16.7ms,也不行。&/p&&p&js的单线程限制了回调会在16.7ms之后加入任务队列,却不能保证一定在16.7ms之后触发。如果当下js正在进行耗时计算,回调就只能等着。所以实际上回调执行的时机,是定时器设置后 &= 16.7ms后。&/p&&p&那么去定时器是否意味着否定了之前说的函数去抖和函数节流操作?&/p&&p&NONONO,这两种提升scroll性能的操作应用于不同的场景:&/p&&ul&&li&scroll过程中伴随着不直接改变画面效果的计算操作,如懒加载、loadmore等,在这样的scroll场景里,我们要不断进行判断操作,大量的计算操作就可能阻塞scroll,所以要对操作进行“稀释”。&/li&&li&scroll过程中伴随着直接改变画面效果的操作,如动画、affix引起的scroll滚动等。&/li&&/ul&&p&&b&案例:&/b&在这个世界上,有一种经典的导航栏形式,那就是,affix。&/p&&blockquote&这种导航栏在你scroll时会粘在你的窗口的固定位置(一般是top),并且在你点击导航栏时自动滚动到页面对应的target内容。&/blockquote&&figure&&img src=&https://pic4.zhimg.com/v2-af07fd6e7e36f7ac50b169_b.jpg& data-thumbnail=&http://pic2.zhimg.com/v2-af07fd6e7e36f7ac50b169_b.jpg& class=&content_image&&&/figure&&p&&a href=&http://link.zhihu.com/?target=http%3A//7xw3pf.com1.z0.glb.clouddn.com/scroll-performance_13-16-28.gif& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&不动戳我&/a&&/p&&p&这是我自己做的一个小demo,利用了setInterval,每16.7ms设置scrollTop + 5px,达到“平滑”滚动的效果。&/p&&figure&&img src=&http://pic1.zhimg.com/v2-fca1f91fc989f16beaa0268_b.jpg& class=&content_image&&&/figure&&p&emmmm,看着不规则的锯齿,难受。&/p&&p&如果还不够明显,试试将wait设为50ms&/p&&figure&&img src=&http://pic1.zhimg.com/v2-ad53672c0ffd6bfefa661e20_b.jpg& class=&content_image&&&/figure&&p&看起来,要赶上每一个标准帧渲染的时机,不是那么容易,但是旁友,你听说过安利吗?哦走错片场了,是&i&requestAnimationFrame()&/i&和&i&requestIdleCallback()&/i&.&/p&&p&&b&requestAnimationFrame()&/b&&/p&&blockquote&The window.requestAnimationFrame() method tells the browser that you wish to perform an animation and requests that the browser call a specified function to update an animation before the next repaint. The method takes a callback as an argument to be invoked before the repaint.&/blockquote&&p&可以将它看做一个钩子,刚好卡在浏览器重绘前向我们的操作伸出橄榄枝。实际上它更像定时器,每秒60次执行回调——符合屏幕的刷新频率,遇到耗时长的操作,这个数字会降到30来保证稳定的帧数。&/p&&p&语法也很简单:&i&window.requestAnimationFrame(callback)&/i&&/p&&p&更改后的代码:&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&kr&&const&/span& &span class=&nx&&newScrollTop&/span& &span class=&o&&=&/span& &span class=&k&&this&/span&&span class=&p&&.&/span&&span class=&nx&&getPosition&/span&&span class=&p&&(&/span&&span class=&k&&this&/span&&span class=&p&&.&/span&&span class=&nx&&panes&/span&&span class=&p&&[&/span&&span class=&nx&&index&/span&&span class=&p&&].&/span&&span class=&nx&&$refs&/span&&span class=&p&&.&/span&&span class=&nx&&content&/span&&span class=&p&&).&/span&&span class=&nx&&top&/span& &span class=&o&&-&/span& &span class=&k&&this&/span&&span class=&p&&.&/span&&span class=&nx&&distance&/span&
&span class=&kd&&function&/span& &span class=&nx&&scrollStep&/span&&span class=&p&&()&/span& &span class=&p&&{&/span&
&span class=&nb&&document&/span&&span class=&p&&.&/span&&span class=&nx&&documentElement&/span&&span class=&p&&.&/span&&span class=&nx&&scrollTop&/span& &span class=&o&&+=&/span& &span class=&mi&&5&/span&
&span class=&k&&if&/span& &span class=&p&&(&/span&&span class=&nb&&document&/span&&span class=&p&&.&/span&&span class=&nx&&documentElement&/span&&span class=&p&&.&/span&&span class=&nx&&scrollTop&/span& &span class=&o&&&&/span& &span class=&nx&&newScrollTop&/span&&span class=&p&&)&/span& &span class=&p&&{&/span&
&span class=&nb&&window&/span&&span class=&p&&.&/span&&span class=&nx&&requestAnimationFrame&/span&&span class=&p&&(&/span&&span class=&nx&&scrollStep&/span&&span class=&p&&)&/span&
&span class=&p&&}&/span&
&span class=&p&&}&/span&
&span class=&nb&&window&/span&&span class=&p&&.&/span&&span class=&nx&&requestAnimationFrame&/span&&span class=&p&&(&/span&&span class=&nx&&scrollStep&/span&&span class=&p&&)&/span&
&/code&&/pre&&/div&&p&与定时器很相似,只是鉴于其一次执行只调用一次回调,所以需要以递归的方式书写。&/p&&p&测试一下:&/p&&figure&&img src=&http://pic2.zhimg.com/v2-f700fecec596c1_b.jpg& class=&content_image&&&/figure&&p&可以说是很顺滑了~&/p&&p&兼容性呢?&/p&&figure&&img src=&http://pic1.zhimg.com/v2-8d275ba747bd62c9ae71c8_b.jpg& class=&content_image&&&/figure&&p&&b&&a href=&http://link.zhihu.com/?target=https%3A//developer.mozilla.org/zh-CN/docs/Web/API/Window/requestAnimationFrame& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Learn more about requestAnimationFrame()&/a&&/b&&/p&&p&&br&&/p&&p&&b&requestIdleCallback()&/b&&/p&&blockquote&The window.requestIdleCallback() method queues a function to be called during a browser's idle periods. This enables developers to perform background and low priority work on the main event loop, without impacting latency-critical events such as animation and input response. Functions are generally called in first-in-first- however, callbacks which have a timeout specified may be called out-of-order if necessary in order to run them before the timeout elapses.&/blockquote&&p&意思是,它会在一帧末尾浏览器空闲时触发回调,否则,推迟到下一帧。&/p&&p&看定义,它适合应用于执行在后台运行或者优先度低的任务,但是鉴于我们的案例逻辑和计算都比较简单,应该能满足&b&一帧末尾有空闲&/b&(毕竟标题是“不择手段”),have a try.&/p&&p&实际上,基础使用上&i&requestIdleCallback()&/i&和&i&requestAnimationFrame()&/i&语法相同,代码修改甚至也只替换了方法名。&/p&&p&应用情况呢?&/p&&figure&&img src=&http://pic4.zhimg.com/v2-f5b76ab0c7d8bdee8753b_b.jpg& class=&content_image&&&/figure&&p&也是如丝般顺滑~仔细看每一帧,我们会发现,Fire Idle Callback正如其定义,出现在每帧的最后。&/p&&p&但是兼容性看起来除了chrome和FireFox之外,就不是那么友好了:&/p&&figure&&img src=&http://pic1.zhimg.com/v2-aac9f8c630aeaf0d73d8_b.jpg& class=&content_image&&&/figure&&p&&b&总结&/b&&/p&&p&在追求高性能的渲染效果时,可以考虑用&i&requestIdleCallback()&/i&和&i&requestAnimationFrame()&/i&代替定时器。前者适合流畅的动画效果场景,后者适用于分离一些优先级低的操作逻辑,使用时需要考虑清楚。&/p&&p&&br&&/p&&p&&b&避免强制重排&/b&&/p&&p&记忆力好的同学可能还记得,我们在之前描述浏览器渲染过程时,提到一个强制重排的概念,它的特点是,会插队!&/p&&blockquote&注意红线,意思是可能会在JS里强制重排,当访问scrollWidth系列、clientHeight系列、offsetTop系列、ComputedStyle等属性时,会触发这个效果,导致Style和Layout前移到JS代码执行过程中&/blockquote&&p&这个强制重排(force layout)听起来好像和重排很像啊,那么它和重排以及重绘是什么关系呢?&/p&&p&优秀的前端工程师对重绘和重绘的概念已经很熟悉了,我这里就不再赘述。浏览器有自己的优化机制,包括之前提到的每帧只响应同类别的事件一次,再比如这里的会把一帧里的多次重排、重绘汇总成一次进行处理。&/p&&p&&b&flush队列&/b&是浏览器进行重排、重绘等操作的队列,所有会引起重排重绘的操作都包含在内,比如dom修改、样式修改等。如果每次js操作都去执行一次重排重绘,那么浏览器一定会卡卡卡卡卡,所以浏览器通常是&b&在一定的时间间隔(一帧)内,批量处理队列里的操作&/b&。但是,对于有些操作,比如获取元素相对父级元素左边界的偏移值(Element.offsetLeft),但在此之前我们进行了样式或者dom修改,这个操作还攒在flush队列里没有执行,那么浏览器为了让我们获取正确的offsetLeft(虽然之前的操作可能不会影响offsetLeft的值),就会立即执行队列里的操作。&/p&&figure&&img src=&http://pic2.zhimg.com/v2-0acbee13c34a221ff611_b.jpg& data-caption=&& data-rawwidth=&930& data-rawheight=&417& class=&origin_image zh-lightbox-thumb& width=&930& data-original=&http://pic2.zhimg.com/v2-0acbee13c34a221ff611_r.jpg&&&/figure&&p&所以我们知道了,就是这个特殊操作会影响浏览器正常的执行和渲染,假设我们频繁执行这样的特殊操作,就会打断浏览器原来的节奏,增大开销。&/p&&p&而这个特殊操作,具体指的就是:&/p&&ul&&li&elem.offsetLeft, elem.offsetTop, elem.offsetWidth, elem.offsetHeight, elem.offsetParent&/li&&li&elem.clientLeft, elem.clientTop, elem.clientWidth, elem.clientHeight&/li&&li&elem.getClientRects(), elem.getBoundingClientRect()&/li&&li&elem.scrollWidth, elem.scrollHeight&/li&&li&elem.scrollLeft, elem.scrollTop&/li&&li&...&/li&&/ul&&p&&b&&a href=&http://link.zhihu.com/?target=https%3A//gist.github.com/paulirish/5d52fb081ba& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&See more:What forces layout / reflow&/a&&/b&&/p&&p&解决办法呢,有俩:&/p&&ul&&li&基础版:使用前面提到过的requestAnimationFrame(),将以上特殊操作汇集并延迟入队&/li&&li&进阶版:使用第三方&a href=&http://link.zhihu.com/?target=https%3A//github.com/wilsonpage/fastdom& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&FastDom&/a&帮助我们自动完成读写操作的批处理,实际上它也是建立在requestAnimationFrame()上构造的。&a href=&http://link.zhihu.com/?target=http%3A//wilsonpage.github.io/fastdom/examples/animation.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&官方提供的example&/a&看起来效果简直优秀&/li&&/ul&&blockquote&FastDom works as a regulatory layer between your app/library and the DOM. By batching DOM access we avoid unnecessary document reflows and dramatically speed up layout performance.&br&Each measure/mutate job is added to a corresponding measure/mutate queue. The queues are emptied (reads, then writes) at the turn of the next frame using window.requestAnimationFrame.&br&FastDom aims to behave like a singleton across all modules in your app. When any module requires 'fastdom' they get the same instance back, meaning FastDom can harmonize DOM access app-wide.&br&Potentially a third-party library could depend on FastDom, and better integrate within an app that itself uses it.&/blockquote&&p&&b&总结&/b&&/p&&p&谨慎使用以上特殊的读操作,要使用也尽量汇集、包裹(requestAnimationFrame()),避免单个裸奔。&/p&&p&&b&&a href=&http://link.zhihu.com/?target=https%3A//developers.google.com/web/tools/chrome-devtools/rendering-tools/forced-synchronous-layouts%3Fhl%3Dzh-cn& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Learn more about how to giagnose forced synchronous layouts with chrome DevTools&/a&&/b&&/p&&p&&br&&/p&&p&&b&提升合成层&/b&&/p&&p&不知道有没有人,曾经围坐在黑夜里的炉火旁边,听前端前辈们传递智慧的话语 —— 做位移效果时使用tranform代替top/left/bottom/right,尤其是移动端!&/p&&p&why?&/p&&p&因为top/left/bottom/right属性性能差呀 —— 这类属性会影响元素在文档中的布局,可能改变其他元素的位置,引起重排,造成性能开销&/p&&p&因为tranform属性性能好呀 —— 使用transform属性(3D/animation)将元素提升至合成层,省去布局和绘制环节,美滋滋~&/p&&p&说到这里,你可能还不是太清楚合成层的概念,其实看这篇就够了:&a href=&http://link.zhihu.com/?target=http%3A//taobaofed.org/blog//performance-composite/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&无线性能优化:Composite&/a&&/p&&p&但是照顾一下有些“太长不看”猫病的旁友们,在这里做一些总结。&/p&&p&1.一些属性会让元素们&b&创建出不同的渲染层&/b&&/p&&ul&&li&有明确的定位属性(relative、fixed、sticky、absolute)&/li&&li&透明的(opacity 小于 1)&/li&&li&有 CSS 滤镜(fliter)&/li&&li&有 CSS transform 属性(不为 none)&/li&&li&...&/li&&/ul&&p&2.达成一些条件,&b&渲染层会提升为合成层&/b&&/p&&ul&&li&硬件加速的 iframe 元素(比如 iframe 嵌入的页面中有合成层)&/li&&li&3D 或者 硬件加速的 2D Canvas 元素&/li&&li&video 元素&/li&&li&有 3D transform&/li&&li&对 opacity、transform、fliter、backdropfilter 应用了 animation 或者 transition&/li&&li&will-change 设置为 opacity、transform、top、left、bottom、right(其中 top、left 等需要设置明确的定位属性,如 relative 等)&/li&&li&...&/li&&/ul&&p&提升为合成层干什么呢?普通的渲染层普通地渲染,用普通的顺序普通地合成不好吗?非要搞啥特殊待遇!&/p&&p&浏览器就说了:我这也是为了大家共同进步(提升速度)!看那些搞特殊待遇的,都是一些拖我们队伍后腿的(性能开销大),分开处理,才能保证整个队伍稳定快速的进步!&/p&&p&&b&特殊待遇&/b&:合成层的位图,会交由 GPU 合成,比 CPU 处理要快。当需要 repaint 时,只需要 repaint 本身,不会影响到其他的层。&/p&&blockquote&对布局属性进行动画,浏览器需要为每一帧进行重绘并上传到 GPU 中&br&&br&对合成属性进行动画,浏览器会为元素创建一个独立的复合层,当元素内容没有发生改变,该层就不会被重绘,浏览器会通过重新复合来创建动画帧&/blockquote&&p&所以,从合成层出发,为了优化scroll性能,我们可以做这些:&/p&&p&&b&&a href=&http://link.zhihu.com/?target=https%3A//developer.mozilla.org/zh-CN/docs/Web/CSS/will-change& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&will-change&/a&&/b&&/p&&p&提升合成层的有效方式,应用这个属性,实际上是提前通知浏览器,为接下来的动画效果操作做准备。值得注意的是&/p&&ul&&li&不要将 will-change 应用到太多元素上,增加渲染层意味着新的内存分配和更复杂的层的管理&/li&&li&有节制地使用。动态样式增加比一开始就写在样式表里更能减少不必要的开销。&/li&&/ul&&p&示例:&/p&&div class=&highlight&&&pre&&code class=&language-css&&&span&&/span&&span class=&nt&&will-change&/span&&span class=&o&&:&/span& &span class=&nt&&scroll-position&/span& &span class=&o&&//&/span& &span class=&err&&表示开发者希望在不久后改变滚动条的位置或者使之产生动画。&/span&
&/code&&/pre&&/div&&p&然后,国际惯例【并不,附上兼容性&/p&&figure&&img src=&http://pic4.zhimg.com/v2-8dd9cea742e559d9d08ab_b.jpg& class=&content_image&&&/figure&&p&&br&&/p&&p&&b&除此之外&/b&&/p&&ul&&li&使用 transform 或者 opacity 来实现动画效果&/li&&li&对于较少可能变化的区域,防止页面其他部分重绘时影响这一片,考虑提升至合成层。&/li&&li&提升合成层的hack方法:translateZ(0)&/li&&/ul&&p&&b&总结&/b&&/p&&p&从合成层的角度作为性能提升的下手方向,是值得肯定的,但是具体采用什么样的方案,还是要先切实地分析页面的实际性能表现,根据不同的场景,综合考虑方案的得失,再总结出正确的优化途径。&/p&&p&&br&&/p&&p&&b&what's more&/b&&/p&&p&&b&使用css属性代替js“模拟操作”&/b&&/p&&p&&a href=&http://link.zhihu.com/?target=https%3A//developer.mozilla.org/en-US/docs/Web/CSS/scroll-behavior& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&scroll-behavior&/a&&/p&&blockquote&The scroll-behavior CSS property specifies the scrolling behavior for a scrolling box, when scrolling happens due to navigation or CSSOM scrolling APIs. Any other scrolls, e.g. those that are performed by the user, are not affected by this property. When this property is specified on the root element, it applies to the viewport instead.&/blockquote&&p&可以借此实现affix,而不用使用定时器或requestAnimationFrame模拟平滑的scroll操作&/p&&p&demo戳:&a href=&http://link.zhihu.com/?target=https%3A//developer.mozilla.org/zh-CN/docs/Web/CSS/scroll-behavior& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&锚点链接+scroll-behavior&/a&&/p&&figure&&img src=&https://pic1.zhimg.com/v2-023d32d042e5bbf7a7c7_b.jpg& data-thumbnail=&http://pic4.zhimg.com/v2-023d32d042e5bbf7a7c7_b.jpg& class=&content_image&&&/figure&&p&但是目前仅是实验性的功能,残念&/p&&figure&&img src=&http://pic4.zhimg.com/v2-dec286e18eda_b.jpg& class=&content_image&&&/figure&&hr&&h2&总结&/h2&&p&页面渲染性能的优化涉及方方面面,这里只是以scroll事件为立足点分析列举了一些改善的方法,深入性和全面性都不足,但更多希望能起到一个引子的作用,给有心深入的同学一个概括性的印象。&/p&&hr&&h2&参考链接&/h2&&p&以下这些大大们的文章都很值得阅读分析做笔记!&/p&&ul&&li&&a href=&http://link.zhihu.com/?target=https%3A//developers.google.com/web/fundamentals/performance/rendering/%3Fhl%3Dzh-cn& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&渲染性能&/a&&/li&&li&&a href=&http://link.zhihu.com/?target=https%3A//github.com/chokcoco/cnblogsArticle/issues/12& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&【前端性能】高性能滚动 scroll 及页面渲染优化&/a&&/li&&li&&a href=&http://link.zhihu.com/?target=https%3A//chuckliu.me/%23%21/posts/58ea6af15dc74& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&浏览器渲染详细过程:重绘、重排和 composite 只是冰山一角&/a&&/li&&li&&a href=&http://link.zhihu.com/?target=https%3A//dzone.com/articles/web-workers-responsive& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Web Workers, for a responsive JavaScript application&/a&&/li&&li&&a href=&http://link.zhihu.com/?target=https%3A//github.com/hanzichi/underscore-analysis/issues/20& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&JavaScript 函数节流和函数去抖应用场景辨析&/a&&/li&&li&&a href=&http://link.zhihu.com/?target=https%3A//github.com/aooy/blog/issues/5& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&从event loop规范探究javaScript异步及浏览器更新渲染时机&/a&&/li&&/ul&
&!--假装此处有一个段子作为引子--&TL;DR1. chrome devtool 是诊断页面滚动性能的有效工具2. 提升滚动时性能,就是要达到fps高且稳。3. 具体可以从以下方面着手使用web worker分离无页面渲染无关的逻辑计算触发监听事件时使用函数节流与函数去抖使用request…
&p&更新于17年12月20日。&/p&&p&2018年的1月1日到4月30日,希尔顿的白吃白住活动又来啦!&/p&&p&活动内容见下图&/p&&figure&&img src=&https://pic4.zhimg.com/v2-64cc8cb975a145bb77ded3f35d23a607_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&1000& data-rawheight=&521& class=&origin_image zh-lightbox-thumb& width=&1000& data-original=&https://pic4.zhimg.com/v2-64cc8cb975a145bb77ded3f35d23a607_r.jpg&&&/figure&&p&活动注册地址如下:&a href=&//link.zhihu.com/?target=https%3A//www.hiltonhonors.com/zh_CN/HHCM/4/landing& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&18年春季希尔顿无上限奖励积分活动&i class=&icon-external&&&/i&&/a&&/p&&p&这个活动的意思是,每次入住可以额外获取2000积分,满5次入住额外获取10000积分。&/p&&p&相当于,&b&每次入住,额外获取4000积分。&/b&&/p&&p&要知道,市面上均价400元以上的希尔顿花园,希尔顿逸林,&/p&&p&有很多&b&只要5000积分就能兑换到。&/b&&/p&&p&另外,&b&钻石会员还会额外赠送你750积分。&/b&&/p&&p&那么一次入住实际的花费是&/p&&p&&b&00-750=250积分。&/b&&/p&&p&250积分多少钱呢?&b&10元以内。&/b&&/p&&p&市面上均价800以上的希尔顿逸林呢,&/p&&p&以一万积分兑换,实际花费是&/p&&p&-0&/p&&p&&b&不超过200元。&/b&&/p&&p&&br&&/p&&p&操作流程就是&/p&&p&1,注册帐号。&/p&&p&2,购买积分。&/p&&p&3,预定然后入住。&/p&&p&建议看完原始答案以后再看一下相关文章。&/p&&p&关于希尔顿的相关文章如下:&/p&&p&1,如何购买积分:&a href=&https://zhuanlan.zhihu.com/p/& class=&internal&&希尔顿又又又又叕叕开始5折卖分啦!&/a&&/p&&p&(这次促销截止到17年12月31号,下次积分促销预计会在明年二月份)&/p&&p&2,关于希尔顿的一点感叹:&a href=&https://zhuanlan.zhihu.com/p/& class=&internal&&希尔顿,不止是羊毛可以薅&/a&&/p&&p&3,此前其他集团酒店的入住攻略:&a href=&https://zhuanlan.zhihu.com/p/& class=&internal&&三百以内!无脑住五星级!喜达屋集团超强攻略来袭!&/a&&/p&&p&希望大家旅行愉快!&/p&&p&若有不懂,也欢迎大家向我咨询。&/p&&p&微信,微信群,QQ群里给大家免费答疑几个月了~&/p&&hr&&p&---------------------以下为原答案-------------------&/p&&p&学生狗一只!!!!干货!!!&/p&&p&不抖机灵!!!&br&如果是出去玩的话,住有些地方的希尔顿比住如家汉庭7天便宜多了&br&而且&br&而且&br&而且&br&而且以下东西纷纷免费&br&双人早餐免费&br&房型升级免费&br&游泳池健身房免费&br&晚上6点到8点的欢乐时光(算是一个小自助)免费&br&全天候饮料免费&br&下午4点退房免费&br&这样的四五星酒店,以极低的价格体验过了一次,&br&还会再住如家汉庭????&/p&&p&上半年课比较少了,从二月份入坑希尔顿开始,出去住酒店通通希尔顿,App显示住了18晚了,但是实际上有时候出去开的两个房,也只能算一间房的SN的&/p&&figure&&img src=&https://pic1.zhimg.com/v2-bab_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&750& data-rawheight=&893& class=&origin_image zh-lightbox-thumb& width=&750& data-original=&https://pic1.zhimg.com/v2-bab_r.jpg&&&/figure&&p&&br&&/p&&p&&br&&/p&&p&&br&&/p&&p&希尔顿花园,实际花费曾经不超过三十块,&/p&&p&&br&&/p&&figure&&img src=&https://pic3.zhimg.com/v2-b05121befb22c49ffb80c8cadbc1bf16_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&4032& data-rawheight=&3024& class=&origin_image zh-lightbox-thumb& width=&4032& data-original=&https://pic3.zhimg.com/v2-b05121befb22c49ffb80c8cadbc1bf16_r.jpg&&&/figure&&p&&br&&/p&&figure&&img src=&https://pic4}

我要回帖

更多关于 鼠标丢帧 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信