效果图

实现代码
<script src="https://lf26-cdn-tos.bytecdntp.com/cdn/expire-1-M/vue/2.6.14/vue.min.js" type="application/javascript"></script>
<script src="https://lf9-cdn-tos.bytecdntp.com/cdn/expire-1-M/ace/1.4.14/ace.js" type="application/javascript"></script>
<script src="https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/ace/1.4.14/ext-language_tools.min.js" type="application/javascript"></script>
<style>
body {
font-size: 14px;
color: #222;
background: #f7f7f7;
}
* {
-webkit-border-radius: 0 !important;
-moz-border-radius: 0 !important;
border-radius: 0 !important;
}
#app {
height: 100%;
width: 100%;
}
#wrapper {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
#toolbox {
height: 3%;
display: flex;
align-items: center;
}
#toolbox button,
select {
margin: 2px 5px 2px;
}
#editor {
height: 97%;
width: 100%;
}
</style>
<div id="app">
<div id="wrapper">
<div id="toolbox">
<button @click="btnClick($event,'fullscreen')" title="Fullscreen">Fullscreen</button>
<button @click="btnClick($event,'find')" title="Search">Search</button>
<button @click="btnClick($event,'undo')" title="Undo">Undo</button>
<button @click="btnClick($event,'redo')" title="Redo">Redo</button>
<button @click="btnClick($event,'wrap')" title="Wrap">Wrap</button>
<select v-model="theme" title="Select Theme" @change="change($event,'theme')">
<option v-for="(v, k) in aceTheme" :key="k" :value="v">{{k}}</option>
</select>
<select v-model="mode" title="Select Document Type" @change="change($event,'mode')">
<option v-for="(v, k) in aceMode" :key="k" :value="v">{{k}}</option>
</select>
<select v-model="fontSize" title="Select Font Size" @change="change($event,'fontSize')">
<option v-for="(v, k) in aceFontSize" :key="k" :value="v">{{k}}</option>
</select>
</div>
<div id="editor" contenteditable="true"></div>
</div>
</div>
<script>
ace.config.set("basePath", "https://lf9-cdn-tos.bytecdntp.com/cdn/expire-1-M/ace/1.4.14/");
new Vue({
el: "#app",
data() {
return {
mode: "text",
theme: "monokai",
fontSize: 14,
editor: null,
aceTheme: {
Chaos: "chaos",
Textmate: "textmate",
Ambiance: "ambiance",
Merbivore: "merbivore",
Xcode: "xcode",
Clouds: "clouds",
Sqlserver: "sqlserver",
Eclipse: "eclipse",
TomorrowNightBlue: "tomorrow_night_blue",
Twilight: "twilight",
Dreamweaver: "dreamweaver",
Cobalt: "cobalt",
TomorrowNightEighties: "tomorrow_night_eighties",
KrTheme: "kr_theme",
PastelOnDark: "pastel_on_dark",
Katzenmilch: "katzenmilch",
Kuroir: "kuroir",
Dawn: "dawn",
MerbivoreSoft: "merbivore_soft",
Gruvbox: "gruvbox",
Chrome: "chrome",
Monokai: "monokai",
Gob: "gob",
TomorrowNightBright: "tomorrow_night_bright",
SolarizedDark: "solarized_dark",
VibrantInk: "vibrant_ink",
SolarizedLight: "solarized_light",
Github: "github",
IdleFingers: "idle_fingers",
Tomorrow: "tomorrow",
Terminal: "terminal",
OneDark: "one_dark",
TomorrowNight: "tomorrow_night",
Dracula: "dracula",
NordDark: "nord_dark",
CloudsMidnight: "clouds_midnight",
CrimsonEditor: "crimson_editor",
MonoIndustrial: "mono_industrial",
Iplastic: "iplastic",
},
aceMode: {
Java: "java",
CSS: "css",
SVG: "svg",
Powershell: "powershell",
JSP: "jsp",
SASS: "sass",
JSON: "json",
HTML: "html",
Text: "text",
Groovy: "groovy",
FreeMarker: "ftl",
YAML: "yaml",
Kotlin: "kotlin",
Stylus: "stylus",
SQL: "sql",
SH: "sh",
Typescript: "typescript",
SCSS: "scss",
XML: "xml",
JavaScript: "javascript",
MySQL: "mysql",
PHP: "php",
Markdown: "markdown",
Python: "python",
},
aceFontSize: {
12: 12,
14: 14,
15: 15,
16: 16,
17: 17,
18: 18,
20: 20,
22: 22,
24: 24,
26: 26,
30: 30,
},
};
},
mounted() {
let editor = ace.edit("editor");
editor.getSession().setUseWrapMode(false);
editor.setShowPrintMargin(false);
editor.setAutoScrollEditorIntoView(true);
editor.getSession().setMode("ace/mode/" + this.mode);
editor.setTheme("ace/theme/" + this.theme);
editor.setFontSize(parseInt(this.fontSize));
editor.setOptions({
showGutter: true,
enableBasicAutocompletion: true,
enableSnippets: true,
enableLiveAutocompletion: true,
});
this.editor = editor;
},
methods: {
btnClick(e, cmdValue) {
e.preventDefault();
editor = this.editor;
if (cmdValue === "wrap") {
editor.setOption("wrap", editor.getOption("wrap") == "off" ? "free" : "off");
} else if (cmdValue === "fullscreen") {
this.fullscreen();
} else {
this.aceCommend(cmdValue);
}
},
change(e, selectionType) {
e.preventDefault();
editor = this.editor;
if (selectionType == "mode") {
editor.getSession().setMode("ace/mode/" + this.mode);
} else if (selectionType == "theme") {
editor.setTheme("ace/theme/" + this.theme);
} else if (selectionType == "fontSize") {
editor.setFontSize(parseInt(this.fontSize));
}
},
aceCommend(cmd) {
this.editor.commands.exec(cmd, this.editor);
},
fullscreen() {
((void 0 !== document.fullScreenElement && null === document.fullScreenElement) ||
(void 0 !== document.msFullscreenElement && null === document.msFullscreenElement) ||
(void 0 !== document.mozFullScreen && !document.mozFullScreen) ||
(void 0 !== document.webkitIsFullScreen && !document.webkitIsFullScreen)) &&
(editor.container.requestFullScreen
? editor.container.requestFullScreen()
: editor.container.mozRequestFullScreen
? editor.container.mozRequestFullScreen()
: editor.container.webkitRequestFullScreen
? editor.container.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT)
: editor.container.msRequestFullscreen && editor.container.msRequestFullscreen());
},
},
});
</script>