一名优秀的Web前端开发工程师的生存攻略

前端下午茶

共 14293字,需浏览 29分钟

 ·

2023-06-12 13:13

作者:氢灵子

原文:https://juejin.cn/post/7214512376669372453

虽然从毕业到现在,我只工作了 3、4 年,但我什么都做:前端 Web、移动端 Android、后端 .NET,甚至还有嵌入式。但我最喜欢的还是 Web 前端,我喜欢图形、动画、交互,喜欢 HTML、CSS 和 Javascript 赋予的快速呈现的能力。我喜欢 Web 前端能够让我自己实现自己的需求,喜欢 Web 前端更加靠近视觉、艺术方面的能力,方便我做一些自己喜欢的动画、游戏等等。

我自认为自己在 Web 前端还有点研究,从最初的原生 HTML、CSS、Javascript,到框架 React、Vue、Angular,到绘图技术 Canvas、SVG,到后端接壤 Node 等。我在工作时也很开心,编写网页并不会让我感到疲劳。但最近的一些事情和现实情况,却让我怀疑,我现在做得事情是否有价值。

一是个人的成长速度放缓。工作中需要的技能,基本上我已具备,一般的工作对我来说没有任何问题。但我只是做一些大部分 Web 前端工程师都能做得工作:调用接口、呈现数据、填写表单、发送请求。少数让我觉得兴奋之一的工作是数据可视化,但比较少。

二是市场上出现了大量“前端已死”的声音。由于经济下行,很多公司裁员。而 Web 前端因为门槛低,容易被替代,大量 Web 前端程序员失业。所以我想,虽然我目前在公司没有被裁的风险,但其实不可替代性很低,日后万一有风吹草动,我会不会是最先被裁撤的。

三是 AI 技术的爆发发展。GPT 等模型的出现,使得 AI 代替人担任某些岗位似乎成为了可能,GPT-4 更是能够从设计图直接生成网页代码。很多人对自己的岗位是否会被替代而带有,我也无法免俗。虽然我认为 Web 前端的上限很高,但并不是所有公司都需要那么尖端的 Web 前端技术。如果真到了 AI 替代人类的那一天,我将何去何从。

以上是我最近的一些担忧,它们让我思考:

  • Web 前端的价值是什么?
  • 我是一个合格的 Web 前端工程师吗?
  • 如果我不再从事 Web 前端,那么我能从中汲取什么,并带到新的领域中?

我想搞清楚这些问题,因此我进行了一些思考和总结,写了一些文章。

我喜欢 Web 前端,热爱编程。即使有一天我不得不放弃做一名 Web 前端工程师,我希望我离开是因为环境容不下我,而不是因为我不是一个合格的 Web 前端工程师。我希望但市场不再需要 Web 前端工程师的时候,在这个领域学到的东西,能让我更好的进入另外一个领域。

就像 JQuery,使用率不断下降,但它的思想引领了一个时代的编程方法,潜移默化地影响了 Web 标准。它并不是被淘汰,而是功成身退。

Web 前端工程师是什么

Web 前端工程师是什么?通俗的来说,是编写网页的人。

但在成为 Web 前端工程师之前,先得是一个工程师,再是一个软件工程师,然后是 Web 前端工程师。

工程师

维基百科这么定义工程师:工程师是指那些在工程专业领域的人,他们使用科学知识来驾驭技术以解决实际问题,并以此为职业[1]。

工程通常是用于实现某个需求的一系列工作,而“问题”一词很好地揭示了工程师的本质。因为通常来说,工程不是容易完成的,常伴随着一系列问题。此时就需要工程师在有限的资源下,想尽办法来解决问题,完成工程。

因此,通俗的说,工程师是解决问题的人

软件工程师

承袭上面的定义,可以推出软件工程师是实现软件工程的人,通俗的来说,软件工程师是解决软件领域问题的人

在传统项目(比如土木工程)中,工程师通常不是工程的具体操作人(真正操作人是建筑工人),而是设计师和规划者。在软件领域,软件工程也可以分为工程师和程序员,即由软件工程师来理解需求、构建框架、定义系统,由程序员来做具体编程的工作。在大型项目中,可能确实如此。但因为软件领域的体量轻,需要的固定资源少,特别是对于互联网软件行业,一家公司可能不会由很多人,通常是以小团队为单位进行软件开发。因此,在这些项目和团队中,不会区分工程师和程序员,即软件的设计人员和编程人员是同一个。

