ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

前端性能优化实战:吃透Chrome Performance面板,告别玄学调优

前端性能优化实战:吃透Chrome Performance面板,告别玄学调优 1. 从玄学调优到科学定位为什么性能分析一定要看Performance面板做前端这几年我见过太多团队把性能优化做成了开盲盒。页面卡了第一反应是压缩图片、砍第三方库、上CDN一顿操作猛如虎再看指标心里苦。问题在于你根本不知道瓶颈到底在哪就只能靠猜。猜对了是运气猜错了是常态最后变成调参玄学谁也没法说服谁。真正能把性能问题从我觉得变成数据在这的工具就是浏览器自带的Performance面板。这玩意不是Chrome的隐藏彩蛋它是DevTools里最硬核、也最被低估的一个标签页。很多前端开发待了五六年Network面板玩得飞起Elements面板改样式比设计还快唯独Performance面板一打开就头皮发麻——满屏的色块、密集的横条、各种看不懂的缩写完全不知道从哪下手。这篇博文我就把这层窗户纸捅破。我会用实际的录制和分析流程把Performance面板里的每一个关键视图、每一项核心指标、每一块颜色到底在说什么拆开揉碎了讲清楚。目标是让你看完之后拿到任何一个卡顿页面都能自己录一段性能报告快速定位到具体是脚本执行慢、样式计算爆炸、还是渲染层频繁重绘然后对症下药。这个面板适合谁只要你的工作跟网页性能这四个字沾边都值得花时间吃透。前端工程师做页面优化后端查接口渲染瓶颈测试同学给开发提bug时附上一份带火焰图的性能报告——杀伤力完全不是一个级别。甚至产品经理拿它来对比改版前后的性能差异也能有理有据地说这个需求不能上因为首屏FPS掉了15。而且本质上Performance面板解决的是性能优化里最核心的一个问题时间都去哪了。它不关心你的代码长什么样、用了什么框架、跑在什么设备上它只关心一件事——浏览器从收到你的页面开始每一毫秒都在干什么。把这个问题搞清楚了优化方向自然就出来了。2. 先看懂这几个核心指标不然录了白录我不建议一上来就按Record按钮。Performance面板录出来的数据非常密集如果对关键指标没有概念录完你也只能对着屏幕发呆。我自己的经验是先花十分钟搞清楚面板里那几个核心指标在说什么再动手实操效率高得多。2.1 录一段数据要盯住的六个数Performance面板录制完成后顶部会有几条关键数据线加上Summary的饼图组成了性能报告的仪表盘。我每次分析性能最先看的就是下面这几个指标含义重点关注场景FPS每秒帧数页面流畅度的最直观体现滚动、动画、拖拽卡顿CPU整段录制期间CPU占用曲线长时间高占用会导致页面无响应NET网络请求耗时分布首屏资源加载慢Heap堆内存占用变化内存泄漏、GC频繁加载时长页面从开始到加载完成的总耗时首屏速度优化脚本/渲染/绘制时长三类主要任务的耗时占比定位瓶颈所在类型FPS这条线最关键。如果你录制的场景里有动画或滚动这条线应该稳定在60附近显示为绿色一旦掉到30以下甚至出现大段的红色说明页面已经明显卡顿。这里有个小细节要注意Performance面板里的FPS是近似值它统计的是主线程上帧与帧之间的时间间隔不是显示器真实刷新率但对于判断卡不卡完全够用。CPU曲线看的是整体CPU占用率的时间线如果它在长时间内都是90%以上说明页面在疯狂消耗计算资源用户会感觉设备发烫、风扇狂转、操作反应迟钝。Heap这个很容易被忽略但我建议每份性能报告都扫一眼。如果Heap曲线整体呈现上升-平台-上升-平台这样的阶梯状并且GC垃圾回收事件频繁那大概率有内存泄露。内存问题最难排查越早发现越好。2.2 底部概览区的三块拼图工具栏下方的概览区域Overview分为三个部分Network网络、Frames帧、Timings时间指标。它们对应了性能优化的三条线资源加载、渲染流畅度、关键时间点。Network部分是一根根横条每根条代表一个资源请求颜色越深表示耗时越长。Frames部分是一排小方块绿色表示这一帧在16.6ms内完成渲染红色就是超时掉帧。Timings部分标出了关键节点比如FPFirst Paint首次绘制、FCPFirst Contentful Paint首次内容绘制、LCPLargest Contentful Paint最大内容绘制和DCLDOMContentLoaded。这三个部分是性能报告的地图导航先看它们锁定大致方向再往下沉入Main主线程看细节。我见过有人一上来就盯着Main线程那密密麻麻的色块看看十分钟也没看出名堂。正确的路径应该是先概览再局部最后下沉。2.3 Summary饼图怎么读才有用录制结束后顶部会有一个Summary选项卡展示一个饼图。这个饼图很容易被误读——很多人看一眼脚本占了50%就开始骂自己代码写得烂其实不是这么回事。Summary饼图展示的是主线程上各类任务的耗时占比主要包括这几类Scripting脚本执行JS代码运行时间包括事件处理、定时器、requestAnimationFrame回调等Rendering渲染样式计算Style、布局Layout、更新图层树等Painting绘制把渲染结果绘制成位图的过程Loading加载HTML解析、资源加载相关Other其他执行任务之间的空隙、浏览器内部开销饼图的价值在于快速定性——如果你的页面卡顿先看饼图里哪一块是最大头。Scripting占比高重点排查JS逻辑Rendering占比高重点排查样式和布局Painting占比高重点排查合成层和绘制区域。这个方向定错了后面全白干。但要注意饼图是平均占比它会把整段录制时间平均掉。如果一个任务只持续了100ms但在那段时间里CPU打满了饼图上可能只占3%。所以饼图只是切入点真正的细节必须去Main线程的时间线里看。3. 从录到读一条完整的Performance分析流水线理论说得再多不如亲手走一遍流程。这一节我按自己的实操习惯把Performance面板从录制到分析的关键步骤过一遍。你跟着做一遍再回头看那些术语就会发现其实没那么玄乎。3.1 录制前必须做的三个设置第一件事用无痕窗口打开目标页面。为什么普通窗口里各种浏览器插件都在后台跑着它们会影响性能数据的真实性。尤其是广告拦截类的扩展看着人畜无害实际上对页面加载和脚本执行都有影响。无痕窗口默认禁用大部分扩展能给你一个相对干净的环境。第二件事在DevTools的Performance设置里确认CPU和网络没有限流。除非你要模拟低端设备环境否则这两项都应该选择No throttling不限流。很多性能问题在开发机上根本复现不了就是因为开发机配置太好。如果你想模拟真实用户环境我的建议是CPU 4x降速 Fast 3G网络这是比较接近中端Android手机的体验。第三件事规划好你要录什么。性能录制不是打开就录而是要先想清楚录首屏加载那就从空白页开始录滚动卡顿先准备好滚动的操作路径录点击交互想清楚从点击哪个按钮开始。录制的时间最好控制在5-10秒之内太长了文件大、分析难太短了又可能错过关键任务。目标明确才能让报告有说服力。3.2 录制操作的三个关键动作设置完成后点击Performance面板左上角的Record按钮实心圆点页面会进入录制模式。这时候操作页面操作完成后点击Stop性能报告就生成了一部分。但这里有一个很多人不知道的选项——录制时还可以打标记。在录制过程中随时按键盘上的CtrlMac上是⌘DevTools会在时间线上打一个黄色的标记点。我在实测中经常这么用录制开始后先停顿一秒让基线数据稳定然后标记一下再点击页面上我想测的按钮操作完再标记一下。这样结束后两个标记之间的那段数据就是一次独立交互的完整性能轨迹分析起来特别清晰。另一个关键动作是使用Start profiling and reload或者叫刷新录制来自动录制首屏加载。这个按钮通常在录制按钮旁边点击后会自动刷新页面、记录从加载到页面完全渲染的全过程是分析首屏性能的最快捷方式。注意这个功能会从页面加载的第一毫秒就开始记录正好覆盖了DNS解析、TCP连接、资源下载、HTML解析、脚本执行这一整条链路。录完stop之后报告会分为两个视图上面是汇总信息下面是可以展开的详细时间线。保存报告可以用左上角的保存按钮导出JSON方便发群里跟同事对线——性能报告在这你别说我冤枉你。加载报告直接拖JSON文件进面板即可不依赖原页面。3.3 分析时先看两条主线报告生成后我习惯先拉两个视图的数据出来一个是之前说的Overview一个是Main线程时间线。Overview看的是宏观FPS掉到多少、NET加载串行了多久、Timings上各个关键时间点相隔多远。Main线程看的是微观每一毫秒主线程在执行什么任务、每个任务的耗时多长、任务之间的依赖关系如何。用个不恰当但贴切的比喻Overview像医院体检报告的总检结论告诉你哪个器官指标异常Main线程像详细的影像报告告诉你哪块组织的哪个位置出了什么问题。只看总检结论会漏掉细节只看影像看不懂全貌两个结合起来才是完整的诊断。4. 火焰图、Main线程与三种视图内行到底怎么看如果你只记住Performance面板里的一个东西那必须是Main线程的火焰图。这是整个面板信息量最大、也最能体现功力的地方。但信息量大不代表难懂只要搞清楚它的组织和阅读规则你就能像读代码一样读性能数据。4.1 火焰图的两种方向从栈底到栈顶火焰图是一种堆栈可视化方式横轴是时间纵轴是调用栈深度。在Performance面板里Main线程的时间线本质上就是一张横向的火焰图——越靠上的色块代表越深的调用栈一个色块被上方另一个色块完全覆盖说明后者调用了前者。这里我建议新手先用自顶向下的方式看从最上层的任务开始比如Event: scroll或者Function Call往下展开它调用了什么函数再展开那些函数又调用了什么。这种方式跟代码执行顺序一致容易理解。当你已经做了几轮优化需要找具体函数的耗时占比时再切换到自底向上——它专门统计每个函数被调用了多少次、累计耗时多少直接列出消耗最大的那几个函数省得自己一层层翻。Chrome DevTools现在提供了两种火焰图折叠方式面板左上角的Activity下拉菜单可以切换。日常分析大多数情况下用默认的Flame Chart火焰图展示执行栈的完整嵌套关系如果你只想看每个函数自己执行花了多久不关心调用关系切换到Bottom-Up自底向上视图更直观。4.2 Main线程里的颜色代码Main线程时间线上的色块是有标准配色的掌握了配色你一眼就能判断页面在干什么颜色含义常见触发方式黄色Scripting脚本执行JS函数调用、定时器、事件回调紫色Rendering渲染样式计算、布局、更新图层树绿色Painting绘制绘制位图、生成显示列表蓝色Loading加载解析HTML、加载资源灰色Other其他任务间空隙、内部开销深绿GPU图形处理纹理上传、GPU绘制你一定遇到过这种情况滚动页面卡顿打开Performance录了一段发现Main线程上有一长串紫色的块展开一看全是Recalculate Style和Layout。这两个是Rendering阶段最经典的耗时大户几乎每一个样式属性变化都可能触发它们。比如你用JS改了元素的transform属性浏览器不一定重新布局但一定会重新计算样式你改了元素的宽度布局大概率跑不掉。这里要补一个前端性能的经典细节强制同步布局Forced Synchronous Layout。当你在JS里读取一个需要实时计算的样式属性比如offsetHeight、offsetWidth、getBoundingClientRect()时如果此时浏览器恰好有需要重新布局的变更还没执行浏览器就只能立刻停下来先做一次布局这一次布局就是同步的会卡住主线程。在火焰图上它的典型特征是在Scripting的黄色块里突然夹着一个深紫色的Layout块。遇到这种情况优化方向就是避免在读取样式前修改DOM把读操作和写操作分开批次处理。4.3 Call Tree、Event Log和Bottom-Up三个视图怎么配合点击Main线程时间线上的任意一个任务底部会弹出三类详细视图Call Tree调用树、Event Log事件日志、Bottom-Up自底向上。我自己的使用习惯是先把任务选中后切到Call Tree看当前的函数调用链从上往下找哪个子调用最耗时确定瓶颈是哪个函数然后切到Event Log按耗时排序把耗时超过100ms的长任务挑出来列为怀疑对象最后用Bottom-Up按函数聚合耗时把最耗时的几个函数名记下来去代码里搜索定位行号。Call Tree和Bottom-Up的区别值得多说一句。Call Tree是跟随一个任务内部的调用链展开它保留父子关系适合分析单次任务。Bottom-Up是把所有任务里的同一个函数聚在一起累加耗时不管它被谁调用、何时调用只看总量。比如你要回答updateList这个函数一共让我卡了多少毫秒用Bottom-Up最合适你要回答点击按钮后从handleClick到render的路径上哪里最慢用Call Tree最合适。4.4 颜色越深的块不等于越需要优化新手容易犯的一个错误看到火焰图里某个函数块很大很显眼就急着去优化它。我的经验是先看这个块属于什么颜色、在调用的哪个层级。如果一块黄色下方还有非常密集的紫色块那这个函数的大部分耗时就出在布局上——你光扶着它改JS不够还得改样式和DOM操作方式。另外一个容易误判的点是空档。火焰图如果用极慢的CPU降速来录制你会看到大段的灰色时间块那不代表浏览器在偷懒那是在等待外部资源返回。网络加载期间主线程是空的如果Net概览区那个时刻有请求在等那就是网络瓶颈不是JS问题。用Performance测性能分清等待和执行至关重要这直接决定了优化方向是压缩资源还是优化逻辑。5. 顺手把这三个性能问题拍死在沙滩上光说理论不实践就是耍流氓。下面我用三个最常见的卡顿场景把Performance面板的实战用法过一遍。这三个场景覆盖了前端性能优化里至少70%的日常问题。5.1 场景一滚动卡成幻灯片怎么确认是渲染层问题现象页面滚动时FPS掉到20左右而且CPU曲线跟着起伏。录一段滚动操作的Performance报告我通常这样分析先看Main线程上的色块构成。如果大部分是紫色和绿色Rendering Painting说明瓶颈在渲染和绘制重点检查有没有在滚动过程中频繁触发布局和重绘的属性。继续点开这些紫色块看具体是Recalculate Style还是Layout。如果是Layout再往下看布局操作集中在哪个盒子——往往是某个元素的宽度变化引发了整个文档的Re-layout。经典问题就在这里如果滚动中在改变width、height、top、left这些属性浏览器要做完整的布局计算改用transform之后元素会进入合成层不再触发布局和绘制滚动顺滑度立刻上一个大台阶。这就是为什么现在动画性能优化的铁律是能用transform就用transform能用opacity就用opacity——这两个属性可以走合成器不占用主线程。在Performance面板里验证优化效果也非常直观优化前录一段Main线程上紫色和绿色连成一片优化后再录一段同样的滚动操作Main线程上的紫色块明显变少甚至大部分时间都是空闲的灰色。这种前后对比比任何嘴上说服都有力。注意给元素加will-change: transform可以把元素提升到合成层但千万别到处乱加。每个合成层都会占用GPU内存合成层太多移动端直接卡出天际。我见过有同事给页面上三十个元素都加will-change结果手机上滚动更卡了。合成层不是越多越好它是贵的可用资源。5.2 场景二点击按钮后页面卡住100ms怎么定位到具体函数现象点击某个按钮后界面肉眼可见地顿了一下大约100ms左右没有响应。录制操作时记得在点击前后各打一次标记。停止录制后找到两个标记之间的时间段在Main线程上找那个时间范围内的长任务Main线程里单个任务超过50ms就是长任务。选中这个长任务切到Call Tree视图往下展开调用链找到耗时最重的子调用。这里有个特别实用的技巧在Call Tree视图里勾选右上角的Angular、React之类的框架支持滤镜如果有的话面板会帮你过滤掉框架内部函数的干扰直接定位到你写的业务代码上。比如用React框架一长串调用栈里全是updateFunctionComponent那一类名称看着头大。开了代码拆包后很多构建工具会在函数名后面带上源文件路径信息你可以直接从Call Tree的节点名上找到src/components/xxx.tsx这种信息比在压缩后的生产代码里搜函数名快得多。找到瓶颈函数后怎么读一个函数的耗时等于它内部所有子调用的耗时之和再加上它自身的执行开销。如果这个函数下面挂着一大堆子调用那先用Call Tree看哪个子调用最耗时如果这个函数没什么子调用但本身耗时很长那问题大概率是死循环、大对象遍历、或者频繁的DOM读写。5.3 场景三首屏加载白屏时间长怎么判断瓶颈在资源还是渲染首屏慢是性能优化的重点也是Performance面板最能发挥作用的场景。用Start profiling and reload录制一次完整加载然后看三个地方第一步看Timings。FP跟FCP的间隔如果很大说明是渲染管线卡住了——浏览器收到HTML资源了但迟迟画不出来第一帧。FCP到LCP的间隔大则通常是图片、字体或者大块文本内容加载太慢。第二步看Network部分哪个资源耗时最离谱。第三步看Main线程。这里我想强调一个经验首屏优化先看网络再看渲染最后才看JS。因为首屏阶段主线程大部分时间都在等资源加载真正的脚本执行往往靠后。很多团队一优化首屏就开始压缩JS代码量但如果Network里图片资源占了两秒你压缩JS根本没用。Performance面板的价值就是帮你用数据说清楚这两秒到底花在哪个环节上了。遇到Network里某个请求耗时特别长先看它是不是在瀑布流的最后一个看它的排队时间Queueing、下载时间Content Download和等待时间Waiting/ TTFB。排队时间长的多半是连接数达到浏览器上限了TTFB长的问题在服务端下载时间长的才是资源本身太大。这个区分非常重要因为前两个问题你压缩资源没用得调服务器和网络优化。6. 录帧率、看长任务、用新API进阶操作三板斧基础流程跑通之后再补三个进阶技巧。它们不是Performance面板的隐藏功能而是围绕它构建的周边能力。用好了你的分析效率会再上一个台阶。6.1 Rendering面板里抓FPS和渲染遍数很多人不知道Chrome DevTools里除了Performance面板还有一个专门看实时渲染性能的Rendering面板。按CtrlShiftP打开命令菜单输入Rendering就能开启它。Rendering面板里最有用的两个开关是Frame Rendering Stats在页面左上角显示实时的FPS和渲染帧耗时。这个比Performance面板更适合边操作边观察——比如你一边滚动页面一边盯着左上角的FPS数字变化能立刻感知到哪个滚动位置卡顿最严重。Paint flashing开启后页面上所有正在被浏览器绘制重绘的区域会闪烁绿色高亮。如果开启这个开关后你发现整个页面都在疯狂闪烁说明页面在频繁、大范围地重绘优化方向就是减少重绘面积、缩小绘制区域。Rendering面板适合做探查——快速确定问题大概在哪。Performance面板适合做确诊——精确分析到底哪一行代码导致的卡顿。两者配合效率远超只用其中一个。6.2 Long Tasks和用户感知为什么50ms是分界线Performance面板分析长任务有一个前提概念什么是长任务。所有超过50ms的连续任务都算Long Task。这个50ms是有讲究的——浏览器的目标是在16.6ms内渲染一帧但当一帧中有多个任务时前一个任务不能阻塞后续任务的开始。研究发现如果单个任务超过50ms用户就能明显感知到页面卡顿。在使用Performance面板时我几乎每次都会主动找超过50ms的任务段来重点分析用Call Tree拆解开看内部到底在做什么。注意我这里说的Long Tasks不是一个泛泛的概念Chrome有一个PerformanceObserver的API可以直接监听长任务const observer new PerformanceObserver((list) { for (const entry of list.getEntries()) { // entry.duration 就是这个长任务的耗时 console.log(长任务耗时: ${entry.duration}ms); } }); observer.observe({ entryTypes: [longtask] });这个API在生产环境非常实用。用户说页面卡但你本地复现不了就可以在线上埋点统计长任务的分布情况结合用户设备信息定位是哪些代码在高负载设备上触发了长任务。Performance面板是你在开发环境看的PerformanceObserver是你在生产环境收集的一里一外才能形成完整的性能监控闭环。6.3 用Performance面板顺便读懂浏览器的加载时序第一张性能报告你可能只会用来看哪里慢但多看几张之后你会发现它其实是浏览器工作机制的绝佳教学材料。每次录首屏加载你都能清楚地看到HTML解析器ParserHTML解析了多少个节点中间穿插了多少次脚本执行脚本执行Evaluate Script在解析过程中为什么会阻塞后面的HTML解析样式计算Recalculate Style在什么时机触发和布局Layout有什么关系图片解码和纹理上传Decode Image、GPU Upload是在绘制阶段之前还是之后。这些知识点如果不看Performance面板光靠读文档永远只能记个概念。但你在面板上亲眼见到这段脚本执行的时候下方的HTML解析完全停滞了就会真正理解为什么推荐defer和async、为什么要控制脚本在head里的数量、为什么要做代码分割。我经常跟团队新人说想搞懂浏览器渲染原理别光听我讲自己去Performance面板录三段一段普通页面加载、一段带大量同步脚本的页面加载、一段有大量图片的页面加载。对照着看三份报告你对浏览器工作机制的理解会超过很多写了三年代码但没录过性能报告的人。7. 避坑手册这些细节不说你可能一直踩写到这里最后分享几个我在实际工作中踩过、也看别人反复踩的坑。这些细节通常不会出现在官方文档的醒目位置但对分析结果影响巨大。坑一在普通窗口录制没关插件。这句话我已经强调过一次这里再强调一次因为太重要了。有些扩展会在每个页面注入脚本导致你的性能报告里出现大量跟业务无关的脚本执行时间这会直接污染你的分析结果。特别是广告拦截类和密码管理类扩展它们的工作机制就是在每个页面跑注入脚本。不关插件的录制结果要么浪费时间排查根本不存在的瓶颈要么影响你判断真实的问题定位。坑二不看设备和网络限流设置得出没问题的结论。开发者经常犯一个错在MacBook Pro上万毫秒的动画丝滑般流畅就断言性能没问题。但你用户用的是几年前的中端安卓手机性能差距可以达到5-10倍。在Performance面板的录制设置里我建议至少测一轮CPU 4x降速的情况。我自己做移动端页面优化时有个习惯优化前的报告和优化后的报告必须在相同的CPU/网络降速条件下录制否则前后的数据没有任何可比性。坑三录制时间太长文件巨大分析体验极差。有次我同事录了一分半钟的页面操作导出的JSON接近200MBDevTools打开后卡了半分钟才渲染出报告。录制时间控制在10秒以内是个好习惯除非你在做特定长时间场景的测试。更聪明的做法是把一次操作拆成多次录制比如首屏加载录一次点击弹窗录一次滚动列表录一次。这样每份报告都聚焦单一场景分析起来快得多。坑四忽略Session之外的浏览器主线程活动。Performance面板默认记录的当前页面在录制期间的活动但浏览器主线程还承担着其他任务其他标签页的定时器、后台任务的GC、扩展程序的服务工作线程等。某些情况下你的页面不卡但整体浏览器卡打开面板看CAO曲线跑满了全是Other类型的任务。这不代表你的页面有问题而是浏览器整体负载过高。遇到这种情况我一般会先关掉其他所有标签页再重新录一次排除干扰。对比两次报告能帮你判断问题是页面的还是环境的。坑五生产环境代码压缩过函数名全是单字母分析困难。这是线上问题排查时最头大的场景。用Source Map可以解决——确保线上环境上传了Source Map文件DevTools会自动把压缩后的调用栈映射回原始源码。这里要注意安全问题Source Map会暴露源码所以生产环境的Source Map要么只对内网可见要么在需要分析时临时开启分析完立即关闭。我见过很多团队图省事不上Source Map结果线上问题根本没法用Performance面板定位只能靠猜效率极低。坑六把Performance面板当唯一工具忽视了浏览器之外的性能因素。Performance面板主战场是浏览器渲染和前端执行层它记录不了服务端响应和CDN节点断开这种问题。如果你看到TTFB速度正常但Content Download异常缓慢那是网络传输链路的问题如果FCP慢但Main线程上明显有空闲那是资源调度和网络水线问题。这类问题你要用Network面板配合Chrome的Performance Insights或者直接找网络工具去排查。工具各有边界别指望一把扳手解决所有螺丝。最后一个建议建一份自己的性能基线数据。我负责的项目里有一个固定的做法每次发版前在同样的测试环境、同样的限流条件下用Performance面板录一段核心路径首屏加载 一次关键交互的报告把核心指标记录成一个基准表。版本迭代后对比新的报告和基准表大于10%的退化直接打回。这种做法让性能优化从一次性的急救变成了日常的质量门禁比什么强势宣导都管用。Performance面板就是个仪表盘你的车况好不好它一目了然。引擎逻辑哪条线最重、哪个环节最占时间、哪个函数导致的油耗最高事实都摆在时间线上骗不了人。多用几次你对页面为什么卡的判断会从玄学变成科学。这个转变比学再多的优化技巧都值钱。
返回列表