vben
2021-08-24 56a966cfbf8db5b29a42185f0f25a0e800c30dbb
src/components/CodeEditor/src/codemirror/CodeMirror.vue
@@ -1,126 +1,105 @@
<template>
  <div class="relative !h-full w-full overflow-hidden" ref="el"> </div>
  <div class="relative !h-full w-full overflow-hidden" ref="el"></div>
</template>
<script lang="ts">
  import {
    ref,
    onMounted,
    onUnmounted,
    watchEffect,
    watch,
    defineComponent,
    unref,
    nextTick,
  } from 'vue';
<script lang="ts" setup>
  import { ref, onMounted, onUnmounted, watchEffect, watch, unref, nextTick } from 'vue';
  import { useDebounceFn } from '@vueuse/core';
  import { useAppStore } from '/@/store/modules/app';
  import { useWindowSizeFn } from '/@/hooks/event/useWindowSizeFn';
  import CodeMirror from 'codemirror';
  // css
  import './codemirror.css';
  import 'codemirror/theme/idea.css';
  import 'codemirror/theme/material-palenight.css';
  // modes
  import 'codemirror/mode/javascript/javascript';
  import 'codemirror/mode/css/css';
  import 'codemirror/mode/htmlmixed/htmlmixed';
  export default defineComponent({
    props: {
      mode: {
        type: String,
        default: 'application/json',
      },
      value: {
        type: String,
        default: '',
      },
      readonly: {
        type: Boolean,
        default: false,
      },
  const props = defineProps({
    mode: { type: String, default: 'application/json' },
    value: { type: String, default: '' },
    readonly: { type: Boolean, default: false },
  });
  const emit = defineEmits(['change']);
  const el = ref();
  let editor: Nullable<CodeMirror.Editor>;
  const debounceRefresh = useDebounceFn(refresh, 100);
  const appStore = useAppStore();
  watch(
    () => props.value,
    async (value) => {
      await nextTick();
      const oldValue = editor?.getValue();
      if (value !== oldValue) {
        editor?.setValue(value ? value : '');
      }
    },
    emits: ['change'],
    setup(props, { emit }) {
      const el = ref();
      let editor: Nullable<CodeMirror.Editor>;
    { flush: 'post' },
  );
      const debounceRefresh = useDebounceFn(refresh, 100);
      const appStore = useAppStore();
  watchEffect(() => {
    editor?.setOption('mode', props.mode);
  });
      watch(
        () => props.value,
        async (v) => {
          await nextTick();
          const oldValue = editor?.getValue();
          if (v !== oldValue) {
            editor?.setValue(v ? v : '');
          }
        },
        { flush: 'post' }
      );
      watchEffect(() => {
        editor?.setOption('mode', props.mode);
      });
      watch(
        () => appStore.getDarkMode,
        async () => {
          setTheme();
        },
        {
          immediate: true,
        }
      );
      function setTheme() {
        unref(editor)?.setOption(
          'theme',
          appStore.getDarkMode === 'light' ? 'idea' : 'material-palenight'
        );
      }
      function refresh() {
        editor?.refresh();
      }
      async function init() {
        const addonOptions = {
          autoCloseBrackets: true,
          autoCloseTags: true,
          foldGutter: true,
          gutters: ['CodeMirror-linenumbers'],
        };
        editor = CodeMirror(el.value!, {
          value: '',
          mode: props.mode,
          readOnly: props.readonly,
          tabSize: 2,
          theme: 'material-palenight',
          lineWrapping: true,
          lineNumbers: true,
          ...addonOptions,
        });
        editor?.setValue(props.value);
        setTheme();
        editor?.on('change', () => {
          emit('change', editor?.getValue());
        });
      }
      onMounted(async () => {
        await nextTick();
        init();
        window.addEventListener('resize', debounceRefresh);
      });
      onUnmounted(() => {
        window.removeEventListener('resize', debounceRefresh);
        editor = null;
      });
      return { el };
  watch(
    () => appStore.getDarkMode,
    async () => {
      setTheme();
    },
    {
      immediate: true,
    },
  );
  function setTheme() {
    unref(editor)?.setOption(
      'theme',
      appStore.getDarkMode === 'light' ? 'idea' : 'material-palenight',
    );
  }
  function refresh() {
    editor?.refresh();
  }
  async function init() {
    const addonOptions = {
      autoCloseBrackets: true,
      autoCloseTags: true,
      foldGutter: true,
      gutters: ['CodeMirror-linenumbers'],
    };
    editor = CodeMirror(el.value!, {
      value: '',
      mode: props.mode,
      readOnly: props.readonly,
      tabSize: 2,
      theme: 'material-palenight',
      lineWrapping: true,
      lineNumbers: true,
      ...addonOptions,
    });
    editor?.setValue(props.value);
    setTheme();
    editor?.on('change', () => {
      emit('change', editor?.getValue());
    });
  }
  onMounted(async () => {
    await nextTick();
    init();
    useWindowSizeFn(debounceRefresh);
  });
  onUnmounted(() => {
    editor = null;
  });
</script>