vue(element)中使用monaco實(shí)現(xiàn)代碼高亮

vue(element)中使用monaco實(shí)現(xiàn)代碼高亮

使用的是vue語(yǔ)言佃牛,用element的組件淹辞,要做一個(gè)在線編輯代碼,要求輸入代碼內(nèi)容吁脱,可以進(jìn)行高亮展示桑涎,可以切換各不同語(yǔ)言,而且支持關(guān)鍵字補(bǔ)全兼贡,還要有一個(gè)各不同版本間的代碼左右比較攻冷,這就是需求。

至于為什么選中monaco遍希,請(qǐng)查看 vue(element)中代碼高亮插件全面對(duì)比

好了等曼,現(xiàn)在正式開工吧!

首先需要下載monaco-editor組件凿蒜,monaco-editor-webpack-plugin組件

npm install monaco-editor
npm install monaco-editor-webpack-plugin

當(dāng)然啦禁谦,npm下載很是緩慢,換個(gè)國(guó)內(nèi)鏡像废封,淘寶的吧州泊。果然,速度就嗖嗖的起來漂洋。

npm install -g cnpm --registry=https://registry.npm.taobao.org
cnpm install

cnpm install monaco-editor
cnpm install monaco-editor-webpack-plugin

可在node_modules下看到其目錄結(jié)構(gòu)

monaco_lgx211

核心代碼如下所示

首先寫個(gè)組件遥皂,供其他頁(yè)面引入調(diào)用力喷,

CodeEditor.vue

<template>
  <div class="code-container" ref="container"></div>
</template>

