1+ <template >
2+ <div ref =" editorEl" class =" ace-editor" ></div >
3+ </template >
4+
5+ <script setup>
6+ import { ref , onMounted , watch , onUnmounted } from ' vue' ;
7+ import ace from ' ace-builds' ;
8+ import ' ace-builds/src-noconflict/theme-monokai' ; // 主题
9+ import ' ace-builds/src-noconflict/mode-javascript' ; // 语言模式
10+
11+ const props = defineProps ({
12+ modelValue: String , // v-model 绑定
13+ mode: { type: String , default: ' javascript' }, // 语言模式
14+ theme: { type: String , default: ' monokai' }, // 主题
15+ readOnly: { type: Boolean , default: false }, // 只读模式
16+ vid: { type: [String , Number ], default: ' ' }
17+ });
18+
19+ const emit = defineEmits ([' update:modelValue' ]);
20+ const editorEl = ref (null );
21+ let editor = null ;
22+
23+ onMounted (() => {
24+ // 初始化编辑器
25+ editor = ace .edit (editorEl .value , {
26+ value: props .modelValue || ' ' ,
27+ mode: ` ace/mode/${ props .mode } ` ,
28+ theme: ` ace/theme/${ props .theme } ` ,
29+ readOnly: props .readOnly ,
30+ fontSize: 14 ,
31+ });
32+
33+ // 监听内容变化
34+ editor .session .on (' change' , () => {
35+ const value = editor .getValue ();
36+ if (value .trim ().startsWith (' {' ) || value .trim ().startsWith (' [' )) {
37+ try {
38+ const formatted = JSON .stringify (JSON .parse (value), null , 2 );
39+ if (value !== formatted) {
40+ editor .setValue (formatted, 1 ); // 第二个参数 1 表示不记录历史
41+ }
42+ } catch (e) {
43+ // 忽略非 JSON 内容
44+ }
45+ }
46+ emit (' update:modelValue' , value);
47+ });
48+ });
49+
50+ // 监听外部值变化
51+ watch (() => props .modelValue , (newVal ) => {
52+ if (editor && newVal !== editor .getValue ()) {
53+ editor .setValue (newVal);
54+ }
55+ });
56+
57+ // 销毁编辑器
58+ onUnmounted (() => {
59+ editor? .destroy ();
60+ });
61+ < / script>
62+
63+ < style scoped>
64+ .ace - editor {
65+ width: 100 % ;
66+ height: 500px ;
67+ border: 1px solid #ddd;
68+ }
69+ < / style>
0 commit comments