基于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. Java中获取类声明泛型的Class对象(WEB开发Dao层的抽取)

    在WEB开发中,用到三层架构中经常会遇到代码抽取的情况,例如在dao层中,我们需要对数据库的基本操作进行抽取例如这样,在抽取之前我们需要定义抽取类的接口: public interface BaseD ...

  2. c# 32位程序突破2G内存限制

    起因在开发过程中,由于某些COM组件只能在32位程序下运行,程序不得不在X86平台下生成.而X86的32位程序默认内存大小被限制在2G.由于程序中可能存在大数量处理,期间对象若没有及时释放或则回收,内 ...

  3. Asp-Net-Core学习笔记:身份认证入门 _

    前言 过年前我又来更新了~ 我就说了最近不是在偷懒吧,其实这段时间还是有积累一些东西的,不过还没去整理-- 所以只能发以前没写完的一些笔记出来 就当做是温习一下啦 PS:之前说的红包封面我还没搞,得抓 ...

  4. redis安装和基础使用

    redis安装 mkdir /server/tools -p cd /server/tools echo 'PATH=/usr/local/redis/src:$PATH' >>/etc/ ...

  5. Qt添加资源文件

    参考视频:https://www.bilibili.com/video/BV1XW411x7NU?p=27 以添加图片为例进行说明: 1)点击工程名,选择"添加新文件": 2)选择 ...

  6. kettle从入门到精通 第十三课 kettle 字符串操作

    1.本次示例讲解一些常用的字符串操作,有字段拼接,枚举值转换,计算器.字符串替换.字段拆分. 2.输入元数据有firstName.secondName.sex.salary.englishName.o ...

  7. Easysearch 容量规划建议

    基于容量估算 主要问题: 每天将索引多少原始数据(GB)?保留数据多少天? 原始数据膨胀率 您将强制执行多少个副本分片? 您将为每个数据节点分配多少内存? 您的内存:数据比例是多少? 原则 保留 +1 ...

  8. 使用final shell 连接使用 ubuntu server linux

    书接上回,VM 安装ubuntu server:https://www.cnblogs.com/runliuv/p/16880599.html 1.从 https://www.hostbuf.com/ ...

  9. 两个Excel表格核对 excel表格中# DIV/0 核对两个表格的差异,合并运算VS高级筛选

    两个Excel表格核对   excel表格中# DIV/0 核对两个表格的差异,合并运算VS高级筛选 1.两列顺序一样的数据核对 方法1:加一个辅助列,=B2=C2 结果为FALSE的就是不相同的 方 ...

  10. 函数式表达式基本类型及固定类型 demo

    1.常见类型及使用 import java.util.function.BiConsumer; import java.util.function.BiFunction; import java.ut ...