vue下使用Monaco Editor

vue下使用Monaco Editor

1.简介

​ Monaco Editor是为VS Code提供支持的代码编辑器。描述代码编辑器的功能,良好的网页是在这里。它已获得MIT许可,并支持Classic Edge,Edge,Chrome,Firefox,Safari和Opera。移动浏览器或移动Web框架支持Monaco编辑器(但移动的有的浏览器是支持的,起码我用的几个都支持)。

2.开始

2.1 安装环境

npm install monaco-editor@0.21.2 --save
npm install monaco-editor-webpack-plugin --save //这个必须安装,不然起不来

2.2 配置文件

修改webpack.base.conf.js配置文件。(前几步借鉴时间脱臼大神博客,步骤大同小异)

const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin');
module.exports = {
  ...
  plugins: [
    ...
    new MonacoWebpackPlugin()
  ]
};

2.3 开始使用

新建vue文件,添加如下代码即可使用

<div id="container"></div> <!--宽高自行设定 -->
import * as monaco from 'monaco-editor'
export default{
    data(){
        return {
            editor:null,//文本编辑器
        }
    },
    mounted(){
      this.initEditor();  
    },
    methods:{
        initEditor(){
            // 初始化编辑器,确保dom已经渲染
            this.editor = monaco.editor.create(document.getElementById('container'), {
                value:'',//编辑器初始显示文字
                language:'sql',//语言支持自行查阅demo
                automaticLayout: true,//自动布局
                theme:'vs-dark' //官方自带三种主题vs, hc-black, or vs-dark
            });
        },
        getValue(){
            this.editor.getValue(); //获取编辑器中的文本
        }
    }
}

附:Monaco Editor demo

image-20201012143856748.png

附:语言支持(当然支持自定义语言)

//modesIds即为支持语言
var modesIds = monaco.languages.getLanguages().map(function(lang) { return lang.id; });

附:配置项(根据自身需要在初始化编辑器是配置) 配置项链接

selectOnLineNumbers: true,//显示行号
roundedSelection: false,
readOnly: false,        // 只读
cursorStyle: 'line',        //光标样式
automaticLayout: false, //自动布局
glyphMargin: true,  //字形边缘
useTabStops: false,
fontSize: 28,       //字体大小
autoIndent:true,//自动布局
quickSuggestionsDelay: 500,   //代码提示延时

至此,最简单的文档编辑器已经完成。

3. 进阶

3.1 文件改动状态

export default{
    data(){
        return {
            editor:null,//文本编辑器
            isSave:true,//文件改动状态,是否保存
            oldValue:'' //保存后的文本
        }
    },
    methods:{
        initEditor(){
            // 初始化编辑器,确保dom已经渲染
            this.editor = monaco.editor.create(document.getElementById('container'), {
                value:'',//编辑器初始显示文字
                language:'sql',//语言支持自行查阅demo
                automaticLayout: true,//自动布局
                theme:'vs-dark' //官方自带三种主题vs, hc-black, or vs-dark
            });
            this.editor.onKeyUp(() => {
                // 当键盘按下,判断当前编辑器文本与已保存的编辑器文本是否一致
                if(this.editor.getValue() != this.oldValue){
                    this.isSave = false;
                }
            });
        },
        //保存编辑器方法
        saveEditor(){
            this.oldValue = this.editor.getValue();
            ...保存逻辑
        }
    }
}

3.2 更改编辑器语言

export default{
    data(){
        return {
            editor:null,//文本编辑器
        }
    },
    methods:{
        initEditor(){
            // 初始化编辑器,确保dom已经渲染
            this.editor = monaco.editor.create(document.getElementById('container'), {
                value:'',//编辑器初始显示文字
                language:'sql',//语言支持自行查阅demo
                automaticLayout: true,//自动布局
                theme:'vs-dark' //官方自带三种主题vs, hc-black, or vs-dark
            });
        },
        changeModel(){
            var oldModel = this.editor.getModel();//获取旧模型
            var value = this.editor.getValue();//获取旧的文本
            //创建新模型,value为旧文本,id为modeId,即语言(language.id)
            //modesIds即为支持语言
            //var modesIds = monaco.languages.getLanguages().map(function(lang) { return lang.id; });
            var newModel = monaco.editor.createModel(value,id);
            //将旧模型销毁
            if(oldModel){
                oldModel.dispose();
            }
            //设置新模型
            this.editor.setModel(newModel);
        }
    }
}

3.3 更改编辑器配置

//此例为更改编辑器为只读模式,其余以此类推
this.editor.updateOptions({readOnly:true})

3.4 触发编辑器事件

//此为格式化代码,anything无用,后一个参数为action事件,自行查找,我也就找到这么一个
this.editor.trigger('anything','editor.action.formatDocument');

3.5 获取选中内容

