Vue 基于vue-codemirror实现的代码编辑器
基于vue-codemirror实现的代码编辑器开发环境jshint 2.11.1jsonlint 1.6.3script-loader 0.7.2vue 2.6.11vue-codemirror 4.0.6element-ui 2.13.1 (使用到element-ui message组件,提示错误消息,如果不想安装该组件,替换编辑器中的this.$message所在行函数代码即可)功能介绍1、
功能介绍
1、 支持不同的代码编辑模式
目前仅支持支持json, sql, javascript,css,xml, html,yaml, markdown, python编辑模式,默认为 json
2、 支持使用不同主题
支持62种主题,默认为 blackboard
3、 支持文件拖拽导入
支持鼠标拖拽文件到编辑框,编辑框自动展示被拖拽文件的内容(当然,不是所有文件都可以,比如word文件,.exe文件就不行)
4、 支持json格式化
1)json编辑模式下,鼠标失去焦点时自动格式化json字符串,支持定义开关该特性
2)支持自定义格式化化缩进,支持字符或数字,最大不超过10,默认缩进2个空格
3)json编辑模式下,黏贴json字符串到编辑框时,支持自动格式化编辑框内容
4)json编辑模式下,支持按Ctrl+Alt+L快捷键主动格式化当前json格式字符内容
5、 支持显示代码行号
6、 支持编辑时“智能”缩进
7、 支持代码折叠/展开
支持json, sql, javascript,css,xml, html,yaml, markdown, python等
8、 支持静态代码语法检查
目前仅支持支持 json,javascript
9、 支持批量替换
操作方法:
按Ctrl + Shift + r键,弹出框中输入要被替换的内容,回车,然后再次输入用于替换的内容,回车即可。
10、 支持快速搜索
操作方法:
按Ctrl + F,弹出框中输入要查找内容,回车
11 、 支持跳转到指定行
操作方法:
按Alt + G 快捷键, 弹出快对话框中输入行号,回车即可
12、 支持鼠标点击高亮匹配单词
使用场景举例:鼠标点击某个单词,高亮其它区域和被点击单词相同的单词
13、 支持自动补全提示
目前仅支持 sql,javascript,html,python
备注:出现自动补全提示时,按tab键可自动补
14、 支持自动补全xml标签
支持输入完开放xml、html元素标签时,自动补齐右侧闭合标签、或者输入完 </ 时,自动补齐闭合标签
使用场景举例:输入完时自动补齐右侧
15、 支持自动匹配xml标签
xml、html编辑模式下,支持自动匹配标签
使用场景举例:鼠标点击时xml标签时(开放标签或闭合标签),自动高亮另一半标签
16、 支持自动匹配括号
使用场景举例:光标点击紧挨{、]括号左、右侧时,自动突出显示匹配的括号 }、]
17、 支持光标所在当前行背景高亮
18、 支持高亮选中内容
使用场景举例:按下鼠标左键,拖拽选择内容时,高亮被选中内容,文字反白
主要依赖安装
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”;
Vue.use(ElementUI);
Vue.use(codemirror);
编辑器组件实现
<template>
<codemirror
ref="myCm"
:value="value"
: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/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","value"],
data() {
return {
editorValue: "",
cmOptions: {
theme:!this.cmTheme || this.cmTheme == "default"? "blackboard": this.cmTheme,
mode:!this.cmMode || this.cmMode == "default"? "application/json": this.cmMode,
extraKeys: {
Tab: "autocomplete",
"Ctrl-Alt-L": () => {
try {
if (this.cmOptions.mode == "application/json" &&this.value) {
this.editorValue = this.formatStrInJson(this.value);
}
} catch (e) {
this.$message.error("格式化代码出错:" + e.toString());
}
}
},
lineWrapping: true,//代码折叠
lineNumbers: true,//是否显示行号
autofocus: true,
smartIndent: 4,// 自动缩进
indentUnit: 4, //缩进单位
tabSize: 4, //tab字符的宽度
autocorrect: true,//自动更正
spellcheck: true,//拼写检查
lint: true,
gutters: [
"CodeMirror-lint-markers",//代码错误检测
"CodeMirror-linenumbers",
"CodeMirror-foldgutter",//展开收起
],
foldGutter: 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);
});
},
// 黏贴事件处理函数
OnPaste(event) {
if (this.cmOptions.mode == "application/json") {
try {
this.editorValue = this.formatStrInJson(this.value);
} 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();
this.$emint('onChangeCode',cm.getValue())
},
// 格式化字符串为json格式字符串
formatStrInJson(strValue) {
return JSON.stringify( JSON.parse(strValue),null, this.defaultJsonIndentation)
}
},
created() {
try {
if (!this.value) {
this.cmOptions.lint = false;
return;
}
if (this.cmOptions.mode == "application/json") {
if (!this.enableAutoFormatJson) {
return;
}
this.editorValue = this.formatStrInJson(this.value);
}
} catch (e) {
console.log("初始化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>
</div>
<code-mirror-editor
ref="cmEditor"
:cmTheme="cmTheme"
:cmMode="cmMode"
:autoFormatJson="autoFormatJson"
:jsonIndentation="jsonIndentation"
:value="codeValue
@onChangeCode="changeCode"
></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 关闭,
codeValue:'[{text:"text1",value:"value1"}]',//代码
};
},
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";
}
},
//代码修改
changeCode(value){
this.codeValue = value;
}
}
};
</script>
<style>
.CodeMirror {
position: absolute;
top: 80px;
left: 2px;
right: 5px;
bottom: 0px;
padding: 2px;
height: auto;
overflow-y: auto;
}
.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>
更多推荐
所有评论(0)