05-面试讲解
# 网页复制成图片至剪贴板面试讲解
# 技术点图谱
涉及的技术点如下:
- Canvas
- Blob
- 剪贴板
# 亮点描述
模拟问题:我看到你写的项目亮点是“实现网页复制成图片到剪贴板”,剪贴板好像是Clipboard API就能实现的,为什么你认为能作为一个亮点呢?
问题分析
- 先介绍当时做这个事情的背景
- 描述这个和普通的方案(直接使用Clipboard API)有什么区别?会遇到什么样的问题?
- 你拿到这个问题你是如何思考的
- 你思考出来的落地方案
- 落地方案的效果
- 封装为了公共模块,发布到了 npm 上面
参考答案
老师,是这样的。这个乍眼一看确实好像用 Clipboard API 就能实现,但其实里面有需要特殊处理的地方。
当时产品经理特意提到了这个需求,需要像飞书一样,一键复制网页内容,以图片的形式放入到剪贴板里面。而 Clipboard API 大家平时在使用的时候,一般都是放文本内容到剪贴板里面,如何将网页内容快速转为图片,然后放到剪贴板里面,是这个需求背后要额外处理的点。(阐述和普通方案的区别)
我当时拿到这个需求后,对整个需求进行了功能拆解,考虑先将网页内容转为 Canvas,然后再将 Canvas 图像转为 Blob 数据放入到剪贴板。整体的处理流程差不多是这样的,但是里面也涉及到一些细枝末节的地方需要处理。(钩子🪝)
最后整个模块的代码写好后,为了方便以后使用,我还将其打包发不到了 npm 上面。
所以对于其他人来讲不知道感受如何,但对于我自己来讲,这是我通过这个项目所沉淀下来的一个东西,因此在简历里面我也把它作为了我的项目亮点。(最后解释为什么作为项目亮点)
# 技术点讲解
# 1. Canvas
模拟问题:我听你刚才说,将网页内容转为 Canvas,这一块儿具体是怎么做的呢?
问题分析
问你怎么做的时候,千万不要只回答用 html2canvas 库就行了。
应该回答网页转为 canvas 需要做哪些工作,最后再说通过一个现成的库可以直接搞定。
- 介绍详细的转换步骤(说个几个步骤就行了...)
- 介绍如果你来写,你的模块设置
- 介绍 html2canvas
- 设置钩子
参考答案
要将网页内容转换为 Canvas,这不是一个简单的工作,这里涉及到要对整棵 DOM 树的解析,以及样式计算等工作,还包含各种各样的细节,比如:
- 如何处理叠加效果
- 如何处理字体
- 处理滚动和视口
- 递归绘制子元素
- ....
这一块儿如果对浏览器的渲染原理没有十足的了解的话,做起来会遇到各种各样的坑。我因为对浏览器的整个渲染原理是比较清晰的,所以这一块儿的一个大致流程,我心里还是有数的。如果让我来设计的话,这里我会拆分成好几个模块,每个模块各司其职,比如:
- NodeParser:负责解析 DOM 树,提取需要绘制的节点信息。
- ImageLoader:负责加载和处理图像资源。
- FontLoader:负责加载和处理字体资源,确保自定义字体能够正确渲染。
- CanvasRenderer:负责管理和执行所有 Canvas 绘制操作。
- ....
整个做下来工作量是非常大的。不过好在后来我了解到有一个叫 html2canvas 的库,就是专门做这个事情的,这为我节省了很大一部分时间,而且像这种公共模块,也是通过了单元测试的,用起来也会比较放心。这样我就可以把精力放在处理其他问题上面。
# 2. Blob
模拟问题:你刚才说得到 Canvas 后,还会将其转为 Blob 数据,你说一下什么是 Blob 呢?这是流数据么?
问题分析
- 简单介绍什么是 Blob
- 贴合自己的项目讲一下是如何用的
- 设置钩子
参考答案
Blob 全称是 Binary Large Object,是一种表示不可变的、原始数据的类文件对象。Blob 可以包含文本、图像、视频等各种类型的数据。但是严格意义来讲,Blob 并非流数据,但与流数据之间能够相互转换。(简单介绍Blob)
当时在项目里面通过 html2canvas 得到 Canvas 后,可以调用 Canvas 的 toBlob 方法,就能直接得到 Blob 数据,然后将 Blob 数据写入到剪贴板里面。(贴合自己的项目来讲怎么用的)
其实一开始我是没有想着做一层转换的,但是后来发现剪贴板那一块儿是有一些限制(为最后一个钩子🪝做铺垫)在里面的,比如使用 Clipboard API 时,不能直接以 base64 字符串的形式,而是需要封装为 Blob 对象传入。
另外还有一些其他的限制,我也是挨着一个一个去解决的。(钩子🪝)
# 3. 剪贴板
模拟问题:那你说一下剪贴板还有哪些限制呢?
问题分析
- 举两个有代表性的限制
- 尽量贴合自己的项目来讲
- 收尾
- 突出自己的做事儿的风格
- 这次项目的收获
参考答案
比如一开始我写的图像类型为 jpeg,结果发现不能正常工作。然后我就去查阅了剪贴板的规范文档,发现支持的 MIME 类型有 text/plain、text/html 和 image/png,难怪不得我写的 image/jpeg 无法正常工作。
再比如还有一个细节,就是剪贴板必须在安全的环境下才能正常工作,当时一开始我使用的是 HTTP 协议,也是出现了无法写入的问题。后面我知道这个限制后,修改了项目代理的配置,换成了 HTTPS 环境,才变正常的。
这是我印象最深的两个点,通过解决这两个问题,我在解决问题的习惯上也有了改善,以前就老是百度去查,现在像这种 WebAPI 类型的问题,我会直接去翻阅 MDN 或者规范文档,这样得到的答案是最准确的。
做完这个项目后,相比以前,我对和剪贴板相关需求的处理,也更加熟练了。并且项目结束后,我还将这个模块发布到了 npm 上,下次有同样的业务需求,直接下载依赖用就好了~(这次做项目的一个收获)
所以对于其他人来讲不知道感受如何,但对于我自己来讲,这确确实实是一个印象深刻的点,因此在简历里面我也把它作为了我的项目亮点。(再次解释为什么这个可以作为一个项目亮点)
(结束🎉)
-EOF-