基于vue-codemirror实现的代码编辑器

开发环境

jshint 2.11.1

jsonlint 1.6.3

script-loader 0.7.2

vue 2.6.11

vue-codemirror 4.0.6

element-ui 2.13.1 (使用到element-ui message组件,提示错误消息,如果不想安装该组件,替换编辑器中的this.$message所在行函数代码即可)

功能介绍

1、  支持不同的代码编辑模式

目前仅支持支持json, sql, javascript,css,xml, html,yaml, markdown, python编辑模式,默认为 json

2、  支持使用不同主题

支持62种主题,默认为 blackboard

 

3、  支持API编程

目前支持修改样式,获取内容,修改编辑框内容值

 

4、  支持复制,黏贴,剪切,撤销等常见操作

 

5、  支持文件拖拽导入

支持鼠标拖拽文件到编辑框,编辑框自动展示被拖拽文件的内容(当然,不是所有文件都可以,比如word文件,.exe文件就不行)

 

6、  支持json格式化

1)json编辑模式下,鼠标失去焦点时自动格式化json字符串,支持定义开关该特性

2)支持自定义格式化化缩进,支持字符或数字,最大不超过10,默认缩进2个空格

3)json编辑模式下,黏贴json字符串到编辑框时,支持自动格式化编辑框内容

4)json编辑模式下,支持按Ctrl+Alt+L快捷键主动格式化当前json格式字符内容

7、  支持显示代码行号

 

8、  支持编辑时“智能”缩进

 

9、  支持代码折叠/展开

支持json, sql, javascript,css,xml, html,yaml, markdown, python等

10、 支持静态代码语法检查

目前仅支持支持 json,javascript

11、 支持批量替换

操作方法:

按Ctrl + Shift + r键,弹出框中输入要被替换的内容,回车,然后再次输入用于替换的内容,回车即可。

12、 支持快速搜索

操作方法:

按Ctrl + F,弹出框中输入要查找内容,回车

13、 支持跳转到指定行

操作方法:

按Alt + G 快捷键, 弹出快对话框中输入行号,回车即可

 

14、 支持鼠标点击高亮匹配单词

使用场景举例:鼠标点击某个单词,高亮其它区域和被点击单词相同的单词

15、 支持自动补全提示

目前仅支持 sql,javascript,html,python

备注:出现自动补全提示时,按tab键可自动补全

16、 支持自动补全括号,单、双引号

支持自动补全括号:(),[],{},单引号,双引号:'' ""

使用场景举例:输入 [ 时,自动显示为[],并且把光标定位在括号中间

17、 支持自动补全xml标签

支持输入完开放xml、html元素标签时,自动补齐右侧闭合标签、或者输入完 </ 时,自动补齐闭合标签

使用场景举例:输入完<book>时自动补齐右侧</book>

 

18、 支持自动匹配xml标签

xml、html编辑模式下,支持自动匹配标签

 

使用场景举例:鼠标点击时xml标签时(开放标签或闭合标签),自动高亮另一半标签

19、 支持自动匹配括号

使用场景举例:光标点击紧挨{、]括号左、右侧时,自动突出显示匹配的括号 }、]

 

20、 支持光标所在当前行背景高亮

 

21、 支持高亮选中内容

使用场景举例:按下鼠标左键,拖拽选择内容时,高亮被选中内容,文字反白

主要依赖安装

npm install jsonlint

npm install jshint

npm install script-loader

npm install vue-codemirror

npm install element-ui

src/main.js配置

添加以下带背景色的部分的配置

import Vue from "vue"

import ElementUI from "element-ui"

import "element-ui/lib/theme-chalk/index.css"

...略

// 引入jshint用于实现js自动补全提示 

import jshint from "jshint";

window.JSHINT = jshint.JSHINT;

 

// 引入代码编辑器 

import { codemirror } from "vue-codemirror";

import "codemirror/lib/codemirror.css";

 

import App from "./app/App"

...略

Vue.use(ElementUI);

Vue.use(codemirror);

...略