同时,对于这个世代的程序员来说,交叉工种和学科的能力几乎是不可或缺的。一个程序员也必须学会工程、系统等知识,才能更好的发展。因此本文不区分软件工程师和程序员。

软件,既是软件工程师的目标,也是软件工程师的手段。因此,为了完成软件而必须的编程能力、系统知识、思想方法,是软件工程师的核心技能。

Web 前端工程师

Web 前端工程师是软件工程师的一种。传统意义的 Web 通常是指运行在浏览器(如 Chrome)上的软件,这种软件的特点是:

  • 资源从服务器获取
  • 运行在一个沙箱中
  • 渲染依托于浏览器而不是直接使用操作系统的 API

这些特点使得 Web 有诸多限制,比如必须在有网络的环境下运行、不能访问本地文件等,但也造就了它天生的最大优势:跨平台。只要是有浏览器的地方,就能运行网页。早年可能还存在浏览器之间差异的问题,但随着 Blink 和 Webkit 几乎统治了浏览器市场以及 IE 的入土,Web 标准化(W3C)越来越深入人心(至少目前是这样的)。所以前端工程师大部分时间只需要把重点放在浏览器上,相较于其它软件(比如移动端),系统底层差异造成的麻烦就小得多。在非桌面端,也出现了 Hybrid 和 Electron 等跨平台的开发方式。

所以,Web 前端开发工程师是根据 Web 标准,用运行在浏览器中的软件,来解决问题的人

前端工程师

至此,得到了一个 Web 前端工程师的通俗说法。

现在把概念扩大一点,把 Web 拿掉,什么是前端工程师呢?这里的“前端”是相对于后端服务器而言的,从前不区分前后端,一个请求从浏览器出发,到后台服务器,到数据返回到浏览器,都由后端程序完成。但是随着需求的增长,Web 页面的复杂度增加,以及浏览器性能的提升促使单页面应用(SPA)的出现,后端程序员快忙不过来了。于是出现了前后端分离,当然前后端分离的好处[2]不单单是为后端程序员减轻负荷,但这不是本片文章的讨论范围,因此不予叙述。

随着前端的发展,对前端工程师的要求也越来越高,出现了更多对前端工程师的技能要求。也就是说,相较于后端,前端工程师的技术和思想开始越来越区别于后端。主要体现在:

  • 良好的美术审美和用户交互体验
  • 不同设备显示方式的兼容(桌面,平板,手机)
  • 数据可感知(数据可视化,音视频播放)

从这些角度来讲,开发桌面端、移动端和嵌入式段软件的工程师,应该也属于前端工程师,而且目前的趋势也正是朝着这个方向前进,出现了很多跨平台的工具,比如 Flutter 和 Reactive Native。也就是说,直接与用户打交道的界面,都可能是前端工程师的工作

从内容上来看,现在的前端已不再是简单的文字和图片,也不仅仅是音视频等各种媒体,而是朝着多维度的可交互方向发展,比如游戏、VR、网页端的复杂应用(比如 Office)、3D 等等。

Web 前端工程师的作用

Web 前端工程师的工作内容是编写网页。从工程的角度来讲,这项工作包括:

  1. 理解需求,构建系统框架
  2. 整理系统需要的资源(比如 UI 资源、接口资源、部署资源)
  3. 编写程序源代码,将代码转译或编译成浏览器可用的程序
  4. 保证程序在浏览器的兼容性和性能要求
  5. 将网页程序部署到服务器
  6. 监控并收集日志,优化网页、修复错误

前端不断发展,对工程师的要求也越来越高。最近 10 年兴起的前端工程化潮流,使得 Web 编程越来越成熟和完善,各种工具和框架层出不穷,方兴未艾。因此,Web 前端工程师不能只满足于输出网页,也要关心自己用于开发网页的工具。也也就是老话说的:工欲善其事,必先利其器。包括但不限于:

  • 源代码转编译和打包工具(比如 Webpack)
  • Web 标准与浏览器兼容性插件(比如 Babel)
  • 代码编辑器和相关插件(比如 VSCode)
  • 浏览器和相关插件
  • 网页程序部署服务器(比如 Nginx)

