codeEditor

168 阅读1分钟
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Vue2 Ace Editor</title>
  <!-- 引入 Vue.js -->
  <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.min.js"></script>
  <!-- 引入 vue2-ace-editor -->
  <script src="https://unpkg.com/vue2-ace-editor@0.0.13/dist/vue2-ace-editor.min.js"></script>
  <!-- 引入 Ace Editor -->
  <script src="https://cdn.jsdelivr.net/npm/ace-builds@1.4.12/src-min-noconflict/ace.js"></script>
  <!-- 引入 Ace Editor 主题 -->
  <script src="https://cdn.jsdelivr.net/npm/ace-builds@1.4.12/src-min-noconflict/theme-monokai.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/ace-builds@1.4.12/src-min-noconflict/theme-dracula.js"></script>
  <!-- 引入 Ace Editor 模式 -->
  <script src="https://cdn.jsdelivr.net/npm/ace-builds@1.4.12/src-min-noconflict/mode-javascript.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/ace-builds@1.4.12/src-min-noconflict/mode-json.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/ace-builds@1.4.12/src-min-noconflict/mode-html.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/ace-builds@1.4.12/src-min-noconflict/mode-css.js"></script>
  <!-- 引入 Element UI -->
  <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
  <script src="https://unpkg.com/element-ui/lib/index.js"></script>
  <style>
    .el-card__header {
      padding: 20px;
    }
    .el-select {
      width: 130px;
      margin-right: 20px;
    }
    .el-button {
      margin-right: 10px;
    }
    .editor-container {
      border: 1px solid #e8e8e8;
      min-height: 300px;
    }
  </style>
</head>
<body>
  <div id="app">
    <div ref="screenFull">
      <el-card class="box-card" shadow="hover">
        <div slot="header" class="clearfix">
          <span>代码编辑器</span>
        </div>
        <div style="display: flex; width: 100%; margin-bottom: 10px;">
          <el-select
            v-model="valueTheme"
            placeholder="选择主题"
            filterable
            clearable
            @change="selectTheme"
          >
            <el-option
              v-for="item in listTheme"
              :key="item"
              :label="item"
              :value="item">
            </el-option>
          </el-select>

          <el-select
            v-model="valueCodeLang"
            placeholder="选择语言"
            filterable
            clearable
            @change="selectLang"
          >
            <el-option
              v-for="item in listCodeLang"
              :key="item"
              :label="item"
              :value="item">
            </el-option>
          </el-select>

          <el-select
            v-model="valueFontSize"
            placeholder="字体大小"
            filterable
            clearable
            @change="selectFontSize"
          >
            <el-option
              v-for="item in listFontSize"
              :key="item"
              :label="item"
              :value="item">
            </el-option>
          </el-select>

          <el-button type="primary" icon="el-icon-document-copy" @click="copyCode">复制</el-button>
          <el-button v-if="valueCodeLang === 'json'" type="primary" icon="el-icon-view" @click="formatCode">美化</el-button>
          <el-button type="primary" :icon=" fullScreen ? 'el-icon-full-screen' : 'el-icon-crop' " @click="screen">{{ fullScreen ? '退出全屏' : '全屏' }}</el-button>
        </div>
        <div class="editor-container">
          <editor
            ref="aceEditor"
            v-model="content"
            @init="editorInit"
            width="100%"
            :height="editorHight + 'px'"
            :lang="lang"
            :theme="theme"
            :options="{
              enableBasicAutocompletion: true,
              enableSnippets: true,
              enableLiveAutocompletion: true,
              tabSize: 4,
              fontSize: fontSize,
              readOnly: readOnly,
              showPrintMargin: false
            }"
          ></editor>
        </div>
      </el-card>
    </div>
  </div>

  <script>
    // 注册组件
    Vue.component('editor', window['vue2-ace-editor']);
    
    new Vue({
      el: '#app',
      data() {
        return {
          listTheme: [
            'clouds',
            'clouds_midnight',
            'dracula',
            'chrome',
            'chaos',
            'xcode',
            'monokai',
            'ambiance',
            'dreamweaver',
            'eclipse',
            'github',
            'idle_fingers'
          ],
          listCodeLang: [
            'json',
            'yaml',
            'xml',
            'java',
            'text',
            'javascript',
            'scheme',
            'lua',
            'mysql',
            'perl',
            'powershell',
            'python',
            'ruby',
            'sql',
            'hjson',
            'ini'
          ],
          listFontSize: [10, 12, 14, 16, 20],
          content: '',
          valueTheme: 'clouds',
          valueCodeLang: 'json',
          valueFontSize: 12,
          theme: 'clouds',
          lang: 'json',
          fontSize: 12,
          tmpFontSize: 12,
          fullScreen: false,
          unFullEditorHight: 300,
          editorHight: 300,
          appendToBody: true,
          readOnly: false
        };
      },
      methods: {
        selectTheme(newValue) {
          this.theme = newValue;
        },
        selectLang(newValue) {
          this.lang = newValue;
        },
        selectFontSize(newValue) {
          this.fontSize = newValue;
          this.tmpFontSize = newValue;
        },
        editorInit() {
          const langTools = ace.require('ace/ext/language_tools');
          ace.config.setModuleUrl('ace/ext/language_tools', 'https://cdn.jsdelivr.net/npm/ace-builds@1.4.12/src-min-noconflict/ext-language_tools.js');
          ace.config.setModuleUrl('ace/ext/beautify', 'https://cdn.jsdelivr.net/npm/ace-builds@1.4.12/src-min-noconflict/ext-beautify.js');
          langTools.addCompleter({
            getCompletions: (editor, session, pos, prefix, callback) => {
              callback(null, []);
            }
          });
        },
        copyCode() {
          const code = this.$refs.aceEditor.editor.getValue();
          if (navigator.clipboard) {
            navigator.clipboard.writeText(code);
            this.$message.success('复制成功');
          } else {
            this.$message.error('您的浏览器不支持自动复制,请手动复制');
          }
        },
        formatCode() {
          const code = this.$refs.aceEditor.editor.getValue();
          if (code !== '') {
            const string = JSON.stringify(JSON.parse(code), null, 2);
            this.$refs.aceEditor.editor.setValue(string);
          }
        },
        screen() {
          this.valueFontSize = this.fontSize = 12;
          const element = this.$refs.screenFull;
          if (this.fullScreen) {
            this.appendToBody = true;
            this.editorHight = this.unFullEditorHight;
            if (document.exitFullscreen) {
              document.exitFullscreen();
            } else if (document.webkitCancelFullScreen) {
              document.webkitCancelFullScreen();
            } else if (document.mozCancelFullScreen) {
              document.mozCancelFullScreen();
            } else if (document.msExitFullscreen) {
              document.msExitFullscreen();
            }
          } else {
            this.appendToBody = false;
            this.editorHight = window.screen.availHeight - 50;
            if (element.requestFullscreen) {
              element.requestFullscreen();
            } else if (element.webkitRequestFullScreen) {
              element.webkitRequestFullScreen();
            } else if (element.mozRequestFullScreen) {
              element.mozRequestFullScreen();
            } else if (element.msRequestFullscreen) {
              element.msRequestFullscreen();
            }
          }
          this.fullScreen = !this.fullScreen;
        }
      }
    });
  </script>
</body>
</html>