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