分析需求可行性和开发资源

Web 前端工程师需要理解需求,当然理解需求不是前端工程师一个人的工作,一起工作的还有产品经理和其它程序员等。而前端程序员在这个步骤中,很重要的一个作用是判断需求的可行性,即判断一个功能点能否在浏览器中实现,能否满足性能要求

这一点对于产品和项目都很重要。如果某个功能无法实现,那么产品经理就需要考虑是否要修改或放弃这个功能,或者另想办法,绕个弯间接地实现功能。如果功能可以实现,但是需要很大的研发投入或开发时间,那么项目经理就需要把这一风险好好考虑。

如果需求可以实现,那么就需要评估完成需求需要的时间,指出实现需求必须的资源,然后进一步与具体工作的同事沟通。如果需求实现存在风险,那么应及时提出,以方便项目经理调整安排,或者与同事商量以探索可能的解决方案。

为了做好这一点,要求 Web 前端工程师有这些能力:

  • 沟通技巧:抓住重点,提炼要点,倾听对方的需求,提出自己的需求。
  • 跟随 Web 标准的发展,学习新知识和技术。
  • 全面了解浏览器的功能,认识浏览器能做的和不能做的,以及浏览器能够达到的极限。
  • 了解浏览器在不同环境下的局限(比如在手机中的浏览器可能有性能和网速的问题)。
  • 抽象需求为代码结构,将现实和 UI 领域的概念转换为编程领域的概念。能够下意识地想到需求应该怎样实现,有哪些既有地方案和已存的代码可以参考。

产出实现需求、性能优秀且对用户友好的网页

Web 前端工程师的产出,一般来说包括以下:

  • 单页面应用:页面内容由运行时 Javascript 生成且自己管理状态,数据从后台获取。
  • 服务端渲染应用:页面内容由服务器直接生成,随着文档一起发送到浏览器,通常是为 SEO[3] 设计。
  • 渐进式网页应用(Progressive Web Application,PWA[4]):常驻在浏览器中,可以离线使用的应用。

如果推广至前端工程师,那么桌面端 GUI 软件和移动端应用可能也是前端工程师的工作。这些软件对于前端工程师,通常是用基于 Web 的跨平台构建工具实现,比如:Electron 和 Webview。当然也可以使用自成一派的工具,比如 Flutter。

实现功能、减少错误,是对网页最基本的要求,然后再谈性能和体验的问题。

性能

网页的性能主要是指网页浏览时的流畅性,包括:

  • 从网页跳转到显示主要内容的时间短。
  • 用户点击或其它交互后网页做出反应的时间短。
  • 网页内容发生变化时不突变(即通俗来说不卡顿)。

这些指标的详细研究,可以参考谷歌的 Web 开发网站[1]。

要做到这些,需要工程师对可能消耗大量时间的代码和操作有所意识,想办法减少冗余操作,提高效率。通常来说,算力密集的工作通常由后台服务器来完成,但随 Web Application 的发展,越来越多的产品将 Web 视作一个可以独立完成工作的平台,这对 Web 前端工程师带来了更多的挑战。

可用的方法有:

  • 使用浏览器开发工具[5],检查性能消耗大的代码并优化。
  • 缓存体积大的数据(存放在内存、LocalStorage 和 IndexDB 等)。
  • 使用 Web Worker,并发运行高消耗的程序。
  • 降低资源文件体积,减少打包冗余。

体验

网页是给人浏览的界面,因此网页的操作方法应符合人的认知逻辑,风格应符合人的审美(艺术创新除外),交互方式应尊重人的感受

为了达到这些要求,网页需要做到:

  • 页面需要一定的焦点控制,即应该突出重点部分,同时引导用户的焦点在不同部分将流转,有所取舍,不能过于复杂。
  • 用户进行的一切操作(比如点击、悬浮、滚动、加载等),都应有所反馈,反馈的方式包括但不限于:正常的流程、通知、样式变化等。
  • 大面积的内容变化(比如弹出框),应有动画进行过渡。
  • 页面重复出现的元素,有相同的含义且始终保持一致。
  • 保存用户当前的操作状态,页面跳转返回或进行其它变更状态的操作时,应当保存的状态(比如列表位置、表单填写)可以自动重现。