//获取编辑器选中的参数,包括起始行等等
var selection = this.editor.getSelection();
//获取当前选中的文本
var text = currentFn(editor,selection.startLineNumber,selection.startColumn,selection.endLineNumber,selection.endColumn);
function currentFn(monacoEditor, startLineNumber, startColumn, endLineNumber, endColumn) {
    let currentText = '' //选中文字的内容
    let num = 0;//累计回车的数量
    let startIndex = null;//截取编辑器内容的起始下标
    let endIndex = null;//截取编辑器内容的结束下标
    // monacoEditor.getValue().split('')  :  获取编辑器内容,并拆成数组,并把每一个字符作为数组的每一项
    if (startLineNumber < endLineNumber) {//当起始行<结束行(方向:从上到下,从左到右)
        monacoEditor.getValue().split('').map((item, index) => {
            if (startLineNumber === 1) {//判断起始行当前行数,为1 则前面没有回车
            startIndex = startColumn - 1;//获取起始下标
            if (item === '\n') {
                num += 1;//累计回车数量(针对于结束行)
                if (num === endLineNumber - 1) {//获取结束行最近的回车的下标+结束行的结束列
                endIndex = index + endColumn
                }
            }
            } else {//判断起始行当前行数,大于1 则前面有回车
            if (item === '\n') {//累计回车数量
                num += 1
                if (num === startLineNumber - 1) {//获取起始行最近的回车的下标+起始行的起始列
                startIndex = index + startColumn
                }
                if (num === endLineNumber - 1) {//获取结束行最近的回车的下标+结束行的结束列
                endIndex = index + endColumn
                }
            }
            }
        })
    } else if (startLineNumber > endLineNumber) {//当起始行>结束行(方向:从下到上,从右到左)
        monacoEditor.getValue().split('').map((item, index) => {
            if (endLineNumber === 1) {//判断结束行当前行数,为1 则前面没有回车
            startIndex = endColumn - 1;//获取起始下标
            if (item === '\n') {
                num += 1;//累计回车数量(针对于起始行)
                if (num === startLineNumber - 1) {//获取结束下标:起始行最近的回车的下标+起始行的起始列
                endIndex = index + startColumn
                }
            }
            } else {//判断结束行当前行数,大于1 则前面有回车
            if (item === '\n') {//累计回车数量
                num += 1
                if (num === endLineNumber - 1) {//获取结束行最近的回车的下标+结束行的结束列
                startIndex = index + endColumn
                }
                if (num === startLineNumber - 1) {//获取起始行最近的回车的下标+起始行的起始列
                endIndex = index + startColumn
                }
            }
            }
        })
    } else if (startLineNumber === endLineNumber) {//当起始行=结束行(方向:从左到右,从右到左)
        monacoEditor.getValue().split('').map((item, index) => {
            if (endLineNumber === 1) {
            startIndex = startColumn < endColumn ? startColumn - 1 : endColumn - 1
            endIndex = startColumn > endColumn ? startColumn - 1 : endColumn - 1
            } else {
            if (item === '\n') {
                num += 1
                if (num === endLineNumber - 1) {
                startIndex = startColumn < endColumn ? startColumn + index : endColumn + index
                endIndex = startColumn > endColumn ? startColumn + index : endColumn + index
                }
            }
            }
        })
    }
    currentText = monacoEditor.getValue().slice(startIndex, endIndex)
    return currentText
}

3.6 代码提示

monaco.languages.registerCompletionItemProvider('sql', {
    provideCompletionItems: function(model, position) {
        // 获取当前行数
        const line = position.lineNumber;

        // 获取当前列数
        const column = position.column;
        // 获取当前输入行的所有内容
        const content = model.getLineContent(line)
        // 通过下标来获取当前光标后一个内容,即为刚输入的内容
        const sym = content[column - 2];
        var textUntilPosition = model.getValueInRange({startLineNumber: 1, startColumn: 1, endLineNumber: position.lineNumber, endColumn: position.column});
        var word = model.getWordUntilPosition(position);
        var range = {
            startLineNumber: position.lineNumber,
            endLineNumber: position.lineNumber,
            startColumn: word.startColumn,
            endColumn: word.endColumn
        };
        //---------------------------------------------------
        //上面的代码仅仅是为了获取sym,即提示符
        //---------------------------------------------------
        var suggestions = [];
        if(sym == "$"){
            //...
            //拦截到用户输入$,开始设置提示内容,同else中代码一致,自行拓展
        }else{
            //直接提示,以下为sql语句关键词提示
            var sqlStr = ['SELECT','FROM','WHERE','AND','OR','LIMIT','ORDER BY','GROUP BY'];
            for(var i in sqlStr){
                suggestions.push({
                    label: sqlStr[i], // 显示的提示内容
                    kind: monaco.languages.CompletionItemKind['Function'], // 用来显示提示内容后的不同的图标
                    insertText: sqlStr[i], // 选择后粘贴到编辑器中的文字
                    detail: '', // 提示内容后的说明
                    range:range
                });
            }
        }
        return {
            suggestions: suggestions
        };
    },
    triggerCharacters: ["$",""]
});
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,367评论 6 512
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,959评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,750评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,226评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,252评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,975评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,592评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,497评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,027评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,147评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,274评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,953评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,623评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,143评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,260评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,607评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,271评论 2 358