master
2022-02-14 1684d66eaf39f77980b987359f413d2ff5714940
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
<template>
    <div ref="editorRef" class="cl-codemirror">
        <textarea id="editor" class="cl-code" :height="height" :width="width"></textarea>
 
        <div class="cl-codemirror__tools">
            <el-button size="mini" @click="formatCode">格式化</el-button>
        </div>
    </div>
</template>
 
<script lang="ts">
import { defineComponent, nextTick, onMounted, ref, watch } from "vue";
import CodeMirror from "codemirror";
import beautifyJs from "js-beautify";
import "codemirror/lib/codemirror.css";
import "codemirror/addon/hint/show-hint.css";
import "codemirror/theme/hopscotch.css";
import "codemirror/addon/hint/javascript-hint";
import "codemirror/mode/javascript/javascript";
import { deepMerge } from "/@/cool/utils";
 
export default defineComponent({
    name: "cl-codemirror",
 
    props: {
        modelValue: null,
        height: String,
        width: String,
        options: Object
    },
 
    emits: ["update:modelValue", "load"],
 
    setup(props, { emit }) {
        const editorRef = ref<any>(null);
 
        let editor: any = null;
 
        // 获取内容
        function getValue() {
            if (editor) {
                return editor.getValue();
            } else {
                return "";
            }
        }
 
        // 设置内容
        function setValue(val?: string) {
            if (editor) {
                editor.setValue(val || "");
            }
        }
 
        // 格式化
        function formatCode() {
            if (editor) {
                editor.setValue(beautifyJs(getValue()));
            }
        }
 
        // 监听内容变化
        watch(
            () => props.modelValue,
            (val: string) => {
                if (editor && val != getValue()) {
                    setValue(val);
                }
            }
        );
 
        onMounted(function () {
            nextTick(() => {
                // 实例化
                editor = CodeMirror.fromTextArea(
                    editorRef.value.querySelector("#editor"),
                    deepMerge(
                        {
                            mode: "javascript",
                            theme: "hopscotch",
                            styleActiveLine: true,
                            lineNumbers: true,
                            lineWrapping: true,
                            indentWithTabs: true,
                            indentUnit: 4,
                            extraKeys: { Ctrl: "autocomplete" },
                            foldGutter: true,
                            autofocus: true,
                            matchBrackets: true,
                            autoCloseBrackets: true,
                            gutters: [
                                "CodeMirror-linenumbers",
                                "CodeMirror-foldgutter",
                                "CodeMirror-lint-markers"
                            ]
                        },
                        props.options
                    )
                );
 
                // 输入监听
                editor.on("change", (e: any) => {
                    emit("update:modelValue", e.getValue());
                });
 
                // 设置内容
                setValue(props.modelValue);
 
                // 格式化
                formatCode();
 
                // 加载回调
                emit("load", editor);
 
                // 设置编辑框大小
                editor.setSize(props.width || "auto", props.height || "auto");
            });
        });
 
        return {
            editorRef,
            formatCode
        };
    }
});
</script>
 
<style lang="scss">
.cl-codemirror {
    border-radius: 3px;
    border: 1px solid #dcdfe6;
    box-sizing: border-box;
    border-radius: 3px;
    line-height: 150%;
 
    &__tools {
        background-color: #322931;
        padding: 10px;
        border-top: 1px solid #444;
    }
}
</style>