Web 前端工程师虽然属于程序员,更多地是理想思维,但是应该向 UI 设计师看齐,具有一定的审美水平和设计思维,了解基本的的色彩、构图等。这一方面的知识,可以参考《写给大家看的设计书》[6]。

更进一步说,前端工程师可以学习初步的 UI/UX 设计师常用的软件(比如 Photoshop、Figma 等),以更好的控制美术资源。

编写良好的代码和网页的持续优化

在实现了需求之后,工程师就需要关心代码在功能和性能以外的属性。在这些方面,良好的代码应具有以下特点:

  • 良好的可读性:为了与同事交流,以及日后自己能看懂。
  • 可扩展和易修改:为了应对 Web 快速变化的需求。

这里的表述是从实际工作中的编程习惯和多人协作出发,而不是传统意义上的代码规范和设计模式。关于良好的代码规范和设计模式,有很多书籍可以参考,比如《设计模式:可复用面向对象软件的基础》[7]和《重构》[8]。因为内容非常多,这里就不展开了。

编写网页不是一蹴而就的事情,即使在网页已经发布了之后,还有很多的甚至是更多的工作要做:

  • 修复用户报告或主动检测到的错误
  • 优化网页的性能
  • 改善代码结构
  • 升级技术栈

搭建基础设施

虽然编写网页需要的工具不多,一台电脑就行。但是为了更高效的工作,Web 前端工程师需要一些基础设施,如同现实中的高速公路一样,有了它才能把货物运往各地。

为了高效的工作,软件工程师想到了很多方法。别忘了软件既是目的,也是手段。

框架

现代的 Web 应用通常不会从 0 开始写 Javascript,而是采用框架和工具(比如 React、Vue、Angular 等)。这些工具大大提高了工作效率,但在这些框架之上,Web 前端工程师还需要一套基于公司和自己业务的框架。这套框架在 React、Vue 或 Angular 的基础上,添加了常用的 UI 组建库,包含了业务常用的代码或库,以及适用于业务的打包和部署代码。这么做的目的,是为了省下重复的搭建项目和打包部署的时间。有些公司的业务可能需要 Web 前端工程师随着工作的推进不断的创建项目,如果此时能够“一键”生成出上述的内容,那么将会省下很多时间,同时也可以不重复之前犯过的错误和踩过的坑。

这样一个框架,也可以说是一份模板,把它放在 Git 仓库中,使用时 fork。或者放在私有 NPM 仓库中,利用npm init <executor>命令[9]进行创建。

CI/CD

Web 通常是需要经常更新的,把新修改的代码打包的文件放到服务器上,也就是部署。举例来说,一般的更新过程如下:

  1. 修改代码
  2. 打包代码
  3. 转移代码到服务器
  4. 重启服务器

以前,2、3、4 步都是手动完成的,也就是在开发者电脑上打包,手动复制到服务器,手动输入命令重启服务器。这样做不仅繁琐,还容易出错。因此,持续继承/持续部署(Continuous Integration/Continuous Deployment,CI/CD)[10]出现了。它把打包代码到重启服务器的步骤自动化,且都在服务器上完成,开发者需要做的只是推送代码。

这一部分的工作通常还需要运维工程师的帮忙,但作为一个软件工程师,这一部分的只是需要了解,最好能亲手试试。

私有 NPM

如前面提到的,Web 前端工程师经常需要在不同的工程间共享代码。一种方法是使用 Git 子模块(Submodule),即在一个 Git 仓库中存放一个子仓库,子仓库使用自己的 Git 管理,与本仓库独立。但是这种方法其实不太适合大规模的代码共享,因为需要协调各个项目之间的版本关系,而 Git 其实不擅长这个事情。更通用的是使用 NPM,如果公司有安全性的考虑,可以在公司的内网搭建私有的 NPM 服务器。

关于创建和上传 NPM 包,可以参考NPM 官方文档[2]。

监控系统

即使是顶级的 Web 前端工程师,写的网页也难免有错误和性能问题,这些在开发时难以察觉的问题或疏忽,在实际用户各种各样的环境中就有可能出现。因此 Web 前端工程师需要从用户端收集日志,内容包括:

  • 页面错误信息
  • 性能信息(加载时间、首屏渲染时间、接口延迟时间等)
  • 接口调用信息
  • 页面运行环境(设备、浏览器、网络情况等)
  • 用户信息

