vscode 鼠标放代码上 显示代码什么时候创建_vscode 源码精读(二)代码编辑器的DOM结构初探...

vscode 中最核心和最重要的内容是它的代码编辑器:monaco editor,monaco editor 不仅是 vscode 的一部分,并且可以作为独立的 web 组件供大家免费使用。 关于 monaco editor 的集成详细文档,大家可以查阅微软的官方文档。

var newModel = monaco.editor.createModel(data, 'some id here!');
var editor = monaco.editor.create(document.getElementById('editor'), {
    model: newModel,
});

monaco editor 的创建过程如上所示,可以看出 monaco editor 有两个核心的对象: model 和 editor。model 部分是存在代码字符串数据的对象,它的内部结构非常复杂,我们会在后面的文章中深入。editor 就是整个代码编辑器。

为了一步一步探索编辑器内部的神秘面纱,我们先从它的 DOM 结构开始。

最外层结构:

  • 容器元素
    • 编辑器主体
      • overflow-guard,编辑器的主要区域
      • overflowingContentWidgets,与右键菜单相关的内容
      • context-view, 与右键菜单相关的内容

对于创建 monaco editor 的时候,有一个隐性的约束,容器的高度必须是确定的,编辑器本事会支持部分的宽度自适应。在创建好 Editor 的时候,editor 会在容器元素上添加两个属性:

  • data-keybinding-context="1", 标示这个编辑器绑定快捷键的方式
  • data-mode-id="", 标示编辑器中的 model id

overflow-guard 编辑器的主要区域:

  • margin: 左侧的代码行号区区,上面列有代码行号,折叠代码图标以及加断点标记。
  • editor-scrollable: 主要代码工作区域
  • scroll-decoration: 滚动阴影装饰窄条,当开始滚动时出现在顶部
  • textarea:鼠标输入框
  • monaco-editor-background textAreaCover line-numbers (主要起装饰作用,具体作用暂时未知,以后补充)
  • overlayWidgets: 按 ctrl + F 弹出来的查找替换搜索框在这里面
  • minimap: 右侧的代码小地图

0595c003580283824a2801cb04d9672a.png

textarea 元素

textarea 元素是一种可以自由控制光标位置显示的技巧。

代码之所以在编辑器中会显示出花花绿绿的各种语法高亮,那是因为它们本身是由一个一个span组成的,并且不是 input 输入框。当我们在编辑器中输入代码时,需要一个光标显示在对应的位置,这个时候就可以控制一个 textarea 元素,它的宽度是 1px,高度对应字体高度,将它的位置设置到当前的位置,并且设置为 focus 状态了,这个时候界面上就会在对应位置上出现一闪一闪的光标。

274c4100f29c5738bc479920b8b8a6e4.png

这是一个普遍的技巧,我们常见的 select 组件中经常会使用到,另外一个常见的场景是在交互式 canvas 中需要用户输入的地方。

overlayWidgets 元素

我们通过按 ctrl + f 键,会在代码编辑器中弹出一个有查找替换框,这个查找替换框就是在 overlayWidgets 里。当然,overlayWidgets 里还有别的 widget,限于当前的认识,无法确切知道是具体是做什么的,但随着我们学习的深入,这些会在以后慢慢揭秘。

c6bcacdbcbd28d308a2c1457467db72f.png

minimap 代码小地图

minimap 的功能相对独立,DOM 结构非常简单:

  • minimap-shadow-hidden, 主要起UI装饰装饰作用
  • canvas:绘制整个代码的缩略图
  • canvas:minimap-decorations-layer, 绘制语法错误的行
  • minimap-slider:minimap 上的半透明罩层,表示当前代码在整个文档中的滚动位置

minimap 是一个很有意思的话题,它的实现特别精巧。这里有一个细节需要注意一下,在UI 上绘制小物体时,通常会选择按大尺寸绘制,然后成比例设置为一个小的 css 来控制最终的显示。

aff365fbb7ee5955eb8ee8cfc4791917.png

代码缩略图是如何绘制的

代码的缩略图如下:

035acf3714b7dc949cc91a2adbc29e25.png

vscode 对于它的实现给了一个非常有意思的答案,具体代码是在 /src/vs/editor/browser/viewParts/minimap 目录下。

microsoft/vscode

这里简单快速地说一下原理,在 vscode 中将 ascii 码 32 到 126 之间的字符,按照两种尺寸(宽1px高2px,和宽2px高4px)提前准备到一个 map 里。具体代码如下:

4782d10440b9b9c1526ccfe2ca4b4d47.png
vscode 中的 minimap char render map

将这个 map 里的数据转换成图片显示出来就是如下的样子:

42b9bb0de628656945256269ac245cff.png
宽 1px,高 2px

acb8e829a54d44eda18be7fe60a93a0b.png
宽 2px,高 4px

在绘制代码的时候,是一个字符一个字符的绘制,如果字符是基础字符集,则从这个map里使用它的像素信息,再对应上字体在文本中的高亮颜色。如果字符是汉字之类,则绘制一个方块。最终绘制的效果如下,可以隐约能看出字体的轮廓:

0d347ace31e2b41bef734655329e1706.png

总结

关于 monaco editor 的 DOM 结构,我们做了一个简单的概览,有了一个大体的了解。关于 Margin 部分,和代码工作区的部分,在后续单独的章节里再展开。

比如虚拟列表技巧的普遍使用,比如一个文档有 1w 行,真实在 DOM 里只会有 50 个左右。不同于我们经常用 virtual-list,vscode 代码编辑器可以下拉到超出文档内容很多的底部。

今天对代码的部分讨论的很少,从 DOM 结构开始切入,对于monaco editor 有一个整体的了解,先知道 What,再去深入 How 的问题。从本质上来说,文档/UT 都是属于代码,代码是一种表象,更重要的是代码背后的设计思路。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值