编辑器组件实现

<template>

<codemirror

ref="myCm"

:value="editorValue"

:options="cmOptions"

@changes="onCmCodeChanges"

@blur="onCmBlur"

@keydown.native="onKeyDown"

@mousedown.native="onMouseDown"

@paste.native="OnPaste"

></codemirror>

</template>

<script>

import { codemirror } from "vue-codemirror";

import "codemirror/theme/blackboard.css";

import "codemirror/mode/javascript/javascript.js";

import "codemirror/mode/xml/xml.js";

import "codemirror/mode/htmlmixed/htmlmixed.js";

import "codemirror/mode/css/css.js";

import "codemirror/mode/yaml/yaml.js";

import "codemirror/mode/sql/sql.js";

import "codemirror/mode/python/python.js";

import "codemirror/mode/markdown/markdown.js";

import "codemirror/addon/hint/show-hint.css";

import "codemirror/addon/hint/show-hint.js";

import "codemirror/addon/hint/javascript-hint.js";

import "codemirror/addon/hint/xml-hint.js";

import "codemirror/addon/hint/css-hint.js";

import "codemirror/addon/hint/html-hint.js";

import "codemirror/addon/hint/sql-hint.js";

import "codemirror/addon/hint/anyword-hint.js";

import "codemirror/addon/lint/lint.css";

import "codemirror/addon/lint/lint.js";

import "codemirror/addon/lint/json-lint";

require("script-loader!jsonlint");

// import "codemirror/addon/lint/html-lint.js";

// import "codemirror/addon/lint/css-lint.js";

import "codemirror/addon/lint/javascript-lint.js";

import "codemirror/addon/fold/foldcode.js";

import "codemirror/addon/fold/foldgutter.js";

import "codemirror/addon/fold/foldgutter.css";

import "codemirror/addon/fold/brace-fold.js";

import "codemirror/addon/fold/xml-fold.js";

import "codemirror/addon/fold/comment-fold.js";

import "codemirror/addon/fold/markdown-fold.js";

import "codemirror/addon/fold/indent-fold.js";

import "codemirror/addon/edit/closebrackets.js";

import "codemirror/addon/edit/closetag.js";

import "codemirror/addon/edit/matchtags.js";

import "codemirror/addon/edit/matchbrackets.js";

import "codemirror/addon/selection/active-line.js";

import "codemirror/addon/search/jump-to-line.js";

import "codemirror/addon/dialog/dialog.js";

import "codemirror/addon/dialog/dialog.css";

import "codemirror/addon/search/searchcursor.js";

import "codemirror/addon/search/search.js";

import "codemirror/addon/display/autorefresh.js";

import "codemirror/addon/selection/mark-selection.js";

import "codemirror/addon/search/match-highlighter.js";