这些日志不仅能在用户报告了错误后,对错误进行分析调试,也可以对性能差的页面,针对性的进行优化。

这一套系统包含两个方面,运行在用户端浏览器的监控程序,和运行在服务器的收集分析程序。市场上有成熟的解决方案,比如阿里云 ARMS,也可以自己搭建。比如在前端编写收集信息的程序[11]后,在后台使用免费的 Elasticsearch + Logstash + Kibana[12]方案,或者 Loki + Grafana[13]方案。

Web 前端工程师的工具包

工欲善其事,必先利其器。作为一个工程师,Web 前端开发者需要很多的工具,最好是自己熟悉和常用的,同时可以自己配置从而最适合自己的。这样一套工具组成一个环境,让工程师在工作室随手可用。

代码编辑器

开发网页需要的软件工具不多,一个代码编辑器和一个浏览器就足够。但是随着 Web 前端内容形式和编程方式的发展,以及为了更高效地工作,一个好的代码编辑器往往可以达到事半功倍的效果。

每个程序员都有自己喜欢的编辑器,但是为了达到上述“适合自己”和“随手可用”的效果,编辑器最好可以安装插件和同步配置。

以 VSCode 为例,它可以安装各种插件,从语言 Lint、调试工具、代码美化、资源预览等一应俱全,同时它支持登陆 Github 或 Microsoft 账号,以在不同设备间同步插件和设置。这样就满足了程序员在不同的工作环境中都能用自己最舒适的编辑器编程的需求。

如果有的功能代码编辑器没有实现,也没有现成的插件,可以自己尝试编写插件[14]。

浏览器扩展

Web 前端工程师在调试网页时,可用的方法有断点调试和控制台日志输出,除此以外还可以借助浏览器扩展。

现代的 Web 开发框架(React、Vue、Angular)等都提供了浏览器扩展,用于显示当前页面中组件的状态、成员变量值、路由信息等,非常直观。有些工具还可以实时设置变量的值,而页面也能立即反应变化,很方便。

除了框架,一些知名库,也提供了开发扩展,比如 Three.js。在移动端,如果没有扩展,可以依靠如 vConsole[16] 这样的 NPM 库,在移动端模拟如桌面浏览器那样的开发控制台。

同样的,如果现成的扩展不能满足要求,也可以自己开发。

个人笔记

Web 前端是一个交叉学科的领域,涉及的知识面非常广。即使一个人的记忆力再好,也总有突然之间想不起某个知识点的情况。特别是在现在技术飞速发展的年代,知道一个东西比记得它的详细内容更重要。因为我们可以将细节记录在笔记中,需要时查询即可。

比如,NPM 有很多有用的库,程序员可以给用过且好用的库打个标签,记下笔记。需要时,查询笔记,使用相应的库即可。

有很多软件可以记录笔记,比如印象笔记和有道云笔记,它们的免费功能就已经够用了。如果觉得放在厂商的服务器上不安全(厂商有跑路的风险),那么也可以记在自己的电脑上,然后用 Git 同步到远程仓库,当在公司工作时,就可以在网页上浏览笔记。

更进一步说,既然我们是 Web 前端工程师,我们可以自己开发一个网页,存放在比如 OSS 的地方,满足我们对笔记的浏览和编辑等要求。

参考资料

[1] Wikipedia,工程师[3]

[2] 知网,Web 项目前后端分离的设计与实现[4]

[3] wikipedia,SEO[5]

[4] web.dev,PWA[6]

[5] Chrome,Devtools Performance[7]

[6] 豆瓣,写给大家看的设计书[8]

[7] 豆瓣,设计模式:可复用面向对象软件的基础[9]

[8] 豆瓣,重构[10]

[9] NPM,init[11]

[10] Github,CI/CD[12]

[11] 掘金,开发一个前端监控系统:错误上报、AJAX 监控、性能指标[13]

[12] Elastic,ELK[14]

[13] Grafana,Loki[15]

[14] VSCode,API[16]

[15] Chrome,Extensions[17]

[16] vConsole[18]

参考资料

[1]

https://web.dev/vitals/: https://link.juejin.cn?target=https%3A%2F%2Fweb.dev%2Fvitals%2F

