前言:最近太太太太太忙了,整天干活干活干活555都没时间学习。赶紧忙里偷闲,沉浸一下 monaco 的世界。还是先复习复习上一篇文章的内容。
上一篇文章讲了两种自定义DOM,这一篇会讲第三种哦。
- IOverlayWidget 是渲染在文本之上的浮窗组件
- IOverlayWidget 属性:
getId
、getDomNode
、getPosition
- 新增 IOverlayWidget:
editor.addOverlayWidget
- 重新渲染 IOverlayWidget:
editor.layoutOverlayWidget
,需要getId
、getPosition
,只能改变位置,不能改变内容 - 删除 IOverlayWidget:
editor.removeOverlayWidget
,提供getId
属性即可
- IOverlayWidget 属性:
- IContentWidget 是出现在光标附近的小框框,和编辑行为息息相关
- IContentWidget 属性:
- allowEditorOverflow 是否允许框框溢出编辑器
- suppressMouseDown 是否阻止鼠标点击行为
- getId 唯一标识
- getDomNode 框框内容
- getPosition 框框位置
- beforeRender 渲染前的回调
- afterRender 渲染后的回调
- 新增 IContentWidget:
editor.addContentWidget
- 重新渲染 IContentWidget:
editor.layoutContentWidget
只能改变位置,不能改变内容 - 删除 IContentWidget:
editor.removeContentWidget
- IContentWidget 属性:
- applyEdits 用来修改指定 range 处的文本
- 监听鼠标落下的方法:
editor.onMouseDown(e=>{})
monaco.editor.MouseTargetType
枚举值,表示鼠标在哪里点击getWordAtPosition()
获取某个位置的一整个单词getWordUntilPosition()
获取的是单词从开头截取到指定 position 的位置- 自定义token的方法:
monaco.languages.setMonarchTokensProvider(languageId, languageDef)
languageDef
:有一个必填属性tokenizer
,它是一个对象,它的属性填一个rules
即可,rules
是一个二维数组
之前都是一篇文章写三个大的知识点,发现这样子容易一篇文章拖太久,所以以后还是一篇写一个吧
changeViewZones
这个 API 用于更改自定义的DOM,当编辑器中的model修改时,创建出来的这些自定义DOM就会消失
接受一个回调函数作为参数
changeViewZones(callback: (accessor: IViewZoneChangeAccessor) => void): void;
真抽象
还好官网给了一个示例
使用示例
回调函数接受的参数类型是
export interface IViewZoneChangeAccessor {
// 创建一个新的 ViewZone
addZone(zone: IViewZone): string;
// 删除 Zone,id 是 addZone 方法的返回值
removeZone(id: string): void;
// 改变 Zone 的位置 编辑器会重新根据 afterLineNumber 和 afterColumn 属性调整位置
layoutZone(id: string): void;
}
这三个方法必须要在 changeViewZones
的内部使用,在外边没有办法通过 editor 调用
然后先看一下 addZone
方法,它接受的参数是我们要创建的DOM元素的各种属性
export interface IViewZone {
// 在哪一行的后面出现 如果在第一行的前面就写0
afterLineNumber: number;
// 在哪一列的后面出现
// 如果没有设置,会在afterLineNumber的最后一列出现
afterColumn?: number;
// 如果 afterColumn 有多个列视图,使用afterColumnAffinity 指定用哪个 默认为 none
// PositionAffinity 是一个枚举值
afterColumnAffinity?: PositionAffinity;
// 即使当前区域看不见也渲染 zone
showInHiddenAreas?: boolean;
// 在同一行设置多个 zone 时决定显示顺序
ordinal?: number;
// 是否阻止 mousedown 事件
// 如果设置,编辑器会给 zone 增加一个 mousedown 事件监听器,并且增加.preventDefault
suppressMouseDown?: boolean;
// zone 的高度 如果设置指定的数字,则heightInPx属性生效
// 如果`heightInPx` 和 `heightInLines`属性都没设置,则默认 heightInLines = 1
heightInLines?: number;
// 单位为px的高度值
heightInPx?: number;
// 最小宽度
minWidthInPx?: number;
// dom 元素
domNode: HTMLElement;
// 在空白区域显示的dom
marginDomNode?: HTMLElement | null;
// 回调函数,给出top值
onDomNodeTop?: (top: number) => void;
// 回调,给出height值
onComputedHeight?: (height: number) => void;
}
其中的 afterColumn 和 afterColumnAffinity 好像没啥用啊,都是从第一列开始放置的呀
先看一下 ordinal 的效果,控制显示顺序
const domNode1 = document.createElement('div')
domNode1.innerHTML = '我是dom1'
domNode1.style.background = 'lightgreen'
const zone1 = {
afterLineNumber: 1,
ordinal:2,
domNode: domNode1
}
const domNode2 = document.createElement('div')
domNode2.innerHTML = '我是dom2'
domNode2.style.background = 'yellow'
const zone2 = {
afterLineNumber: 1,
ordinal: 1,
domNode: domNode2
}
editor.changeViewZones(changeAccessor => {
changeAccessor.addZone(zone1);
changeAccessor.addZone(zone2);
})
显示效果:
marginDomNode 会显示在左边
另外需要用变量保存 addZone 返回的结果,作为 zoneId,后续修改或删除 zone 的时候需要使用
const dom = document.createElement('div')
dom.style.background = 'lightgreen'
let zoneId = null
const marginDomNode = document.createElement('div')
marginDomNode.style.background = 'res'
marginDomNode.innerHTML = '我是marginDom'
editor.changeViewZones(changeAccessor => {
zoneId = changeAccessor.addZone({
afterLineNumber: 1,
heightInLines: 3,
domNode: dom,
marginDomNode
})
})
修改,可以修改dom里面的内容
setTimeout(() => {
dom.innerHTML = '我是修改之后的内容'
editor.changeViewZones(changeAccessor => {
changeAccessor.layoutZone(zoneId)
})
}, 3000)
删除:
setTimeout(() => {
editor.changeViewZones(changeAccessor => {
changeAccessor.removeZone(zoneId)
})
}, 6000)