export default {

components: {

codemirror

},

props: ["cmTheme", "cmMode", "autoFormatJson", "jsonIndentation"],

data() {

return {

editorValue: "",

cmOptions: {

theme:

!this.cmTheme || this.cmTheme == "default"

? "blackboard"

: this.cmTheme,

mode:

!this.cmMode || this.cmMode == "default"

? "application/json"

: this.cmMode,

lineWrapping: true,

lineNumbers: true,

autofocus: true,

smartIndent: false,

autocorrect: true,

spellcheck: true,

extraKeys: {

Tab: "autocomplete",

"Ctrl-Alt-L": () => {

try {

if (

this.cmOptions.mode == "application/json" &&

this.editorValue

) {

this.editorValue = this.formatStrInJson(

this.editorValue

);

}

} catch (e) {

this.$message.error(

"格式化代码出错:" + e.toString()

);

}

}

},

lint: true,

gutters: [

"CodeMirror-lint-markers",

"CodeMirror-linenumbers",

"CodeMirror-foldgutter"

],

foldGutter: true,

autoCloseBrackets: true,

autoCloseTags: true,

matchTags: { bothTags: true },

matchBrackets: true,

styleActiveLine: true,

autoRefresh: true,

highlightSelectionMatches: {

minChars: 2,

style: "matchhighlight",

showToken: true

},

styleSelectedText: true,

enableAutoFormatJson:

this.autoFormatJson == null ? true : this.autoFormatJson,

defaultJsonIndentation:

!this.jsonIndentation ||

typeof this.jsonIndentation != typeof 1

? 2

: this.jsonIndentation

},

enableAutoFormatJson:

this.autoFormatJson == null ? true : this.autoFormatJson,

defaultJsonIndentation:

!this.jsonIndentation || typeof this.jsonIndentation != typeof 1

? 2

: this.jsonIndentation

};

},

watch: {

cmTheme: function(newValue, oldValue) {

try {

let theme =

this.cmTheme == "default" ? "blackboard" : this.cmTheme;

require("codemirror/theme/" + theme + ".css");

this.cmOptions.theme = theme;

this.resetLint();

} catch (e) {

this.$message.error("切换编辑器主题出错:" + e.toString());

}

},

cmMode: function(newValue, oldValue) {

this.$set(this.cmOptions, "mode", this.cmMode);

this.resetLint();

this.resetFoldGutter();

}

},

methods: {

resetLint() {

if (!this.$refs.myCm.codemirror.getValue()) {

this.$nextTick(() => {

this.$refs.myCm.codemirror.setOption("lint", false);

});

return;

}

this.$refs.myCm.codemirror.setOption("lint", false);

this.$nextTick(() => {

this.$refs.myCm.codemirror.setOption("lint", true);

});

},

resetFoldGutter() {

this.$refs.myCm.codemirror.setOption("foldGutter", false);

this.$nextTick(() => {

this.$refs.myCm.codemirror.setOption("foldGutter", true);

});

},

// 修改编辑框样式

setStyle(style) {

try {

this.$nextTick(() => {

let cm = this.$refs.myCm.$el.querySelector(".CodeMirror");

if (cm) {

cm.style.cssText = style;

} else {

this.$message.error(

"未找到编辑器元素,修改编辑器样式失败"

);

}

});

} catch (e) {

this.$message.error("修改编辑器样式失败:" + e.toString());

}

},

// 获取值

getValue() {

try {

return this.$refs.myCm.codemirror.getValue();

} catch (e) {

let errorInfo = e.toString();

this.$message.error("获取编辑框内容失败:" + errorInfo);

return errorInfo;

}

},

// 修改值

setValue(value) {

try {

if (typeof value != typeof "") {

this.$message.error(

"修改编辑框内容失败:编辑宽内容只能为字符串"

);

return;

}

if (this.cmOptions.mode == "application/json") {

this.editorValue = this.formatStrInJson(value);

} else {

this.editorValue = value;

}

} catch (e) {

this.$message.error("修改编辑框内容失败:" + e.toString());

}

},

// 黏贴事件处理函数

OnPaste(event) {

if (this.cmOptions.mode == "application/json") {

try {

this.editorValue = this.formatStrInJson(this.editorValue);

} catch (e) {

// 啥都不做

}

}

},

// 失去焦点时处理函数

onCmBlur(cm, event) {

try {

let editorValue = cm.getValue();

if (this.cmOptions.mode == "application/json" && editorValue) {

if (!this.enableAutoFormatJson) {

return;

}

this.editorValue = this.formatStrInJson(editorValue);

}

} catch (e) {

// 啥也不做

}

},

// 按下键盘事件处理函数

onKeyDown(event) {

const keyCode = event.keyCode || event.which || event.charCode;

const keyCombination =

event.ctrlKey || event.altKey || event.metaKey;

if (!keyCombination && keyCode > 64 && keyCode < 123) {

this.$refs.myCm.codemirror.showHint({ completeSingle: false });

}

},

// 按下鼠标时事件处理函数

onMouseDown(event) {

this.$refs.myCm.codemirror.closeHint();

},

onCmCodeChanges(cm, changes) {

this.editorValue = cm.getValue();

this.resetLint();

},

// 格式化字符串为json格式字符串

formatStrInJson(strValue) {

return JSON.stringify(

JSON.parse(strValue),

null,

this.defaultJsonIndentation

);

}

},

created() {

try {

if (!this.editorValue) {

this.cmOptions.lint = false;

return;

}

if (this.cmOptions.mode == "application/json") {

if (!this.enableAutoFormatJson) {

return;

}

this.editorValue = this.formatStrInJson(this.editorValue);

}

} catch (e) {

console.log("初始化codemirror出错:" + e);

// this.$message.error("初始化codemirror出错:" + e);

}

}

};

