Monaco Editor系列(九)创建自定义DOM changeViewZones

前言:最近太太太太太忙了,整天干活干活干活555都没时间学习。赶紧忙里偷闲,沉浸一下 monaco 的世界。还是先复习复习上一篇文章的内容。
上一篇文章讲了两种自定义DOM,这一篇会讲第三种哦。

  • IOverlayWidget 是渲染在文本之上的浮窗组件
    • IOverlayWidget 属性:getIdgetDomNodegetPosition
    • 新增 IOverlayWidget:editor.addOverlayWidget
    • 重新渲染 IOverlayWidget:editor.layoutOverlayWidget,需要getIdgetPosition,只能改变位置,不能改变内容
    • 删除 IOverlayWidget:editor.removeOverlayWidget,提供 getId 属性即可
  • IContentWidget 是出现在光标附近的小框框,和编辑行为息息相关
    • IContentWidget 属性:
      • allowEditorOverflow 是否允许框框溢出编辑器
      • suppressMouseDown 是否阻止鼠标点击行为
      • getId 唯一标识
      • getDomNode 框框内容
      • getPosition 框框位置
      • beforeRender 渲染前的回调
      • afterRender 渲染后的回调
    • 新增 IContentWidget:editor.addContentWidget
    • 重新渲染 IContentWidget:editor.layoutContentWidget 只能改变位置,不能改变内容
    • 删除 IContentWidget:editor.removeContentWidget
  • 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)
  • 22
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值