首页 > 其他分享 >vue+nuxtJs+monaco制作Monaco Editor编辑器

vue+nuxtJs+monaco制作Monaco Editor编辑器

时间:2022-12-29 14:35:49浏览次数:40  
标签:vue nuxtJs language 编辑器 editor monaco model true

目录

前言

使用版本较低

一、版本

image

二、使用前配置

nuxt.config.js

实现下方五种语言的自动补全
image

三、使用

<template>
  <div class="warp">
    <div ref="container" class="monaco"></div>
  </div>
</template>
<script>
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api'
export default {
  props: {},
  data() {
    return {
      editor: null, // 编辑器
      value: '', // 数据;diff开启时,传新数据
      original: '', // diff开启时,传旧数据
      model: '', // 当前文件model
      originalModel: '', // 原始文件model
      language: 'javascript', // 语言
      diff: false, // 是否为diff功能
      // 默认配置
      defaultOpts: {
        roundedSelection: false, // 右侧不显示编辑器预览框
        contextmenu: true, // 上下文菜单(右键菜单)
        renderWhitespace: 'all', // 启用空白呈现
        formatOnType: true, // 类型格式化
        formatOnPaste: true, // 复制格式化
        foldingStrategy: 'indentation', // 代码可分小段折叠
        folding: true, // 是否启用代码折叠
        readOnly: false, // 只读
        autoIndent: true, // 自动缩进
        automaticLayout: true, // 自适应布局
        wordWrap: true, // 自动换行
        fontSize: 14,
        tabSize: 2, // tab 缩进长度
        theme: 'vs-dark', // 主题
        // renderSideBySide: true, // 行内比较
        // enableSplitViewResizing: true, // 不为行内比较时,中间是否能拖拽
      },
    }
  },
  // diff功能预留 数据不变用不到,未来可能能编辑 监听父组件传值的变化,实时更新到编辑器中
  watch: {
    original: {
      handler(val, oldVal) {
        this.originalModel = monaco.editor.createModel(val, this.language)
        this.editor.setModel({
          original: this.originalModel,
          modified: this.model,
        })
      },
    },
    value: {
      handler(val, oldVal) {
        if (this.diff) {
          this.model = monaco.editor.createModel(val, this.language)
          this.editor.setModel({
            original: this.originalModel,
            modified: this.model,
          })
        } else {
          this.model = monaco.editor.createModel(val, this.language)
          this.editor.setModel(this.model)
        }
        this.$emit('change', this.model.getValue())
      },
    },
  },
  mounted() {
    this.initMonaco()
  },
  beforeDestroy() {
    this.editor && this.editor.dispose()
  },
  methods: {
    initMonaco() {
      // 编辑器挂载之前发生的事件
      this.editorWillMount()
      // 初始化编辑器实例
      if (this.diff) {
        // diff功能
        // 创建diff编辑器
        this.editor = monaco.editor.createDiffEditor(
          this.$refs.container,
          this.defaultOpts
        )
        // 创建原始文件model
        this.originalModel = monaco.editor.createModel(
          this.original,
          this.language
        )
        // 创建当前文件model
        this.model = monaco.editor.createModel(this.value, this.language)
        // 设置编辑器model
        this.editor.setModel({
          original: this.originalModel,
          modified: this.model,
        })
      } else {
        // 创建默认编辑器
        this.editor = monaco.editor.create(
          this.$refs.container,
          this.defaultOpts
        )
        // 创建当前文件model
        this.model = monaco.editor.createModel(this.value, this.language)
        // 设置编辑器模型
        this.editor.setModel(this.model)
      }
      //  编辑器挂载时发生从事件
      this.editorDidMount()
    },
    // 编辑器挂载之前发生的事件
    editorWillMount() {
      // 可用于注册自定义语言、注册自定义皮肤样式、代码提示补全
      this.language = 'consoleBoardLanguage'
      this.defaultOpts.theme = 'myCoolTheme'
      this.setLanguage()
      this.setTheme()
      this.setCodeHint()
    },
    //  编辑器挂载时发生从事件
    editorDidMount() {
      // 可用于注册右键菜单、设置Marker(没用到)
      this.setAction()
    },
    // 设置自定义语言
    setLanguage() {
      // 注册自定义语言ID
      // https://microsoft.github.io/monaco-editor/playground.html#extending-language-services-custom-languages
      monaco.languages.register({
        id: 'consoleBoardLanguage',
      })
      // 自定义语言的语法高亮
      // https://microsoft.github.io/monaco-editor/monarch.html
      monaco.languages.setMonarchTokensProvider('consoleBoardLanguage', {
        ignoreCase: true, // 忽略分词器的大小写
        tokenizer: { // 分词器
          root: [
            [/\[error.*/, 'custom-error'],
            [/\[warn.*/, 'custom-warn'],
            [/\[success.*/, 'custom-success'],
            [/\[表达式正确.*/, 'custom-success'],
          ],
        },
      })
    },
    // 设置自定义皮肤
    setTheme() {
      monaco.editor.defineTheme('myCoolTheme', {
        base: 'vs', // 要继承的基础主题,内置:vs、vs-dark、hc-black
        inherit: true, // 是否继承 base 设定的原始皮肤样式
        rules: [
          // 高亮规则,token为自定义语言时设置的值
          { token: 'custom-error', foreground: 'ff0000', fontStyle: 'bold' },
          { token: 'custom-warn', foreground: 'FFA500' },
          { token: 'custom-success', foreground: '008800' },
        ],
        colors: {
          // 全局颜色
          // https://microsoft.github.io/monaco-editor/playground.html#customizing-the-appearence-exposed-colors
          'editor.foreground': '#000000',
          'editor.background': '#EDF9FA',
          'editorCursor.foreground': '#8B0000',
          'editor.lineHighlightBackground': '#0000FF20',
          'editorLineNumber.foreground': '#008800',
          'editor.selectionBackground': '#88000030',
          'editor.inactiveSelectionBackground': '#88000015',
        },
      })
    },
    // 设置代码提示补全
    setCodeHint() {
      const API = [
        {
          label: 'success', // 控制每个选项显示的文本,一个字符串
          detail: '成功', // 选项的详情,一个字符串
          documentation: '该代码运行成功!!!!!', // 选项的详细描述,一个字符串或markdown
          insertText: '[success]:', // 最后插入的文本
          command: { // 选择后,自动执行内置的action或command操作
            id: 'editor.action.formatDocument', // 内置action详情 console.log()
            title: '选中这个建议选项后,触发格式化操作'
            // id: 'actions.find',
            // title: '选中这个建议选项后,触发查询',
          },
        },
        {
          label: 'focus()',
          detail: '焦点定位的方法',
          documentation: '焦点定位的方法',
          tags: [monaco.languages.CompletionItemTag.Deprecated], // 设置后带删除线
        },
        {
          label: 'newFocus()',
          detail: '焦点定位的方法',
          documentation: '焦点定位的方法',
        },
      ]
      // 第一个参数为语言ID
      monaco.languages.registerCompletionItemProvider('consoleBoardLanguage', {
        // model:当前model position:当前光标的位置 context:自动完成的上下文
        provideCompletionItems(model, position, context) {
          const word = model.getWordUntilPosition(position) // 获取单词的开始位置
          const range = {
            // 开始位置等于结束位置,那么就是插入操作,否则就是替换操作。
            startLineNumber: position.lineNumber, // 开始行数
            endLineNumber: position.lineNumber, // 结束行数
            startColumn: word.startColumn, // 开始列数
            endColumn: word.endColumn, // 结束列数
          }
          return {
            suggestions: API.map((item) => {
              return {
                label: item.label, // 控制每个选项显示的文本,一个字符串
                detail: item.detail, // 选项的详情,一个字符串
                kind: monaco.languages.CompletionItemKind.Function, // 选项的类型,决定了选项的图标,一个枚举值,详情看附录
                documentation: item.documentation, // 选项的详细描述,一个字符串或markdown
                insertText: item.insertText || item.label, // 最后插入的文本
                tags: item.tags || null, // 设置为 [monaco.languages.CompletionItemTag.Deprecated] 后,选项会显示删除线,表示不推荐,或废弃。
                command: item.command || null, // 选择后,自动执行内置的action或command操作
                // range, // 文本要替换的区间,默认是从单词的开始位置(TextDocument.getWordRangeAtPosition)到当前光标的位置。
                additionalTextEdits: [
                  // 追加内容
                  {
                    range,
                    text: `// 追加注释` + '\n', // 内容
                    forceMoveMarkers: true, // Markes相关,正常用不到 true => if `range` is collapsed, all markers at the position will be moved.
                  },
                ],
              }
            }),
          }
        },
      })
    },
    // 设置菜单
    setAction() {
      const editor = this.editor
      // Monaco Editor中菜单项的专业术语叫做Action
      editor.addAction({
        id: 'print-console', // action 的唯一id,需要独一无二,不与其他重复
        label: '打印console', // 菜单名称
        keybindings: [
          // 哪些组合键可以触发,右键提示数组最后一项
          monaco.KeyMod.CtrlCmd | monaco.KeyCode.F10,
          // chord为两个组合 ctrl+I ctrl+O
          monaco.KeyMod.chord(
            monaco.KeyMod.CtrlCmd | monaco.KeyCode.KEY_I,
            monaco.KeyMod.CtrlCmd | monaco.KeyCode.KEY_O
          ),
        ],
        contextMenuGroupId: 'navigation', // 控制操作是否应显示在上下文菜单中以及显示位置 navigation:最前面  insert:自定义取名
        contextMenuOrder: 1.5, // 菜单项的排序权重 越小,越靠前
        run(ed) {
          // 执行函数
          console.log('23333')
          return null
        },
      })
    },
    // 此方法获取到编辑的最新值,传给父组件
    getValue() {
      this.$emit('change', this.model.getValue())
    },
  },
}
</script>
<style lang="scss" scoped>
.warp {
  width: 100%;
  height: 100%;
}
.monaco {
  overflow: hidden;
  width: 80%;
  height: 80%;
  display: block;
  position: relative;
  .monaco-editor {
    width: 100%;
  }
}
</style>

四、附录

1.kind 提示图标类型

image

2.默认action

// 一堆,自己看
console.log(this.$refs.monacoEditor.getEditor()._actions)

标签:vue,nuxtJs,language,编辑器,editor,monaco,model,true
From: https://www.cnblogs.com/DarkCrow/p/17010850.html

相关文章

  • vue3.0的生命周期
    1.vue3的生命周期与vue2的不同点:  2.vue3的生命周期与vue2对应的点:2.1beforeCreate和create相当于setup,因为不能写入setup生命周期内2.2使用vue3的组合式AP......
  • vue中获取dom元素的集合的length不正确的问题
    可以知道在mounted阶段,mounted 不会承诺所有的子组件也都一起被挂载,所以在此阶段,dom结构还没加载完,js就执行了。所以会打印出不正确的length属性。解决方法:1.$nextTick......
  • vue-cropper插件使用
    <template><el-form-item:label="label"prop="coverUrl"><el-imagev-if="ruleCoverUrl"class="uploadImgwh":src="ruleCoverUrl"@c......
  • VueJS使用addEventListener的事件如何触发执行函数的this
    1、使用浏览器监听切屏为例此处为考虑浏览器兼容性推荐使用:document.addEventListener1.1、正常函数使用如下:letn=0;letmax=3;//切屏最大次数document.addE......
  • (一)Vue 3 项目搭建
    确保已安装16.0或更高版本的Node.js,然后在命令行中运行以下命令:npminitvue@latest这一指令将会安装并执行create-vue,它是Vue官方的项目脚手架工具。你将会看到......
  • vue基本语法
    vue基本语法v-bind<!DOCTYPEhtml><htmllang="en"xmlns:v-bind="http://www.w3.org/1999/xhtml"><head><metacharset="UTF-8"><title>Title</title>......
  • vue入门
    Vue入门SOC:关注度分离原则网页三要素:HTML+CSS+js:视图:给用户看,刷新后台给的数据网络通信:axios页面跳转:Vue-router状态管理:vuexVue-UI:ICEM模型V视图C控制器......
  • 【前端vue开发架构】vue开发单页项目架构总结
    活动设计的前端架构主要的技术栈为Vuejs,Webpack,请自行阅读如下技术或者框架的文档:一、基础说明:node (https://nodejs.org/en/)npm(​​https://www.npmjs.com​​)webpac......
  • Vue2下的路由的基本使用
    路由理解:一个路由(route)就是一组映射关系(key-value),多个路由需要路由器(router)进行管理。前端路由:key是路径,value是组件。1.基本使用安装vue-router,命令:npmivue-......
  • vue3+vite build打包报错:Some chunks are larger than 500 KiB after minification. C
    看官方的解决方案:1、在rollup配置文件中添加output.manualChunks,将模块拆分成多个chunk,减小每个chunk的大小;2、build.chunkSizeWarningLimit,提高报错的阈值;3、使用动......