</script>

<style>

.CodeMirror-selected {

background-color: blue !important;

}

.CodeMirror-selectedtext {

color: white !important;

}

.cm-matchhighlight {

background-color: #ae00ae;

}

</style>

引用编辑器组件

<template>

<div class="code-mirror-div">

<div class="tool-bar">

<span>请选择主题</span>

<el-select v-model="cmTheme" placeholder="请选择" size="small" style="width:150px">

<el-option v-for="item in cmThemeOptions" :key="item" :label="item" :value="item"></el-option>

</el-select>

<span style="margin-left: 10px">请选择编辑模式</span>

<el-select

v-model="cmEditorMode"

placeholder="请选择"

size="small"

style="width:150px"

@change="onEditorModeChange"

>

<el-option

v-for="item in cmEditorModeOptions"

:key="item"

:label="item"

:value="item"

></el-option>

</el-select>

<el-button type="primary" size="small" style="margin-left:10x" @click="setStyle">修改样式</el-button>

<el-button type="primary" size="small" style="margin-left:10x" @click="getValue">获取内容</el-button>

<el-button type="primary" size="small" style="margin-left:10x" @click="setValue">修改内容</el-button>

</div>

<code-mirror-editor

ref="cmEditor"

:cmTheme="cmTheme"

:cmMode="cmMode"

:autoFormatJson="autoFormatJson"

:jsonIndentation="jsonIndentation"

></code-mirror-editor>

</div>

</template>

<script>

// 使用时需要根据CodeMirrorEditor.vue的实际存放路径,调整from后面的组件路径,以便正确引用

import CodeMirrorEditor from "@/common/components/public/CodeMirrorEditor";

export default {

components: {

CodeMirrorEditor

},

data() {

return {

cmTheme: "default", // codeMirror主题

// codeMirror主题选项

cmThemeOptions: [

"default",

"3024-day",

"3024-night",

"abcdef",

"ambiance",

"ayu-dark",

"ayu-mirage",

"base16-dark",

"base16-light",

"bespin",

"blackboard",

"cobalt",

"colorforth",

"darcula",

"dracula",

"duotone-dark",

"duotone-light",

"eclipse",

"elegant",

"erlang-dark",

"gruvbox-dark",

"hopscotch",

"icecoder",

"idea",

"isotope",

"lesser-dark",

"liquibyte",

"lucario",

"material",

"material-darker",

"material-palenight",

"material-ocean",

"mbo",

"mdn-like",

"midnight",

"monokai",

"moxer",

"neat",

"neo",

"night",

"nord",

"oceanic-next",

"panda-syntax",

"paraiso-dark",

"paraiso-light",

"pastel-on-dark",

"railscasts",

"rubyblue",

"seti",

"shadowfox",

"solarized dark",

"solarized light",

"the-matrix",

"tomorrow-night-bright",

"tomorrow-night-eighties",

"ttcn",

"twilight",

"vibrant-ink",

"xq-dark",

"xq-light",

"yeti",

"yonce",

"zenburn"

],

cmEditorMode: "default", // 编辑模式

// 编辑模式选项

cmEditorModeOptions: [

"default",

"json",

"sql",

"javascript",

"css",

"xml",

"html",

"yaml",

"markdown",

"python"

],

cmMode: "application/json", //codeMirror模式

jsonIndentation: 2, // json编辑模式下,json格式化缩进 支持字符或数字,最大不超过10,默认缩进2个空格

autoFormatJson: true // json编辑模式下,输入框失去焦点时是否自动格式化,true 开启, false 关闭

};

},

methods: {

// 切换编辑模式事件处理函数

onEditorModeChange(value) {

switch (value) {

case "json":

this.cmMode = "application/json";

break;

case "sql":

this.cmMode = "sql";

break;

case "javascript":

this.cmMode = "javascript";

break;

case "xml":

this.cmMode = "xml";

break;

case "css":

this.cmMode = "css";

break;

case "html":

this.cmMode = "htmlmixed";

break;

case "yaml":

this.cmMode = "yaml";

break;

case "markdown":

this.cmMode = "markdown";

break;

case "python":

this.cmMode = "python";

break;

default:

this.cmMode = "application/json";

}

},

// 修改样式(不推荐,建议参考<style>中的样式,提前配置好样式)

setStyle() {

let styleStr =

"position: absolute; top: 80px; left: 50px; right: 200px; bottom: 20px; padding: 2px; height: auto;";

this.$refs.cmEditor.setStyle(styleStr);

},

//获取内容

getValue() {

let content = this.$refs.cmEditor.getValue();

console.log(content);

},

//修改内容

setValue() {

let jsonValue = {

name: "laiyu",

addr: "广东省深圳市",

other: "nothing",

tel: "168888888",

intro: [{ item1: "item1" }]

};

this.$refs.cmEditor.setValue(JSON.stringify(jsonValue));

}

}

};

