使用vue2-ace-editor实现可选择的代码编辑器

最近在琢磨前端,因项目中需要在页面上编辑代码,所以需要写一个代码编辑器供用户使用。找了几个编辑器相关的组件,对比了下感觉还是vue2-ace-editor用着舒服,写了demo供大家参考。

由于我的项目使用的是vue2,二开鹅厂的bk-ci(蓝盾),因此基础组件使用的是bk组件。大家可以把选择框、按钮这些替换成自己使用的组件(如element-ui等)

组件已经封装好可以直接到手使用,支持更换主题、切换语言、缩进、搜索和替换(编辑器内Ctrl+F)、复制,json美化等...

效果图:

首先,到项目中安装插件:

npm install --save-dev vue2-ace-editor

安装成功后,引用组件,可在main.js中全局引用:

import Editor from 'vue2-ace-editor'
Vue.component('editor', Editor)

或直接在代码中局部引用(如我这里直接代码中引用):

html 复制代码
<template>
    <div>
        <bk-card title="代码编辑器">
            <div style="display: flex;  width: 100%; margin-right: 20px; margin-bottom: 10px;">
                
                <bk-select
                    :disabled="false"
                    placeholder="请选择主题"
                    search-placeholder="搜索主题"
                    v-model="valueTheme"
                    style="width: 150px; margin-right: 20px;"
                    @change="selectTheme"
                    searchable>
                    <bk-option v-for="option in listTheme"
                        :key="option"
                        :id="option"
                        :name="option">
                    </bk-option>
                </bk-select>

                <bk-select
                    :disabled="false"
                    placeholder="请选择语言"
                    search-placeholder="搜索语言"
                    v-model="valueCodeLang"
                    style="width: 150px; margin-right: 20px;"
                    @change="selectLang"
                    :font-size="large"
                    searchable>
                    <bk-option v-for="option in listCodeLang"
                        :key="option"
                        :id="option"
                        :name="option">
                    </bk-option>
                </bk-select>

                <bk-button theme="primary" icon="script-file" class="mr10" @click="copyCode()"> 复制代码</bk-button>
                <bk-button v-if="valueCodeLang === 'json'" theme="primary" icon="eye" class="mr10" @click="formatCode()"> 美化代码</bk-button>

            </div>

            <editor
                ref="aceEditor"
                v-model="content"
                @init="editorInit"
                width="100%"
                height="400px"
                :lang="lang"
                :theme="theme"
                :options="{
                    enableBasicAutocompletion: true,
                    enableSnippets: true,
                    enableLiveAutocompletion: true,
                    tabSize: 6, fontSize: 14,
                    readOnly: readOnly,//设置是否只读
                    showPrintMargin: false //去除编辑器里的竖线
                }"
            ></editor>
        </bk-card>
        
    </div>
</template>

<script>
    export default {
        components: {
            editor: require('vue2-ace-editor')
        },
        props: {
            // 是否只读
            readOnly: {
                type: Boolean,
                default: false
            },
            // 要展示的代码
            codeData: {
                type: String,
                default: ''
            },
            // 默认的主题
            valueTheme: {
                type: String,
                default: 'dracula'
            },
            // 默认的语言
            valueCodeLang: {
                type: String,
                default: 'json'
            }
        },
        data () {
            return {
                listTheme: [
                    'dracula',
                    'chrome',
                    'chaos',
                    'clouds',
                    'clouds_midnight',
                    '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'
                ],
            
                content: '',
                theme: '',
                lang: ''
            }
        },
        mounted () {
            // 初始化编辑器
            this.editorInit()
            // 初始化主题、语言
            this.theme = this.valueTheme
            this.lang = this.valueCodeLang
            // 若传输代码,则展示代码
            if (this.codeData) {
                console.log(this.codeData)
                this.$refs.aceEditor.editor.setValue(this.codeData)
            }
        },
        methods: {
            selectTheme (newValue, oldValue) {
                if (newValue) {
                    this.theme = newValue
                }
            },
            selectLang (newValue, oldValue) {
                if (newValue) {
                    this.lang = newValue
                }
            },
            editorInit () { // 初始化
                require('brace/ext/language_tools')
                require('brace/ext/beautify')
                require('brace/ext/error_marker')
                require('brace/ext/searchbox')
                require('brace/ext/split')

                // 循坏加载语言,通过点击按钮切换
                for (let s = 0; s < this.listCodeLang.length; s++) {
                    require('brace/snippets/' + this.listCodeLang[s])
                }
                for (let j = 0; j < this.listCodeLang.length; j++) {
                    require('brace/mode/' + this.listCodeLang[j])
                }

                // 循坏加载主题,通过点击按钮切换
                for (let i = 0; i < this.listTheme.length; i++) {
                    require('brace/theme/' + this.listTheme[i])
                }
            },

            copyCode () {
                const code = this.$refs.aceEditor.editor.getValue()
                
                // 复制到剪切板
                if (navigator.clipboard) {
                    navigator.clipboard.writeText(code)
                    // 复制成功 给提示 此处省略
                } else {
                    // 复制失败 给提示 此处省略
                    alert('您的浏览器不支持自动复制,请手动复制')
                }
            },

            formatCode () {
                const string = JSON.stringify(JSON.parse(this.$refs.aceEditor.editor.getValue()), null, 2)
                this.$refs.aceEditor.editor.setValue(string)
            }
        
            // getValue () { // 获取编辑器中的值
            //     console.log('编辑器中第一个换行符的位置:' + this.$refs.aceEditor.editor.getValue().indexOf('\n'))
            // }
        }
    }
</script>

<style>

</style>

开发中遇到关于 ' Unexpected token '<'' 的报错的话,要先加载 "brace/snippets/" 再加载 "brace/mode/" 。顺序不对就会报错!

相关推荐
Yjing景20 天前
7、Vue2(一)
vue2
行思理2 个月前
UniApp 从Vue2升级为Vue3需要注意哪些方面
javascript·vue.js·uni-app·vue3·vue2
Geektec2 个月前
智能代码编辑器:Visual Studio Code的深度剖析
vscode·编辑器·编程·代码编辑器·编程语言
azoux3 个月前
我是如何使用 vue2+element-ui 处理负责表单,避免单文件过大的问题
vue2·element-ui
码农研究僧3 个月前
uniapp | vue2 实现用户登录 记住账号密码 功能(附Demo)
uni-app·vue2·登录界面·记住账号密码
苍风的心上人3 个月前
uniapp的h5改成用npm打包
前端·npm·uni-app·vue2
坚持不懈的大白3 个月前
前端:Vue学习 - 购物车项目
axios·vue2·less·vuex·json-server
来一杯龙舌兰4 个月前
Vue2-集成Element-ui、Fontawesome、Axios介绍与使用
ui·axios·vue2·element-ui·fontawesome
流殇꧂4 个月前
使用ElementUI组件库
elementui·vue2
至天4 个月前
UniApp 中 Web/H5 正确使用反向代理解决跨域问题
前端·uni-app·vue3·vue2·vite·反向代理