提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

最近接手了一个新项目,这个项目中有一个需求点就是需要展示json,并且可能还要编辑展示代码,然后我就去调研了关于代码编辑器的有关技术,经过对比决定使用monaco-editor。


提示:以下是本篇文章正文内容,下面案例可供参考

一、monaco-editor是什么?

monaco-editor一款代码编辑器,是微软开源的一个web编辑器,vscode中也是集成它来实现的,所以我们可以通过monaco-editor在我们的网页中集成一个vscode出来,好的废话不多说,直接开干。

二、使用步骤

1.安装依赖
yarn add monaco-editor 或 npm i monaco-editor
2.编写组件

我的代码如下:

<div ref="json-editor-code" class="json-editor"></div>
@Component
export default class JsonCodeEditor extends Vue {
  @Prop({ default: () => {} }) private data!: any
  @Prop({ default: () => {} }) private opt?: any
  private editor: any;
  private monaco: any= monaco;

  private options: any =  {
      language: 'json', // 这里你可以自己写语言。我是写死了。
      automaticLayout: true,
      tabSize: 2,
      overviewRulerBorder: false,
      scrollBeyondLastLine: false,
      minimap: {
        enabled: false // 不要小地图
      },
      theme: 'vs',
      fontSize: "14px",
      autoIndent:true,//自动布局
  }

  @Watch('data', { deep: true })
  private activeChange(val: any) {
    let current: any = this.jsonValidator(this.editor.getValue())
    if (current && !isEqual(val, current)) {
      this.editor.setValue(JSON.stringify(val))
      this.format()
    }
  }

  // json格式检查
  private jsonValidator(val: string) {
    let parsedValue

    try {
      parsedValue = JSON.parse(val)
      return parsedValue
    } catch (e) {
      return false
    }
  }

  private mounted() {
    this.initEditor()

    setTimeout(()=>{
      this.format()
    },100)
  }

  private initEditor() {
    let container = (this.$refs['json-editor-code'] as HTMLElement);
    this.editor = this.monaco.editor.create(container, {
      value: JSON.stringify(this.data),//编辑器初始显示文字
      ...Object.assign(this.options, this.opt),
      scrollbar: {
        horizontal: 'hidden',
      }
    })

    this.editor.onDidChangeModelContent(() => {
      this.$emit('code-change', this.jsonValidator(this.editor.getValue()), this.editor, this.monaco)
    })
  }

  private destroyed() {
    this.editor?.dispose()
  }
  private format() {
    this.editor.getAction('editor.action.formatDocument').run()
  }
}

自此我们就完成一个编辑器组件的一次简单封装。

3.自定义提示

如果我们想要自定义代码提示,并且还能自定义提示警告那该怎么办呢?
其实官方给我们提供了一个演示的demo,但是我没有直接跑出来,经过我的摸索也算是实现了,附上schema规则书写文档和一个能在线生成规则的网站。接下来请看,假设规则如下:

const domain = '127.0.0.1'
const validators = [{ 
	  name: 'button',
	  uri: domain + 'schemas/base/button.json#',
	  schema: {
	    type: 'object',
	    //...
	  }
	},
	{ 
	  name: 'input',
	  uri: domain + 'schemas/base/input.json#',
	  schema: {
	    type: 'object',
	    //...
	  }
	}
]

那么我们封装一个函数用于获取规则

  private getRule(type) {
	return validators.find((vd: any) => vd.name === type);
  }
  private switchRules(val: any) {
    let ruleArray = getRule(val.type)
    ruleArray = Object.assign(cloneDeep(ruleArray), { fileMatch: ['*'] }) // 这里不可少
this.monaco.languages.json.jsonDefaults.setDiagnosticsOptions({
      validate: true,
      schemas: cloneDeep(ruleArray)
    })
  }

获取规则的函数我们有了以后,只需要在数据改变的时候调用这个方法即可更新成匹配当前数据的规则了。

  @Watch('data', { deep: true })
  private activeChange(val: any) {
    let current: any = this.jsonValidator(this.editor.getValue())
    if (current && !isEqual(val, current)) {
      this.switchRules(val) // 这样就更新了规则
      this.editor.setValue(JSON.stringify(val))
      this.format()
    }
  }

总结

monaco还是有缺陷的,比如你的规则会被多个monaco-editor实例共享,不过只要你手动去除就好了,这点也还是能接收。希望这篇文章能够帮助到你。喜欢的话记得一键三连。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