</script>

<style>

.CodeMirror {

position: absolute;

top: 80px;

left: 2px;

right: 5px;

bottom: 0px;

padding: 2px;

height: auto;

overflow-y: auto;

}

</style>

<style lang="scss" scoped>

.code-mirror-div {

position: absolute;

top: 0px;

left: 2px;

right: 5px;

bottom: 0px;

padding: 2px;

.tool-bar {

top: 20px;

margin: 30px 2px 0px 20px;

}

}

</style>

效果展示

  1. 1.  支持多主题

  1. 2. 代码折叠/展开

 

  1. 3. 静态代码语法检查

 

  1. 4.   查找内容

 

  1. 5.   批量替换内容

 

  1. 6.   跳转到指定行

 

  1. 7. 自动补全提示

 

 

  1. 8. 自动匹配xml标签

 

 

  1. 9.   自动匹配括号

  1. 10.  鼠标点击高亮匹配单词

Vue 基于vue-codemirror实现的代码编辑器的更多相关文章

  1. 在vue项目中使用codemirror插件实现代码编辑器功能(代码高亮显示及自动提示

    在vue项目中使用codemirror插件实现代码编辑器功能(代码高亮显示及自动提示) 1.使用npm安装依赖 npm install --save codemirror; 2.在页面中放入如下代码 ...

  2. vue | 基于vue的城市选择器和搜索城市对应的小区

    城市选择器应该是比较常用的一个组件,用户可以去选择自己的城市,选择城市后返回,又根据自己选择的城市搜索小区. 功能展示 这是选择结果 这是选择城市 这是搜索小区 这是搜索小区接口,key为城市名字,i ...

  3. 在Vue中使用CodeMirror 格式显示错误 行数错乱 & 代码隐藏

    项目需要在线展示和编辑Json文件,所以需要找一个代码编辑器,因为我们的项目直接使用的 vueAdmin-template 这个模板 json编辑器也是直接从 vue-element-admin 项目 ...

  4. Vue基于vue-quill-editor富文本编辑器使用心得

    vue-quill-editor的guthub地址,现在市面上有很多的富文本编辑器,我个人还是非常推荐Vue自己家的vue-quill-deitor,虽然说只支持IE10+,但这种问题,帅给别人吧! ...

  5. CodeMirror:基于JavaScript的代码编辑器

    官方网站定义: http://codemirror.net/ CodeMirror is a versatile text editor implemented in JavaScript for t ...

  6. 我的第一个npm包:wechat-menu-editor 基于Vue的微信自定义菜单编辑器

    wechat-menu-editor 微信自定义菜单编辑器 前言 在做微信公众号相关开发时,基本上会去开发的功能就是微信自定义菜单设置的功能,本着不重复造轮子的原则,于是基于Vue封装的一个微信自定义 ...

  7. 基于VUE框架 与 其他框架间的基本对比

    基于VUE框架的基本描述 与 其他框架间的基本对比 2018-11-03  11:01:14 A B React React 和 Vue 有许多相似之处,它们都有: 使用 Virtual DOM 提供 ...

  8. Vue CLI 3+tinymce 5富文本编辑器整合

    基于Vue CLI 3脚手架搭建的项目整合tinymce 5富文本编辑器,vue cli 2版本及tinymce 4版本参考:https://blog.csdn.net/liub37/article/ ...

  9. 基于 vue+vue-router+vuex+axios+koa+koa-router 本地开发全栈项目

    因为毕业设计要做基于Node服务器的项目,所以我就想着用刚学的vue作为前端开发框架,vue作为Vue.js应用程序的状态管理模式+库,axios基于promise用于浏览器和node.js的http ...

  10. CodeMirror 在线代码编辑器

    像百度编辑器插件部分.菜鸟教程示例等高德地图都在使用,这里也记录一下: CodeMirror是一个用于编辑器文本框textarea代码高亮javascript插件...... vue 中使用 参见:h ...

随机推荐

  1. P1036 [NOIP2002 普及组] 选数

    传送锚点:https://www.luogu.com.cn/problem/P1036 题目描述 已知 \(n\) 个整数 \(x_1,x_2,\cdots,x_n\),以及 \(1\) 个整数 \( ...

  2. MyBatis缓存模块源码分析

    优秀的ORM框架都应该提供缓存机制,MyBatis也不例外,在org.apache.ibatis.cache包下面定义了MyBatis缓存的核心模块,需要注意的是这个包中只是MyBatis缓存的核心实 ...

  3. 为什么我们要用Spring Boot

    最近我面试了不少人,其中不乏说对 Spring Boot 非常熟悉的,然后当我问到一些 Spring Boot 核心功能和原理的时候,没人能说得上来,或者说不到点上,可以说一个问题就问趴下了! 这是我 ...

  4. zabbix笔记_003 配置微信告警

    配置邮件告警 安装python-requests,使用微信发送告警 发送告警报错: yum install -y python-requests 测试告警: cat weixin.py #------ ...

  5. 引用数据类型string字符串 类型转换

    String 任何" "之间的值 包括空格 String类型的字面取值 String str1 = "你好" String str2 = "hello ...

  6. 剑指Offer-64.滑动窗口的最大值(C++/Java)

    题目: 给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值.例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,他们的最大值分别为{4,4,6, ...

  7. node-sass升级为dart-sass

    卸载node-sass npm uninstall node-sass 安装dart-sass npm install sass sass-loader -D 在选择dart-sass版本的时候建议低 ...

  8. ZynqMP PL固件通过U-BOOT从指定位置加载FPGA BIT

    原因 PL固件可能经常修改,而BOOT.BIN和文件系统.内核实际上基本不会变,在一个平台上可以用同一份.如果每次修改都要重新打包PL 固件到BOOT.BIN,操作起来非常麻烦.所以希望PL 的固件可 ...

  9. 关于编译告警 C4819 的完整解决方案 - The file contains a character that cannot be represented in the current code page (number). Save the file in Unicode format to prevent data loss.

    引言 今天迁移开发环境的时候遇到一个问题,同样的操作系统和 Visual Studio 版本,原始开发环境一切正常,但是迁移后 VS 出现了 C4819 告警,上网查了中文的一些博客,大部分涵盖几种解 ...

  10. 卷积神经网络-AlexNet

    AlexNet 一些前置知识 top-1 和top-5错误率 top-1错误率指的是在最后的n哥预测结果中,只有预测概率最大对应的类别是正确答案才算预测正确. top-5错误率指的是在最后的n个预测结 ...