vue下使用Monaco Editor

vue下使用Monaco Editor

1.簡介

? Monaco Editor是為VS Code提供支持的代碼編輯器。描述代碼編輯器的功能,良好的網(wǎng)頁是在這里。它已獲得MIT許可,并支持Classic Edge,Edge,Chrome,F(xiàn)irefox,Safari和Opera。移動(dòng)瀏覽器或移動(dòng)Web框架支持Monaco編輯器(但移動(dòng)的有的瀏覽器是支持的,起碼我用的幾個(gè)都支持)。

2.開始

2.1 安裝環(huán)境

npm install monaco-editor@0.21.2 --save
npm install monaco-editor-webpack-plugin --save //這個(gè)必須安裝,不然起不來

2.2 配置文件

修改webpack.base.conf.js配置文件。(前幾步借鑒時(shí)間脫臼大神博客,步驟大同小異)

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

2.3 開始使用

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

<div id="container"></div> <!--寬高自行設(shè)定 -->
import * as monaco from 'monaco-editor'
export default{
    data(){
        return {
            editor:null,//文本編輯器
        }
    },
    mounted(){
      this.initEditor();  
    },
    methods:{
        initEditor(){
            // 初始化編輯器,確保dom已經(jīng)渲染
            this.editor = monaco.editor.create(document.getElementById('container'), {
                value:'',//編輯器初始顯示文字
                language:'sql',//語言支持自行查閱demo
                automaticLayout: true,//自動(dòng)布局
                theme:'vs-dark' //官方自帶三種主題vs, hc-black, or vs-dark
            });
        },
        getValue(){
            this.editor.getValue(); //獲取編輯器中的文本
        }
    }
}

附:Monaco Editor demo

image-20201012143856748.png

附:語言支持(當(dāng)然支持自定義語言)

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

附:配置項(xiàng)(根據(jù)自身需要在初始化編輯器是配置) 配置項(xiàng)鏈接

selectOnLineNumbers: true,//顯示行號
roundedSelection: false,
readOnly: false,        // 只讀
cursorStyle: 'line',        //光標(biāo)樣式
automaticLayout: false, //自動(dòng)布局
glyphMargin: true,  //字形邊緣
useTabStops: false,
fontSize: 28,       //字體大小
autoIndent:true,//自動(dòng)布局
quickSuggestionsDelay: 500,   //代碼提示延時(shí)

至此,最簡單的文檔編輯器已經(jīng)完成。

3. 進(jìn)階

3.1 文件改動(dòng)狀態(tài)

export default{
    data(){
        return {
            editor:null,//文本編輯器
            isSave:true,//文件改動(dòng)狀態(tài),是否保存
            oldValue:'' //保存后的文本
        }
    },
    methods:{
        initEditor(){
            // 初始化編輯器,確保dom已經(jīng)渲染
            this.editor = monaco.editor.create(document.getElementById('container'), {
                value:'',//編輯器初始顯示文字
                language:'sql',//語言支持自行查閱demo
                automaticLayout: true,//自動(dòng)布局
                theme:'vs-dark' //官方自帶三種主題vs, hc-black, or vs-dark
            });
            this.editor.onKeyUp(() => {
                // 當(dāng)鍵盤按下,判斷當(dāng)前編輯器文本與已保存的編輯器文本是否一致
                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已經(jīng)渲染
            this.editor = monaco.editor.create(document.getElementById('container'), {
                value:'',//編輯器初始顯示文字
                language:'sql',//語言支持自行查閱demo
                automaticLayout: true,//自動(dòng)布局
                theme:'vs-dark' //官方自帶三種主題vs, hc-black, or vs-dark
            });
        },
        changeModel(){
            var oldModel = this.editor.getModel();//獲取舊模型
            var value = this.editor.getValue();//獲取舊的文本
            //創(chuàng)建新模型,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();
            }
            //設(shè)置新模型
            this.editor.setModel(newModel);
        }
    }
}

3.3 更改編輯器配置

//此例為更改編輯器為只讀模式,其余以此類推
this.editor.updateOptions({readOnly:true})

3.4 觸發(fā)編輯器事件

//此為格式化代碼,anything無用,后一個(gè)參數(shù)為action事件,自行查找,我也就找到這么一個(gè)
this.editor.trigger('anything','editor.action.formatDocument');

3.5 獲取選中內(nèi)容

//獲取編輯器選中的參數(shù),包括起始行等等
var selection = this.editor.getSelection();
//獲取當(dāng)前選中的文本
var text = currentFn(editor,selection.startLineNumber,selection.startColumn,selection.endLineNumber,selection.endColumn);
function currentFn(monacoEditor, startLineNumber, startColumn, endLineNumber, endColumn) {
    let currentText = '' //選中文字的內(nèi)容
    let num = 0;//累計(jì)回車的數(shù)量
    let startIndex = null;//截取編輯器內(nèi)容的起始下標(biāo)
    let endIndex = null;//截取編輯器內(nèi)容的結(jié)束下標(biāo)
    // monacoEditor.getValue().split('')  :  獲取編輯器內(nèi)容,并拆成數(shù)組,并把每一個(gè)字符作為數(shù)組的每一項(xiàng)
    if (startLineNumber < endLineNumber) {//當(dāng)起始行<結(jié)束行(方向:從上到下,從左到右)
        monacoEditor.getValue().split('').map((item, index) => {
            if (startLineNumber === 1) {//判斷起始行當(dāng)前行數(shù),為1 則前面沒有回車
            startIndex = startColumn - 1;//獲取起始下標(biāo)
            if (item === '\n') {
                num += 1;//累計(jì)回車數(shù)量(針對于結(jié)束行)
                if (num === endLineNumber - 1) {//獲取結(jié)束行最近的回車的下標(biāo)+結(jié)束行的結(jié)束列
                endIndex = index + endColumn
                }
            }
            } else {//判斷起始行當(dāng)前行數(shù),大于1 則前面有回車
            if (item === '\n') {//累計(jì)回車數(shù)量
                num += 1
                if (num === startLineNumber - 1) {//獲取起始行最近的回車的下標(biāo)+起始行的起始列
                startIndex = index + startColumn
                }
                if (num === endLineNumber - 1) {//獲取結(jié)束行最近的回車的下標(biāo)+結(jié)束行的結(jié)束列
                endIndex = index + endColumn
                }
            }
            }
        })
    } else if (startLineNumber > endLineNumber) {//當(dāng)起始行>結(jié)束行(方向:從下到上,從右到左)
        monacoEditor.getValue().split('').map((item, index) => {
            if (endLineNumber === 1) {//判斷結(jié)束行當(dāng)前行數(shù),為1 則前面沒有回車
            startIndex = endColumn - 1;//獲取起始下標(biāo)
            if (item === '\n') {
                num += 1;//累計(jì)回車數(shù)量(針對于起始行)
                if (num === startLineNumber - 1) {//獲取結(jié)束下標(biāo):起始行最近的回車的下標(biāo)+起始行的起始列
                endIndex = index + startColumn
                }
            }
            } else {//判斷結(jié)束行當(dāng)前行數(shù),大于1 則前面有回車
            if (item === '\n') {//累計(jì)回車數(shù)量
                num += 1
                if (num === endLineNumber - 1) {//獲取結(jié)束行最近的回車的下標(biāo)+結(jié)束行的結(jié)束列
                startIndex = index + endColumn
                }
                if (num === startLineNumber - 1) {//獲取起始行最近的回車的下標(biāo)+起始行的起始列
                endIndex = index + startColumn
                }
            }
            }
        })
    } else if (startLineNumber === endLineNumber) {//當(dāng)起始行=結(jié)束行(方向:從左到右,從右到左)
        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) {
        // 獲取當(dāng)前行數(shù)
        const line = position.lineNumber;

        // 獲取當(dāng)前列數(shù)
        const column = position.column;
        // 獲取當(dāng)前輸入行的所有內(nèi)容
        const content = model.getLineContent(line)
        // 通過下標(biāo)來獲取當(dāng)前光標(biāo)后一個(gè)內(nèi)容,即為剛輸入的內(nèi)容
        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 == "$"){
            //...
            //攔截到用戶輸入$,開始設(shè)置提示內(nèi)容,同else中代碼一致,自行拓展
        }else{
            //直接提示,以下為sql語句關(guān)鍵詞提示
            var sqlStr = ['SELECT','FROM','WHERE','AND','OR','LIMIT','ORDER BY','GROUP BY'];
            for(var i in sqlStr){
                suggestions.push({
                    label: sqlStr[i], // 顯示的提示內(nèi)容
                    kind: monaco.languages.CompletionItemKind['Function'], // 用來顯示提示內(nèi)容后的不同的圖標(biāo)
                    insertText: sqlStr[i], // 選擇后粘貼到編輯器中的文字
                    detail: '', // 提示內(nèi)容后的說明
                    range:range
                });
            }
        }
        return {
            suggestions: suggestions
        };
    },
    triggerCharacters: ["$",""]
});
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,825評論 6 546
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,814評論 3 429
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,980評論 0 384
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 64,064評論 1 319
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,779評論 6 414
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 56,109評論 1 330
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,099評論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 43,287評論 0 291
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,799評論 1 338
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,515評論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,750評論 1 375
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,221評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,933評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,327評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,667評論 1 296
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,492評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,703評論 2 380