基于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. C# Afroge摄像头翻转90

    1.dll和命名空间就不在此列举了,如下只是将转换方法介绍: 第一个函数: public void Rotate90() { // 计算角度,类变量 //dAngle = dAngle + 90; / ...

  2. Vue 页面传参方式 Query 和 Params

    1. query 与 params 传参 query 需要和配合 path 属性使用,携带参数会拼接在请求路径后,效果同 Get 请求方式 http://localhost:8033/Permissi ...

  3. 鸿蒙HarmonyOS实战-Web组件(前端函数和应用侧函数相互调用)

    前言 前端函数和应用侧函数相互调用是指前端页面中的JavaScript函数和应用程序侧的函数之间进行相互调用. 在前端开发中,常常会使用JavaScript函数来处理用户的交互事件和操作.这些函数可以 ...

  4. 莫烦tensorflow学习记录 (3)建造我们第一个神经网络

    另一个学习文档http://doc.codingdict.com/tensorflow/tfdoc/tutorials/overview.html 定义 add_layer() https://mof ...

  5. nginx37条优化

    nginx优化: 1. cpu:核心配置 方法1: worker_processes auto; 自动调用[推荐] 方法2: worker_processes 4; 手工配置 检查CPU核心:yum ...

  6. Qt(python) + 百度语音合成 实现demo

    python实现 安装api sudo pip3 install baidu-aip 安装音频处理模块pydub sudo pip3 install pydub from aip import Aip ...

  7. Opencv笔记(12)傅里叶变换

    在之前了解的OpenCV为我们实现的图像变换,这些本质上是从图像到输出图像的映射,即输入仍是一幅图像.本章的傅里叶变换,输出数组的值在含义上和原图像的强度值大不相同,是输入图像的频域表示. cv::d ...

  8. 一款.NET开源、免费、实用的多功能原神工具箱(改善桌面端玩家的游戏体验)

    前言 今天大姚给大家分享一款.NET开源(MIT License).免费.实用的多功能原神工具箱,旨在改善桌面端玩家的游戏体验:胡桃工具箱. 工具箱介绍 胡桃工具箱是一款.NET开源(MIT Lice ...

  9. C#中路径说明

    路径中一个点和两个点的区别 ./    表示当前目录,如"./jquery-1.3.2.min.js",也可以去掉"./",如"jquery-1.3. ...

  10. redis简单应用demo - 订单号自增长的思路:业务编码+地区+自增数值

    redis简单应用demo1.字符串127.0.0.1:6379> set hello toneyOK127.0.0.1:6379> type hellostring127.0.0.1:6 ...