vben
2021-08-24 56a966cfbf8db5b29a42185f0f25a0e800c30dbb
提交 | 用户 | age
a81268 1 <template>
56a966 2   <div class="relative !h-full w-full overflow-hidden" ref="el"></div>
a81268 3 </template>
V 4
8fa601 5 <script lang="ts" setup>
V 6   import { ref, onMounted, onUnmounted, watchEffect, watch, unref, nextTick } from 'vue';
a81268 7   import { useDebounceFn } from '@vueuse/core';
V 8   import { useAppStore } from '/@/store/modules/app';
55e9d9 9   import { useWindowSizeFn } from '/@/hooks/event/useWindowSizeFn';
a81268 10   import CodeMirror from 'codemirror';
55e9d9 11   // css
a81268 12   import './codemirror.css';
V 13   import 'codemirror/theme/idea.css';
14   import 'codemirror/theme/material-palenight.css';
15   // modes
16   import 'codemirror/mode/javascript/javascript';
17   import 'codemirror/mode/css/css';
18   import 'codemirror/mode/htmlmixed/htmlmixed';
55e9d9 19
8fa601 20   const props = defineProps({
55e9d9 21     mode: { type: String, default: 'application/json' },
V 22     value: { type: String, default: '' },
23     readonly: { type: Boolean, default: false },
8fa601 24   });
55e9d9 25
8fa601 26   const emit = defineEmits(['change']);
a81268 27
8fa601 28   const el = ref();
V 29   let editor: Nullable<CodeMirror.Editor>;
a81268 30
8fa601 31   const debounceRefresh = useDebounceFn(refresh, 100);
V 32   const appStore = useAppStore();
a81268 33
8fa601 34   watch(
V 35     () => props.value,
36     async (value) => {
37       await nextTick();
38       const oldValue = editor?.getValue();
39       if (value !== oldValue) {
40         editor?.setValue(value ? value : '');
a81268 41       }
V 42     },
56a966 43     { flush: 'post' },
8fa601 44   );
V 45
46   watchEffect(() => {
47     editor?.setOption('mode', props.mode);
48   });
49
50   watch(
51     () => appStore.getDarkMode,
52     async () => {
53       setTheme();
54     },
55     {
56       immediate: true,
56a966 57     },
8fa601 58   );
V 59
60   function setTheme() {
61     unref(editor)?.setOption(
62       'theme',
56a966 63       appStore.getDarkMode === 'light' ? 'idea' : 'material-palenight',
8fa601 64     );
V 65   }
66
67   function refresh() {
68     editor?.refresh();
69   }
70
71   async function init() {
72     const addonOptions = {
73       autoCloseBrackets: true,
74       autoCloseTags: true,
75       foldGutter: true,
76       gutters: ['CodeMirror-linenumbers'],
77     };
78
79     editor = CodeMirror(el.value!, {
80       value: '',
81       mode: props.mode,
82       readOnly: props.readonly,
83       tabSize: 2,
84       theme: 'material-palenight',
85       lineWrapping: true,
86       lineNumbers: true,
87       ...addonOptions,
88     });
89     editor?.setValue(props.value);
90     setTheme();
91     editor?.on('change', () => {
92       emit('change', editor?.getValue());
93     });
94   }
95
96   onMounted(async () => {
97     await nextTick();
98     init();
99     useWindowSizeFn(debounceRefresh);
100   });
101
102   onUnmounted(() => {
103     editor = null;
a81268 104   });
V 105 </script>