[2]

https://docs.npmjs.com/: https://link.juejin.cn?target=https%3A%2F%2Fdocs.npmjs.com%2F

[3]

https://zh.wikipedia.org/wiki/%E5%B7%A5%E7%A8%8B%E5%B8%88: https://link.juejin.cn?target=https%3A%2F%2Fzh.wikipedia.org%2Fwiki%2F%25E5%25B7%25A5%25E7%25A8%258B%25E5%25B8%2588

[4]

https://kns.cnki.net/kcms2/article/abstract?v=3uoqIhG8C44YLTlOAiTRKibYlV5Vjs7i8oRR1PAr7RxjuAJk4dHXorePou3XcM7FPWoV2jZsjXuB3DxyrNmSXQPxBCxfcRMg&uniplatform=NZKPT: https://link.juejin.cn?target=https%3A%2F%2Fkns.cnki.net%2Fkcms2%2Farticle%2Fabstract%3Fv%3D3uoqIhG8C44YLTlOAiTRKibYlV5Vjs7i8oRR1PAr7RxjuAJk4dHXorePou3XcM7FPWoV2jZsjXuB3DxyrNmSXQPxBCxfcRMg%26uniplatform%3DNZKPT

[5]

https://zh.wikipedia.org/wiki/SEO: https://link.juejin.cn?target=https%3A%2F%2Fzh.wikipedia.org%2Fwiki%2FSEO

[6]

https://web.dev/learn/pwa/: https://link.juejin.cn?target=https%3A%2F%2Fweb.dev%2Flearn%2Fpwa%2F

[7]

https://developer.chrome.com/docs/devtools/performance/: https://link.juejin.cn?target=https%3A%2F%2Fdeveloper.chrome.com%2Fdocs%2Fdevtools%2Fperformance%2F

[8]

https://book.douban.com/subject/26657933/: https://link.juejin.cn?target=https%3A%2F%2Fbook.douban.com%2Fsubject%2F26657933%2F

[9]

https://book.douban.com/subject/34262305/: https://link.juejin.cn?target=https%3A%2F%2Fbook.douban.com%2Fsubject%2F34262305%2F

[10]

https://book.douban.com/subject/4262627/: https://link.juejin.cn?target=https%3A%2F%2Fbook.douban.com%2Fsubject%2F4262627%2F

[11]

https://docs.npmjs.com/cli/v9/commands/npm-init: https://link.juejin.cn?target=https%3A%2F%2Fdocs.npmjs.com%2Fcli%2Fv9%2Fcommands%2Fnpm-init

[12]

https://github.com/solutions/ci-cd/: https://link.juejin.cn?target=https%3A%2F%2Fgithub.com%2Fsolutions%2Fci-cd%2F

[13]

https://juejin.cn/post/6975324063476482056: https://juejin.cn/post/6975324063476482056

[14]

https://www.elastic.co/cn/what-is/elk-stack: https://link.juejin.cn?target=https%3A%2F%2Fwww.elastic.co%2Fcn%2Fwhat-is%2Felk-stack

[15]

https://grafana.com/oss/loki/: https://link.juejin.cn?target=https%3A%2F%2Fgrafana.com%2Foss%2Floki%2F

[16]

https://code.visualstudio.com/api: https://link.juejin.cn?target=https%3A%2F%2Fcode.visualstudio.com%2Fapi

[17]

https://developer.chrome.com/docs/extensions/: https://link.juejin.cn?target=https%3A%2F%2Fdeveloper.chrome.com%2Fdocs%2Fextensions%2F

[18]

https://github.com/Tencent/vConsole: https://link.juejin.cn?target=https%3A%2F%2Fgithub.com%2FTencent%2FvConsole

最后



如果你觉得这篇内容对你挺有启发,我想邀请你帮我个小忙:

  1. 点个「喜欢」或「在看」,让更多的人也能看到这篇内容

  2. 我组建了个氛围非常好的前端群,里面有很多前端小伙伴,欢迎加我微信「sherlocked_93」拉你加群,一起交流和学习

  3. 关注公众号「前端下午茶」,持续为你推送精选好文,也可以加我为好友,随时聊骚。



a55951af34938b9ab21bee1cf38c2220.webp点个喜欢支持我吧,在看就更好了


浏览 23
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报