vue3中使用 codemirror 6

在最近的一個(gè)項(xiàng)目中想要做一個(gè)sql在線編輯的編輯器,由于項(xiàng)目中vue已經(jīng)升級(jí)的到了vue3,使用codemirror 5總是會(huì)發(fā)生各種錯(cuò)誤.索性就直接使用codemirror 6.codemirror 6使用TypeScript編寫,與vue3的 結(jié)合相當(dāng)融洽.接下來看一下具體的實(shí)現(xiàn)過程

codemirror.vue

<template>
  <div ref="codemirror" class="codemirror"></div>
</template>

<script lang="ts">
  import { EditorView, keymap } from '@codemirror/view';
  import { EditorState } from '@codemirror/state';
  import { history, historyKeymap } from '@codemirror/history';
  import { standardKeymap, insertTab } from '@codemirror/commands';
  import { lineNumbers } from '@codemirror/gutter';
  import { sql, MySQL } from '@codemirror/lang-sql';
  import { oneDarkTheme, oneDarkHighlightStyle } from '@codemirror/theme-one-dark';
  import { autocompletion } from '@codemirror/autocomplete';
  import { ref, watch } from 'vue';
  import { SqlType } from '/@/views/index';
  import { useStore } from 'vuex';
  // 數(shù)據(jù)庫類型, 高度, 重載.(監(jiān)聽stroe,destory后create)
  //獲取props
  export default {
    props: {
      sqlType: {
        required: true,
        type: String,
      },
      initHeight: {
        default: '300px',
        type: String,
      },
      initDoc: {
        default: '',
        type: String,
      },
      editable: {
        default: true,
        type: Boolean,
      },
    },
    setup(props) {
      const { state } = useStore();

      let editorView = ref<EditorView>();
      const codemirror = ref(null);
      const sqlType = {
        [SqlType.MYSQL]: MySQL,
      };
      let startState;
      const createEditor = (editorContainer, doc) => {
        if (typeof editorView.value !== 'undefined') {
          editorView.value.destroy();
        }
        startState = EditorState.create({
          //doc為編輯器內(nèi)容
          doc: doc,
          extensions: [
            history(),
            oneDarkTheme,
            keymap.of([
              ...standardKeymap,
              ...historyKeymap,
              // Tab Keymap
              {
                key: 'Tab',
                run: insertTab,
              },
            ]),
            sql({
              dialect: sqlType[props.sqlType],
              schema: state.common[`${props.sqlType}Content`],
            }),
            lineNumbers(),
            oneDarkHighlightStyle,
            autocompletion({ activateOnTyping: true }),
            EditorView.editable.of(props.editable),
          ],
        });
        editorView.value = new EditorView({
          state: startState,
          parent: editorContainer,
        });
      };
      //獲取編輯器里的文本內(nèi)容
      const getEditorDoc = (): string | null => {
        return (editorView.value as EditorView).state.doc.toString();
        // return (editorView.value as EditorView).contentDOM.textContent;
      };
      //監(jiān)聽對(duì)應(yīng)sql的代碼補(bǔ)全信息,如果更新,則重置editor
      watch(
        () => state.common[`${props.sqlType}Content`],
        () => {
          let doc = (editorView.value as EditorView).state.doc.toString() ?? '';
          const editorContainer = codemirror.value;
          createEditor(editorContainer, doc);
        }
      );
      return {
        createEditor,
        getEditorDoc,
        editorView,
      };
    },
    mounted() {
      let doc = (this as any).$props.initDoc;
      const editorContainer = (this as any).$refs.codemirror;
      (this as any).createEditor(editorContainer, doc);
    },
    methods: {
      reloadEditor({ doc }) {
        //更新編輯器里的文檔
        let text = (this as any).editorView.state.doc.toString();
        (this as any).editorView.dispatch({
          changes: { from: 0, to: text.length, insert: doc },
        });
      },
      formatEditorDoc() {
        let text = (this as any).editorView.state.doc.toString();
        let to = text.length;
        text = text.replaceAll(';', ';\r\n');
        let i = 0;
        let newText = '';
        let needNewLine = 50;
        while (i < text.length) {
          let modStr = text.substring(i);
          let namespace = modStr.indexOf(' ');
          let curText = modStr.substring(0, namespace + 1);

          if (newText.length - newText.lastIndexOf('\n') > needNewLine) {
            newText += curText + '\r\n';
          } else {
            newText += curText;
          }
          if (namespace === -1) {
            i = text.length + 1;
            newText += modStr;
          }
          i = namespace + i + 1;
        }

        (this as any).editorView.dispatch({
          changes: { from: 0, to: to, insert: newText },
        });
      },
    },
  };