<script>
  import * as monaco from "monaco-editor";
  let sqlStr =
    "ADD EXCEPT PERCENT ALL EXEC PLAN ALTER EXECUTE PRECISION AND EXISTS PRIMARY ANY EXIT PRINT AS FETCH PROC ASC FILE PROCEDURE AUTHORIZATION FILLFACTOR PUBLIC BACKUP FOR RAISERROR BEGIN FOREIGN READ BETWEEN FREETEXT READTEXT BREAK FREETEXTTABLE RECONFIGURE BROWSE FROM REFERENCES BULK FULL REPLICATION BY FUNCTION RESTORE CASCADE GOTO RESTRICT CASE GRANT RETURN CHECK GROUP REVOKE CHECKPOINT HAVING RIGHT CLOSE HOLDLOCK ROLLBACK CLUSTERED IDENTITY ROWCOUNT COALESCE IDENTITY_INSERT ROWGUIDCOL COLLATE IDENTITYCOL RULE COLUMN IF SAVE COMMIT IN SCHEMA COMPUTE INDEX SELECT CONSTRAINT INNER SESSION_USER CONTAINS INSERT SET CONTAINSTABLE INTERSECT SETUSER CONTINUE INTO SHUTDOWN CONVERT IS SOME CREATE JOIN STATISTICS CROSS KEY SYSTEM_USER CURRENT KILL TABLE CURRENT_DATE LEFT TEXTSIZE CURRENT_TIME LIKE THEN CURRENT_TIMESTAMP LINENO TO CURRENT_USER LOAD TOP CURSOR NATIONAL TRAN DATABASE NOCHECK TRANSACTION DBCC NONCLUSTERED TRIGGER DEALLOCATE NOT TRUNCATE DECLARE NULL TSEQUAL DEFAULT NULLIF UNION DELETE OF UNIQUE DENY OFF UPDATE DESC OFFSETS UPDATETEXT DISK ON USE DISTINCT OPEN USER DISTRIBUTED OPENDATASOURCE VALUES DOUBLE OPENQUERY VARYING DROP OPENROWSET VIEW DUMMY OPENXML WAITFOR DUMP OPTION WHEN ELSE OR WHERE END ORDER WHILE ERRLVL OUTER WITH ESCAPE OVER WRITETEXT";
  export default {
    name: "codeEditor",

    props: {
      options: {
        type: Object,
        default() {
          return {
            language: "java", // shell、sql演训、python
            readOnly: true // 不能編輯
          };
        }
      },

      value: {
        type: String,
        default: ""
      }
    },

    data() {
      return {
        monacoInstance: null,
        provider: null,
        hints: [
          "SELECT",
          "INSERT",
          "DELETE",
          "UPDATE",
          "CREATE TABLE",
          "DROP TABLE",
          "ALTER TABLE",
          "CREATE VIEW",
          "DROP VIEW",
          "CREATE INDEX",
          "DROP INDEX",
          "CREATE PROCEDURE",
          "DROP PROCEDURE",
          "CREATE TRIGGER",
          "DROP TRIGGER",
          "CREATE SCHEMA",
          "DROP SCHEMA",
          "CREATE DOMAIN",
          "ALTER DOMAIN",
          "DROP DOMAIN",
          "GRANT",
          "DENY",
          "REVOKE",
          "COMMIT",
          "ROLLBACK",
          "SET TRANSACTION",
          "DECLARE",
          "EXPLAN",
          "OPEN",
          "FETCH",
          "CLOSE",
          "PREPARE",
          "EXECUTE",
          "DESCRIBE",
          "FORM",
          "ORDER BY"
        ]
      };
    },
    created() {
      this.initHints();
    },
    mounted() {
      this.init();
    },
    beforeDestroy() {
      this.dispose();
    },

    methods: {
      dispose() {
        if (this.monacoInstance) {
          if (this.monacoInstance.getModel()) {
            this.monacoInstance.getModel().dispose();
          }
          this.monacoInstance.dispose();
          this.monacoInstance = null;
          if(this.provider){
            this.provider.dispose();
            this.provider = null
          }
        }
      },
      initHints() {
        let sqlArr = sqlStr.split(" ");
        this.hints = Array.from(new Set([...this.hints, ...sqlArr])).sort();
      },
      init() {
        let that = this;
        this.dispose();
        let createCompleters = textUntilPosition => {
          //過濾特殊字符
          let _textUntilPosition = textUntilPosition
            .replace(/[\*\[\]@\$\(\)]/g, "")
            .replace(/(\s+|\.)/g, " ");
          //切割成數(shù)組
          let arr = _textUntilPosition.split(" ");
          //取當(dāng)前輸入值
          let activeStr = arr[arr.length - 1];
          //獲得輸入值的長(zhǎng)度
          let len = activeStr.length;

          //獲得編輯區(qū)域內(nèi)已經(jīng)存在的內(nèi)容
          let rexp = new RegExp('([^\\w]|^)'+activeStr+'\\w*', "gim");
          let match = that.value.match(rexp);
          let _hints = !match ? [] : match.map(ele => {
            let rexp = new RegExp(activeStr, "gim");
            let search = ele.search(rexp);
            return ele.substr(search)
          })

          //查找匹配當(dāng)前輸入值的元素
          let hints = Array.from(new Set([...that.hints, ..._hints])).sort().filter(ele => {
            let rexp = new RegExp(ele.substr(0, len), "gim");
            return match && match.length === 1 && ele === activeStr || ele.length === 1
              ? false
              : activeStr.match(rexp);
          });
          //添加內(nèi)容提示
          let res = hints.map(ele => {
            return {
              label: ele,
              kind: that.hints.indexOf(ele) > -1 ? monaco.languages.CompletionItemKind.Keyword : monaco.languages.CompletionItemKind.Text,
              documentation: ele,
              insertText: ele
            };
          });
          return res;
        };
        this.provider = monaco.languages.registerCompletionItemProvider("sql", {
          provideCompletionItems(model, position) {
            var textUntilPosition = model.getValueInRange({
              startLineNumber: position.lineNumber,
              startColumn: 1,
              endLineNumber: position.lineNumber,
              endColumn: position.column
            });
            var suggestions = createCompleters(textUntilPosition);
            return {
              suggestions: suggestions
            };

            return createCompleters(textUntilPosition);
          }
        });

        // 初始化編輯器實(shí)例
        this.monacoInstance = monaco.editor.create(this.$refs["container"], {
          value: this.value,
          theme: "vs-dark",
          autoIndex: true,
          ...this.options
        });

        // 監(jiān)聽編輯器content變化事件
        this.monacoInstance.onDidChangeModelContent(() => {
          this.$emit("contentChange", this.monacoInstance.getValue());
        });
      }
    }
  };
