• 通过vue-codemirror和CodeMirror将代码编辑器添加到web项目中


    前言

    最近项目中有一个需求是,需要添加一个代码编辑器到项目中。也不知道是谁设计的,将代码编辑器添加到项目中?

    费了九牛二虎之力终于找到了 vue-codemirrorCodeMirror 感觉是最合适的。

    看一下官方对这两个库的介绍(插件翻译后的):
    在这里插入图片描述
    在这里插入图片描述
    git地址

    vue-codemirror: https://github.com/surmon-china/vue-codemirror

    codemirror5: https://github.com/codemirror/codemirror5

    下面是关于自己使用的一些介绍。

    vue-codemirror

    安装

    安装库

    npm install codemirror vue-codemirror --save
    
    • 1

    安装语言和主题

    支持的语言:语言
    支持的主题:主题

    暂时就安装下面这些

    npm install @codemirror/lang-html --save
    npm install @codemirror/lang-css --save
    npm install @codemirror/lang-javascript --save
    npm install @codemirror/lang-sql --save                                   
    npm install @codemirror/lang-java --save
    
    npm install @codemirror/theme-one-dark --save
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    使用

    如果需要从codemirror导入API/接口,则需要在package.json里添加如下代码:

    "dependencies": {
      "@codemirror/state": "6.x"
    }
    
    • 1
    • 2
    • 3
    import { EditorState } from '@codemirror/state'
    
    • 1

    demo

    <template>
      <codemirror
        v-model="code"
        placeholder="代码编辑..."
        :style="{ height: '400px' ,textAlign: 'left'}"
        :autofocus="true"
        :indent-with-tab="true"
        :tab-size="2"
        :extensions="extensions"
        @ready="handleReady"
        @change="log('change', $event)"
        @focus="log('focus', $event)"
        @blur="log('blur', $event)"
      />
    </template>
    
    <script lang="ts">
    import { defineComponent, ref, shallowRef } from 'vue';
    // 核心库
    import { Codemirror } from 'vue-codemirror';
    // 引入的语言包
    import { javascript } from '@codemirror/lang-javascript';
    // 引入的主题
    import { oneDark } from '@codemirror/theme-one-dark';
    
    export default defineComponent({
        components: {
            Codemirror
        },
        setup() {
            // 默认显示的diamond
            const code = ref('');
            // 扩展,包括语言和主题
            const extensions = [javascript(), oneDark];
    
            // 代码镜像编辑器查看实例引用
            // 说实话shallowRef还真不知道是vue里的
            const view = shallowRef();
            // 准备状态
            const handleReady = (payload) => {
                view.value = payload.view;
            };
    
            // 获取状态,状态始终通过Codemirror编辑器视图可用
            const getCodemirrorStates = () => {
                const state = view.value.state;
                const ranges = state.selection.ranges;
                const selected = ranges.reduce((r, range) => r + range.to - range.from, 0); // 选中的值
                const cursor = ranges[0].anchor; // 光标
                const length = state.doc.length; // 代码长度
                const lines = state.doc.lines; // 行数
                // 其他状态信息
            };
    
            return {
                code,
                extensions,
                handleReady,
                log: console.log
            };
        }
    });
    </script>
    
    • 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

    在这里插入图片描述
    ctrl + f 快捷键也是支持的
    在这里插入图片描述

    注意: 无法同时添加多个语言和主题,如果添加多个主题和语言用于是前面的生效。我尝试添加了一下htmljavascript 只能有一个生效(生效是指有代码提示)

    属性和事件

    属性

    • modelValue,绑定的值,默认空字符串
    • autofocus,是否在编辑器挂载之后自动获取焦点,默认否
    • disabled,是否禁用输入,默认否
    • indentWithTab,是否按照制表符缩进,默认是
    • tabSize,按tab键缩进的格数,默认2
    • placeholder,输入提示语,默认空字符串
    • style,style样式,默认空对象
    • autoDestroy,是否在组件卸载之前自动销毁,默认是
    • extensions,扩展,默认空数组
    • selection,个人理解应该就是选中的代码
    • root,个人理解是dom的根节点

    事件

    • change,编辑器内容改变触发的事件
    • update,状态更新触发的事件
    • focus,当获取焦点后触发的事件
    • blur,当失去焦点后触发的事件
    • ready,当编辑器挂载时触发的事件

    codemirror5

    看完了基于codemirror5封装的vue-codemirror,我们再看一下codemirror5。还是以vue项目为例子

    最新版本好像是6,但是不明白github上为什么是5

    安装

    安装库

    npm install codemirror --save
    
    • 1

    主题和语言

    官方暂时只支持上面哪些语言和主题,还有一些插件可以去github上搜索
    在这里插入图片描述
    另外官方提供了自己开发语言包的案例,如果绝对语言不够,可以自己尝试开发。

    参考

    参考:https://codemirror.net/examples/

    参考官方提供的用例,来学习如何使用

    加载

    <template>
        <div id="editor"></div>
    </template>
    
    <script setup lang="ts">
    import { onMounted, ref } from 'vue';
    import { EditorView, basicSetup } from 'codemirror';
    import { javascript } from '@codemirror/lang-javascript';
    
    const editor = ref();
    onMounted(() => {
        editor.value = new EditorView({
            extensions: [basicSetup, javascript()],
            parent: document.getElementById('editor')
        });
    });
    
    </script>
    
    <style lang="scss" scoped>
    #editor{
        // 高度是不生效的
        width: 600px;
        height: 600px;
        text-align: left;
    }
    </style>
    
    • 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

    在这里插入图片描述

    配置

    参考官方demo,配置tab缩进

    <template>
        <div id="editor"></div>
    </template>
    
    <script setup lang="ts">
    import { onMounted, ref } from 'vue';
    import { EditorView, basicSetup } from 'codemirror';
    import { EditorState, Compartment } from '@codemirror/state';
    import { javascript } from '@codemirror/lang-javascript';
    
    const view = ref();
    
    const tabSize = ref();
    
    onMounted(() => {
        // 创建语言扩展
        const language = new Compartment();
        // 创建tab缩进扩展
        tabSize.value = new Compartment();
    
        // 创建编辑器状态
        const state = EditorState.create({
            extensions: [
                basicSetup,
                language.of(javascript()),
                tabSize.value.of(EditorState.tabSize.of(8))
            ]
        });
    
        // 获取编辑器试图
        view.value = new EditorView({
            state,
            parent: document.getElementById('editor')
        });
    });
    
    // 用于更新tab缩进的方法
    const setTabSize = (view, size) => {
        view.dispatch({
            effects: tabSize.value.reconfigure(EditorState.tabSize.of(size))
        });
    };
    </script>
    
    • 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

    样式

    基础

    可以直接定义样式,当然有些样式可能会不生效,这时你可以直接查看源码,来确定具体修改那一块的样式

    #editor{
     width: 600px;
     text-align: left;
     background-color: black;
     color: #fff !important;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    可以看一下我的这篇文章 vue3:基于highlight实现代码高亮、显示代码行数、添加复制功能,感觉应该是可以实现下面的效果(我自己没有尝试)
    在这里插入图片描述
    官方api
    官方提供的改变样式和主题的方式,没太理解。不过问题不大,完全可以查看源码的方式来修改相应的类。

    其他例子

    其他例子略,感兴趣的可以自行查看。

    扩展

    除了上面的编辑器外还有下面这两款

    https://github.com/ajaxorg/ace :这个好像是不支持es6的导入,只能通过传统的src加载,感兴趣的可以看看

    另一个是 Monaco-Editor 和vscode有很大的关系,但是有点复杂,没搞明白怎么使用

  • 相关阅读:
    clickhouse学习之路----clickhouse的特点及安装
    微信公众号获取openId——开发阶段
    SAP:增强中用commit和wait up会导致操作异常
    产品经理懂点技术:几种常用的系统开发方法
    一个全局最优化的方法:随机游走算法-Random-Walk
    《0基础》学习Python——第十一讲__时间函数
    前端常见面试题
    Kubernetes网络插件Canal的工作原理和关键功能
    网络安全(黑客)自学
    Learning Normal Dynamics in Videos with Meta Prototype Network详解及论文精读
  • 原文地址:https://blog.csdn.net/weixin_41897680/article/details/127453971