美文网首页
vue3中使用 codemirror 6

vue3中使用 codemirror 6

作者: 不看盛景不叙深情 | 来源:发表于2021-12-24 16:33 被阅读0次

    在最近的一个项目中想要做一个sql在线编辑的编辑器,由于项目中vue已经升级的到了vue3,使用codemirror 5总是会发生各种错误.索性就直接使用codemirror 6.codemirror 6使用TypeScript编写,与vue3的 结合相当融洽.接下来看一下具体的实现过程

    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';
      // 数据库类型, 高度, 重载.(监听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为编辑器内容
              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,
            });
          };
          //获取编辑器里的文本内容
          const getEditorDoc = (): string | null => {
            return (editorView.value as EditorView).state.doc.toString();
            // return (editorView.value as EditorView).contentDOM.textContent;
          };
          //监听对应sql的代码补全信息,如果更新,则重置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>
      /* 这个$props没有写错,不要改 */
      .cm-editor {
        height: v-bind('$props.initHeight');
        font-size: 18px;
      }
    </style>
    <style lang="less" scoped></style>
    
    

    store.vue

    const state = {
      //mysql自动补全提示内容,key为表名,数组内为列名
      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

    相关文章

      网友评论

          本文标题:vue3中使用 codemirror 6

          本文链接:https://www.haomeiwen.com/subject/dfolqrtx.html