

Vue学习实践笔记-基于codemirror在页面中嵌入代码编辑器 |坐而言不如起而行! 二丫讲...
source link: http://www.eryajf.net/5164.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

1,基础信息
- 名字:codemirror
- 资料
- Git地址:https://github.com/codemirror/codemirror
- 官方文档:https://codemirror.net/
- 支持的高亮语言:https://codemirror.net/mode/
- 主题选择:https://codemirror.net/demo/theme.html#default
- 衍生
- vue-codemirror
- vue-ele-form
- 一些示例:https://github.surmon.me/vue-codemirror/
2,用法简言
官方文档的阅读性并不是很好,因此简单记录一些几个使用的注意点。没有尝试过直接引用原生的包的效果,目前是基于ele-form这个二次封装的库来做的。不过有许多东西,还可以基于原生的一些特性,进行自定义。
1,高亮语言
一般直接拷贝上边示例中的一些案例即可满足需求,如果想要自定义,有如下注意点,因为我需要的是shell输入框,因此引入语言改成如下内容:
// language
import 'codemirror/mode/shell/shell.js'
需要注意的一个点是,在引用中配置(options
)参数(mode
)时,并不是shell,而是 x-sh
,这个可以在高亮语言中点击进去的示例下边看到,因为这个上下不一致,让我踩了挺长时间的坑(因为网上大多示例都是采用的JavaScript高亮,而这个模块儿引入又刚好是text/javascript
,因此造成了一定的误导),截图示例如下:
2,主题选择
主题选择可以根据如下demo选择适合自己的,引入主题的方式如下:
// theme css
import 'codemirror/theme/base16-light.css'
然后在引用中配置(options
)参数(theme
)中定义即可,这里测试名字是上下一致的,没有其他坑点。不过我引入的shell语言,测试之后发现默认的主题反而最好看,因此不需引入css,直接设置为default
即可。
3,案例分享
接下来分享一下我个人的使用案例,整理内容,大致如下:
<template>
<!-- 代码输入区域 -->
<ele-form :formDesc="formDesc" v-model="formData" :request-fn="handleRequest" @request-success="handleRequestSuccess"></ele-form>
</template>
<script>
// 引入外部包
import EleForm from 'vue-ele-form'
import EleFormCodemirror from 'vue-ele-form-codemirror'
// language
import 'codemirror/mode/shell/shell.js'
// require active-line.js
import'codemirror/addon/selection/active-line.js'
// closebrackets
import'codemirror/addon/edit/closebrackets.js'
// keyMap
import'codemirror/mode/clike/clike.js'
import'codemirror/addon/edit/matchbrackets.js'
import'codemirror/addon/comment/comment.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/keymap/emacs.js'
export default {
data() {
return {
formData: {},
// 定制样式
formDesc: {
option: {
label: "命令", // 说明文字
type: "codemirror", // 选择这个类型
tabSize: 4,
line: true,
theme: 'default', // 主题选择默认
mode: 'text/x-sh', // 此处定义高亮语言风格
lineNumbers: true,
styleActiveLine: true,
autoCloseBrackets: true,
}
},
}
},
methods: {
handleRequest (data) {
console.log(data)
return Promise.resolve()
},
handleRequestSuccess () {
this.$message.success('发送成功')
},
handleSelectionChange(val) {
console.log("选择成功");
this.multipleSelection = val;
},
}
}
</script>
<style>
.CodeMirror-focused .cm-matchhighlight {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAFklEQVQI12NgYGBgkKzc8x9CMDAwAAAmhwSbidEoSQAAAABJRU5ErkJggg==);
background-position: bottom;
background-repeat: repeat-x;
}
.cm-matchhighlight {
background-color: lightgreen;
}
.CodeMirror-selection-highlight-scrollbar {
background-color: green;
}
</style>
在自己的项目中,可根据实际情况将引入的内容放到公共的部分。
4,最终效果
出来的效果大致如下:
3,原生使用
上边通过引入了一个第三方组件来实现的,其实也可以直接通过 vue-codemirror来实现,效果基本上是差不多的。
代码大概如下:
<template>
<!-- 代码输入区域 -->
<codemirror v-model="formData.task_content" :options="cmOptions"/>
</template>
<script>
// language
import 'codemirror/mode/shell/shell.js'
// require active-line.js
import'codemirror/addon/selection/active-line.js'
// closebrackets
import'codemirror/addon/edit/closebrackets.js'
// keyMap
import'codemirror/mode/clike/clike.js'
import'codemirror/addon/edit/matchbrackets.js'
import'codemirror/addon/comment/comment.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/keymap/emacs.js'
export default {
data() {
return {
formData: {},
cmOptions: {
tabSize: 4,
mode: 'text/x-sh',
lineNumbers: true,
line: true,
matchBrackets: true,
scrollbarStyle: 'overlay',
theme: 'default'
},
}
},
methods: {
}
}
</script>
<style>
</style>
这种更加原生的状态,更能方便我们将输入框作为表单的一环来应用,不过默认情况下,代码的行间距有点大,光标太大,不是很好看,可以通过如下代码进行美化:
.code-mirror{
font-size : 13px;
line-height : 150%;
}
然后将这个样式引用即可。
4,其他参数
1,常用配置
keyMap: string
配置快捷键。默认值为default,即 codemorrir.js 内部定义。其它在key map目录下。extraKeys: object
给编辑器绑定与前面keyMap配置不同的快捷键。lineWrapping: boolean
在长行时文字是换行(wrap)还是滚动(scroll),默认为滚动(scroll)。lineNumbers: boolean
是否在编辑器左侧显示行号。firstLineNumber: integer
行号从哪个数开始计数,默认为1 。lineNumberFormatter: function(line: integer) → string
使用一个函数设置行号。gutters: array<string>
用来添加额外的gutter(在行号gutter前或代替行号gutter)。值应该是CSS名称数组,每一项定义了用于绘制gutter背景的宽度(还有可选的背景)。为了能明确设置行号gutter的位置(默认在所有其它gutter的右边),也可以包含CodeMirror-linenumbers类。类名是用于传给setGutterMarker的键名(keys)。fixedGutter: boolean
设置gutter跟随编辑器内容水平滚动(false)还是固定在左侧(true或默认)。scrollbarStyle: string
设置滚动条。默认为”native”,显示原生的滚动条。核心库还提供了”null”样式,此样式会完全隐藏滚动条。Addons可以设置更多的滚动条模式。coverGutterNextToScrollbar: boolean
当fixedGutter启用,并且存在水平滚动条时,在滚动条最左侧默认会显示gutter,当此项设置为true时,gutter会被带有CodeMirror-gutter-filler类的元素遮挡。inputStyle: string
选择CodeMirror处理输入和焦点的方式。核心库定义了textarea和contenteditable输入模式。在移动浏览器上,默认是contenteditable,在桌面浏览器上,默认是textarea。在contenteditable模式下对IME和屏幕阅读器支持更好。readOnly: boolean|string
编辑器是否只读。如果设置为预设的值 “nocursor”,那么除了设置只读外,编辑区域还不能获得焦点。showCursorWhenSelecting: boolean
在选择时是否显示光标,默认为false。lineWiseCopyCut: boolean
启用时,如果在复制或剪切时没有选择文本,那么就会自动操作光标所在的整行。undoDepth: integer
最大撤消次数,默认为200(包括选中内容改变事件) 。historyEventDelay: integer
在输入或删除时引发历史事件前的毫秒数。tabindex: integer
编辑器的tabindex。autofocus: boolean
是否在初始化时自动获取焦点。默认情况是关闭的。但是,在使用textarea并且没有明确指定值的时候会被自动设置为true。
低级选项,下面的选项仅用于一些特殊情况。
dragDrop: boolean
是否允许拖放,默认为true。allowDropFileTypes: array<string>
默认为null。当设置此项时,只接收包含在此数组内的文件类型拖入编辑器。文件类型为MIME名称。cursorBlinkRate: number
光标闪动的间隔,单位为毫秒。默认为530。当设置为0时,会禁用光标闪动。负数会隐藏光标。cursorScrollMargin: number
当光标靠近可视区域边界时,光标距离上方和下方的距离。默认为0 。cursorHeight: number
光标高度。默认为1,也就是撑满行高。对一些字体,设置0.85看起来会更好。resetSelectionOnContextMenu: boolean
设置在选择文本外点击打开上下文菜单时,是否将光标移动到点击处。默认为true。workTime, workDelay: number
通过一个假的后台线程高亮 workTime 时长,然后使用 timeout 休息 workDelay 时长。默认为200和300 (啥玩意儿这个)pollInterval: number
指明CodeMirror向对应的textarea滚动(写数据)的速度(获得焦点时)。大多数的输入都是通过事件捕获,但是有的输入法(如IME)在某些浏览器上并不会生成事件,所以使用数据滚动。默认为100毫秒。flattenSpans: boolean
默认情况下,CodeMirror会将使用相同class的两个span合并成一个。通过设置此项为false禁用此功能。addModeClass: boolean
当启用时(默认禁用),会给每个标记添加额外的表示生成标记的mode的以cm-m开头的CSS样式类。例如,XML mode产生的标记,会添加cm-m-xml类。maxHighlightLength: number
当需要高亮很长的行时,为了保持响应性能,当到达某些位置时,编辑器会直接将其他行设置为纯文本(plain text)。默认为10000,可以设置为Infinity来关闭此功能。viewportMargin: integer
指定当前滚动到视图中内容上方和下方要渲染的行数。这会影响到滚动时要更新的行数。通常情况下应该使用默认值10。可以设置值为Infinity始终渲染整个文档。注意:这样设置在处理大文档时会影响性能。
2,编辑器事件
编辑器实例会触发以下这些事件。其中的instance参数总是指向编辑器本身。
change: (instance: CodeMirror, changeObj: object)
每当编辑器内容发生变化时触发。参数changeObj是一个{from, to, text, removed, origin}对象,包含内容变化的信息。其中from和to是内容改变发生的起止位置(改变发生之前),举个例子,如果改变始于第19行之初,则from为{ch:0, line:18}。text替换起止位置之间内容的文字,按行分割开,组成数组。removed则是被替换掉的内容。这个事件会在operation临结束前,在DOM更新之前触发。changes: (instance: CodeMirror, changes: array:)
类似于change事件,不过是在每次operation后,将改变一次过打包成数组传出来。而展现这些改变,又将出发一次新的operation。beforeChange: (instance: CodeMirror, changeObj:object)
这个事件在内容改变生效前触发,它的handler可以此来修改或取消这次改变。其中的changeObj对象有from, to, text属性。它还包含一个cancel()方法,用于取消这次改变,而且如果这次改变不是来自撤销(undo)与重做(redo)操作的画,它还会有一个update(from, to, text)方法,用来修改这次改变。update方法的3个参数都不是必填的,可以不传入,以直接使用原先的值。注意:你不该在beforeChange的handler中做任务会导致document或其视觉表现的操作。cursorActivity: (instance: CodeMirror)
每当光标或内容选择移动时出发,因此编辑器中任务内容的改变也会出发。keyHandled: (instance: CodeMirror, name: string, event: Event)
每当一个快捷键被通过key map handled时触发。name是被handled的键(例如”ctrl-x”或者“‘q’”),而event则是DOM的keydown或keypress事件。inputRead: (instance: CodeMirror, changeObj: object)
每当被因此对textarea中有新的输入被读取到时触发(可能是来自键盘输入或粘贴)。electricInput: (instance: CodeMirror, line: integer)
当输入的文字匹配mode的electric模式时触发,这会导致该行的缩进发生改变。beforeSelectionChange: (instance: CodeMirror, obj: {range, origin, update})
viewportChange: (instance: CodeMirror, from: number, to: number)
当可视区发生变化时触发(这可能是由于滚动、编辑内容等原因造成)。其参数from和to给出了可视区新的起始位置。swapDoc: (instance: CodeMirror, oldDoc: Doc)
当编辑器的document被使用swapDoc方法更换掉时触发。gutterClick: (instance: CodeMirror, line: integer, gutter: string, clickEvent: Event)
每当编辑器的gutter被点击时触发。其参数分别为编辑器实例;为被点击的行数,从0开始计数;+ gutter的CSS class名;mousedown的原始事件。gutterContextMenu: (instance: CodeMirror, line: integer, gutter: string, contextMenu: Event)
每当编辑器的gutter收到contextmenu事件时触发。与gutterClick不同的是,最后一个参数是contextmenu事件。你可以preventDefault这个事件,这会通知CodeMirror不再进一步handle。focus: (instace: CodeMirror)
当编辑器获得焦点时触发。blur: (instance: CodeMirror)
当编辑器失去焦点时触发。scroll: (instance: CodeMirror)
当编辑器滚动时触发。scrollCursorIntoView (instance: CodeMirror, event: Event)
update: (instance: CodeMirror)
每当CodeMirror更新它的DOM展示时触发。renderLine (instance: CodeMirror, line: LineHandle, element: Element)
每当一行需要被绘制(重绘)成DOM时触发。它触发在DOM元素建立好之后,但在加入document之前。handler可以改动该元素的样式,或是为其添加event handlers,但不该尝试改变编辑器的状态。mousedown, dbclick, touchstart, contextmenu, keydown, keypress, keyup, cut, copy ,paste, dragstart, dragenter, dragover, dragleave, drop: (instance: CodeMirror, event: Event)
当CodeMirrorhandle这些DOm事件时触发。你可以preventDefault这些事件,也可以把它们的codemirrorIgnore属性设为真值,以告知CodeMirror不要再继续handle。文档对象(Document objects, CodeMirror.Doc的实例)change: (doc: CodeMirror.Doc, changeObj: object)
每当document发生改变时触发。参数changeObj类似于编辑器change事件的changeObj。beforeChange: (doc: CodeMirror.Doc, change: object)
参见编辑器的同名事件。cursorActivity: (doc: CodeMirror.Doc)
每当document中的光标和选区变化时触发。beforeSelectionChange: (doc: CodeMirror.Doc, selection: {head, anchor})
参见编辑器的同名事件。Line handles as returned by, for example, getLineHandle
可以理解为行对象delete: ()
当行对象被删除时触发。change: (line: LineHandle, changeObj: object)
当行对象中的内容发生改变(但这一行并没有被完全删除)时触发。changeObj跟编辑器对象的同名事件一样。

Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK