vue下使用Monaco Editor
1.簡介
? Monaco Editor是為VS Code提供支持的代碼編輯器。描述代碼編輯器的功能,良好的網(wǎng)頁是在這里萨醒。它已獲得MIT許可并鸵,并支持Classic Edge,Edge捌蚊,Chrome集畅,F(xiàn)irefox,Safari和Opera缅糟。移動瀏覽器或移動Web框架不支持Monaco編輯器(但移動的有的瀏覽器是支持的挺智,起碼我用的幾個都支持)。
2.開始
2.1 安裝環(huán)境
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> <!--寬高自行設(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,//自動布局
theme:'vs-dark' //官方自帶三種主題vs, hc-black, or vs-dark
});
},
getValue(){
this.editor.getValue(); //獲取編輯器中的文本
}
}
}
附:語言支持(當(dāng)然支持自定義語言)
//modesIds即為支持語言
var modesIds = monaco.languages.getLanguages().map(function(lang) { return lang.id; });
附:配置項(根據(jù)自身需要在初始化編輯器是配置) 配置項鏈接
selectOnLineNumbers: true,//顯示行號
roundedSelection: false,
readOnly: false, // 只讀
cursorStyle: 'line', //光標(biāo)樣式
automaticLayout: false, //自動布局
glyphMargin: true, //字形邊緣
useTabStops: false,
fontSize: 28, //字體大小
autoIndent:true,//自動布局
quickSuggestionsDelay: 500, //代碼提示延時
至此,最簡單的文檔編輯器已經(jīng)完成髓窜。
3. 進(jìn)階
3.1 文件改動狀態(tài)
export default{
data(){
return {
editor:null,//文本編輯器
isSave:true,//文件改動狀態(tài)扇苞,是否保存
oldValue:'' //保存后的文本
}
},
methods:{
initEditor(){
// 初始化編輯器,確保dom已經(jīng)渲染
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(() => {
// 當(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,//自動布局
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無用帆阳,后一個參數(shù)為action事件,自行查找屋吨,我也就找到這么一個
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;//累計回車的數(shù)量
let startIndex = null;//截取編輯器內(nèi)容的起始下標(biāo)
let endIndex = null;//截取編輯器內(nèi)容的結(jié)束下標(biāo)
// monacoEditor.getValue().split('') : 獲取編輯器內(nèi)容,并拆成數(shù)組至扰,并把每一個字符作為數(shù)組的每一項
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;//累計回車數(shù)量(針對于結(jié)束行)
if (num === endLineNumber - 1) {//獲取結(jié)束行最近的回車的下標(biāo)+結(jié)束行的結(jié)束列
endIndex = index + endColumn
}
}
} else {//判斷起始行當(dāng)前行數(shù)敢课,大于1 則前面有回車
if (item === '\n') {//累計回車數(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;//累計回車數(shù)量(針對于起始行)
if (num === startLineNumber - 1) {//獲取結(jié)束下標(biāo):起始行最近的回車的下標(biāo)+起始行的起始列
endIndex = index + startColumn
}
}
} else {//判斷結(jié)束行當(dāng)前行數(shù)直秆,大于1 則前面有回車
if (item === '\n') {//累計回車數(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)后一個內(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: ["$",""]
});