基于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. 未能加载文件或程序集“UFIDA.U8.UAP.GcRegister, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null”或它的某一个依赖项

    这是做采购入库单新增的时候遇到的问题,我是采用模仿写用友u8的zpurrkdhead 主表视图和子表视图zpurrkdtail 去构建 xml文档这样做的,但是再做的时候 [cgcroutecode] ...

  2. pyinstaller 打包无窗口python http.server无法启动

    最近在写一个简单的文件服务器用来访问静态文件,遇到在pyinstaller无窗口模式下无法启动的问题,记录一下解决方案. 原因:http.server需要将记录输出到窗口,而pyinstaller打包 ...

  3. 常用的注意力机制模块(SE、CBAM)

    [深度学习]总目录 SE论文:<Squeeze-and-Excitation Networks>将重点放在了通道(channel)关系上,并提出了一种新的结构单元SE block.将SE ...

  4. Java爬虫-爬取疫苗批次信息

    今年3月份开始,就接到通知, 根据<关于开展有关人群第二剂次脊髓灰质炎灭活疫苗补种工作的通知>国疾控卫免发[2024]1号文件要求,在2016年3月1日至2019年9月30日之间出生的儿童 ...

  5. C语言打印数字前补0

    1.要求说明 例如有个数据为a = 0x10,要求打印输出为0x000010. 2.实现 1 #include <stdio.h> 2 3 4 int main() 5 { 6 int a ...

  6. Java中try catch finally 关键字

    异常处理中的几个常用关键字(try catch finally throw throws) 异常处理 java中提供一套异常处理机制,在程序发生异常时,可以执行预先设定好的处理程序, 执行完成后,程序 ...

  7. oop课程4-6次作业小结

    目录 (1)前言 (2)设计与分析 第四次作业(答题判题程序-4) 新增多选类 新增填空类 第五次作业(家居强电电路模拟程序-1) Element类 控制设备 开关# 分档调速器# 受控设备 白炽灯# ...

  8. 如何使用JavaScript实现在线Excel附件的上传与下载?

    前言 在本地使用Excel时,经常会有需要在Excel中添加一些附件文件的需求,例如在Excel中附带一些Word,CAD图等等.同样的,类比到Web端,现在很多人用的在线Excel是否也可以像本地一 ...

  9. 哈啰面试:说说Dubbo运行原理?

    Dubbo 是一款高性能.轻量级的开源 RPC(远程过程调用)框架,主要用于构建分布式服务和微服务架构.那 Dubbo 又是如何运行的呢?让我们一起来看. 1.核心组件 要说 Dubbo 运行流程就不 ...

  10. 同时开启firewall和iptables

    使用向导 With the iptables service, every single change means flushing all the old rules and reading all ...