</script>
<style>
  /* 這個(gè)$props沒有寫錯(cuò),不要改 */
  .cm-editor {
    height: v-bind('$props.initHeight');
    font-size: 18px;
  }
</style>
<style lang="less" scoped></style>

store.vue

const state = {
  //mysql自動(dòng)補(bǔ)全提示內(nèi)容,key為表名,數(shù)組內(nèi)為列名
  MYSQLContent: {
    apom: ['user', 'app_user', 'app_user_user'],
  },
};
const mutations = {
  setMysqlTableContent(state,data) {
    state.MYSQLContent = { ...state.MYSQLContent, ...data };
  },
};
export default {
  state,
  mutations,
};

index.vue

  <codemirror :sql-type="SqlType.MYSQL" :init-doc="'select * from table;'"></codemirror>

最后看一下效果

image.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市降允,隨后出現(xiàn)的幾起案子恩闻,更是在濱河造成了極大的恐慌,老刑警劉巖剧董,帶你破解...
    沈念sama閱讀 221,888評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件幢尚,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡翅楼,警方通過查閱死者的電腦和手機(jī)尉剩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,677評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來毅臊,“玉大人理茎,你說我怎么就攤上這事」苕遥” “怎么了皂林?”我有些...
    開封第一講書人閱讀 168,386評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)蚯撩。 經(jīng)常有香客問我础倍,道長(zhǎng),這世上最難降的妖魔是什么求厕? 我笑而不...
    開封第一講書人閱讀 59,726評(píng)論 1 297
  • 正文 為了忘掉前任著隆,我火速辦了婚禮扰楼,結(jié)果婚禮上呀癣,老公的妹妹穿的比我還像新娘。我一直安慰自己弦赖,他們只是感情好项栏,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,729評(píng)論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著蹬竖,像睡著了一般沼沈。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上币厕,一...
    開封第一講書人閱讀 52,337評(píng)論 1 310
  • 那天列另,我揣著相機(jī)與錄音,去河邊找鬼旦装。 笑死页衙,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播店乐,決...
    沈念sama閱讀 40,902評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼艰躺,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了眨八?” 一聲冷哼從身側(cè)響起腺兴,我...
    開封第一講書人閱讀 39,807評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎廉侧,沒想到半個(gè)月后页响,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,349評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡伏穆,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,439評(píng)論 3 340
  • 正文 我和宋清朗相戀三年拘泞,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片枕扫。...
    茶點(diǎn)故事閱讀 40,567評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡陪腌,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出烟瞧,到底是詐尸還是另有隱情诗鸭,我是刑警寧澤,帶...
    沈念sama閱讀 36,242評(píng)論 5 350
  • 正文 年R本政府宣布参滴,位于F島的核電站强岸,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏砾赔。R本人自食惡果不足惜蝌箍,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,933評(píng)論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望暴心。 院中可真熱鬧妓盲,春花似錦、人聲如沸专普。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,420評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽檀夹。三九已至筋粗,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間炸渡,已是汗流浹背娜亿。 一陣腳步聲響...
    開封第一講書人閱讀 33,531評(píng)論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蚌堵,地道東北人买决。 一個(gè)月前我還...
    沈念sama閱讀 48,995評(píng)論 3 377
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國和親策州。 傳聞我的和親對(duì)象是個(gè)殘疾皇子瘸味,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,585評(píng)論 2 359

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