基于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. PaddleOCR在 windows下的webAPI部署方案

    很多小伙伴在使用OCR时都希望能过采用API的方式调用,这样就可以跨端跨平台了.本文将介绍一种基于python的PaddleOCR识方案.喜欢的可以关注公众号,获取更多内容. # 一. windows ...

  2. 前端项目报EISDIR: illegal operation on a directory, read这个错误

    背景: 我用webstorm开发前端页面时,项目用Vue3来开发,出现如下报错. 原因: 这个报错是由于代码中引入的一些组件或者模块路径不正确导致的,在vue2中,引入组件是下面这样写的: impor ...

  3. bpmnjs

    在 bpmn.js 中,`bpmnModeler.get()` 方法用于获取不同的模块,你可以通过这些模块来访问和操作 BPMN 模型的不同部分.以下是一些常用的模块和对应的用途: 1. **Canv ...

  4. react 数据请求分层

    封装一个接口请求类 数据模型 请求uri配置设置 数据统一存储于redux中,在本项目中创建一个store目录,此目录中就是redux仓库源 定义仓库入口 reducer methods方法 acti ...

  5. Nodejs fs模块 全局变量

    fs模块提供了用于与文件进行交互相关方法 const fs = require('fs') # 写入数据 fs.writeFile(文件,数据,err=>{}) # 读取文件中数据 fs.rea ...

  6. kettle从入门到精通 第六十一课 ETL之kettle 任务调度器,轻松使用xxl-job调用kettle中的job和trans

    1.大家都知道kettle设计的job流程文件有个缺点:只能设置简单的定时任务,无法设置复杂的如支持cron表达式的job. 今天给大家分享一个使用xxl-job调度carte的流程文件的示例.整个调 ...

  7. MyBatis 的在使用上的注意事项及其辨析

    1. MyBatis 的在使用上的注意事项及其辨析 @ 目录 1. MyBatis 的在使用上的注意事项及其辨析 2. 准备工作 3. #{ } 与 ${ } 的区别和使用 {} 3.1 什么情况下必 ...

  8. RequestBodyAdvice和注解方式进行统一参数处理demo

    RequestBodyAdvice和注解方式进行统一参数处理demo @Target({ ElementType.METHOD, ElementType.TYPE }) @Retention(Rete ...

  9. springboot项目编译时,使用自定义注解类找不到符号

    springboot项目编译时,使用自定义注解类找不到符号 Java项目编译时,使用自定义注解类找不到符号Spring-boot项目编辑器:idea问题:编译时找不到符号.项目中用到了自定义注解类.编 ...

  10. CountDownLatch demo演示裁判和选手赛跑

    # CountDownLatch demo演示裁判和选手赛跑 package com.example.core.mydemo; import java.util.concurrent.CountDow ...