</script>

<style lang="scss" scope>
  .code-container {
    width: 100%;
    height: 100%;
    overflow: hidden;
    border: 1px solid #eaeaea;
    .monaco-editor .scroll-decoration {
      box-shadow: none;
    }
  }
</style>

引入頁(yè)面弟孟,供本頁(yè)面使用

index.vue

<template>
  <div class="container">
    <code-editor
      :options="options"
      :value="content"
      @contentChange="contentChange"
      style="height: 400px; width: 600px;"
    ></code-editor>
  </div>
</template>

<script>
  import CodeEditor from "@/components/CodeEditor";
  export default {
    name: "SQLEditor",
    components: {
      CodeEditor
    },
    data() {
      return {
        content: "",
        options: {
          language: "sql",
          theme: 'vs',
          readOnly: false
        }
      };
    },
    created() {},
    methods: {
      // 綁定編輯器value值的變化
      contentChange(val) {
        this.content = val;
      }
    }
  };
</script>


<style scoped lang="scss">
  .container {
    text-align: left;
    padding: 10px;
  }
</style>

效果如下所示

代碼自動(dòng)提示效果,如下所示

monaco自動(dòng)提示_lgx211

代碼高亮效果样悟,代碼段折疊效果拂募,右側(cè)預(yù)覽效果如下所示

monaco代碼高亮折疊_lgx211
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市窟她,隨后出現(xiàn)的幾起案子陈症,更是在濱河造成了極大的恐慌,老刑警劉巖礁苗,帶你破解...
    沈念sama閱讀 216,372評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件爬凑,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡试伙,警方通過查閱死者的電腦和手機(jī)嘁信,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來疏叨,“玉大人潘靖,你說我怎么就攤上這事≡槁” “怎么了卦溢?”我有些...
    開封第一講書人閱讀 162,415評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)秀又。 經(jīng)常有香客問我单寂,道長(zhǎng),這世上最難降的妖魔是什么吐辙? 我笑而不...
    開封第一講書人閱讀 58,157評(píng)論 1 292
  • 正文 為了忘掉前任宣决,我火速辦了婚禮,結(jié)果婚禮上昏苏,老公的妹妹穿的比我還像新娘尊沸。我一直安慰自己,他們只是感情好贤惯,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評(píng)論 6 388
  • 文/花漫 我一把揭開白布洼专。 她就那樣靜靜地躺著,像睡著了一般孵构。 火紅的嫁衣襯著肌膚如雪屁商。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,125評(píng)論 1 297
  • 那天颈墅,我揣著相機(jī)與錄音蜡镶,去河邊找鬼溯职。 笑死,一個(gè)胖子當(dāng)著我的面吹牛帽哑,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播叹俏,決...
    沈念sama閱讀 40,028評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼妻枕,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了粘驰?” 一聲冷哼從身側(cè)響起屡谐,我...
    開封第一講書人閱讀 38,887評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎蝌数,沒想到半個(gè)月后愕掏,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,310評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡顶伞,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評(píng)論 2 332
  • 正文 我和宋清朗相戀三年饵撑,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片唆貌。...
    茶點(diǎn)故事閱讀 39,690評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡滑潘,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出锨咙,到底是詐尸還是另有隱情语卤,我是刑警寧澤,帶...
    沈念sama閱讀 35,411評(píng)論 5 343
  • 正文 年R本政府宣布酪刀,位于F島的核電站粹舵,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏骂倘。R本人自食惡果不足惜眼滤,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評(píng)論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望稠茂。 院中可真熱鬧柠偶,春花似錦、人聲如沸睬关。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)电爹。三九已至蔫仙,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間丐箩,已是汗流浹背摇邦。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評(píng)論 1 268
  • 我被黑心中介騙來泰國(guó)打工恤煞, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人施籍。 一個(gè)月前我還...
    沈念sama閱讀 47,693評(píng)論 2 368
  • 正文 我出身青樓居扒,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親丑慎。 傳聞我的和親對(duì)象是個(gè)殘疾皇子喜喂,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容