vue2
- 安装
yarn add codemirror
yarn add vue-codemirror
2. 使用
先来看一下 codemirror-vue 暴露的参数
<!-- codeEditor.vue -->
<template>
<codemirror
class="codemirror-box"
ref="codeEditor"
v-model="editor"
:options="cmoptions"
@input="onInput"
></codemirror>
</template>
<script>
import { codemirror } from 'vue-codemirror'
import 'codemirror/lib/codemirror.css' // 核心样式
import 'codemirror/theme/idea.css' // 主题样式 gruvbox-dark material panda-syntax seti nord shadowfox
import 'codemirror/mode/javascript/javascript.js'
import 'codemirror/mode/yaml/yaml.js'
import 'codemirror/mode/nginx/nginx.js'
import 'codemirror/addon/selection/active-line.js' // 当前行背景高亮
import 'codemirror/addon/edit/matchbrackets.js' // 括号匹配
import 'codemirror/addon/edit/closebrackets.js' // 自动闭合括号
import 'codemirror/addon/edit/matchtags.js' // html标签匹配
import 'codemirror/addon/edit/closetag.js' // 自动闭合html标签
import 'codemirror/addon/scroll/simplescrollbars.js' // 滚动条
import 'codemirror/addon/scroll/simplescrollbars.css' // 滚动条
import 'codemirror/addon/fold/brace-fold.js' // javascript 代码折叠
import 'codemirror/addon/fold/indent-fold.js' // yaml代码折叠
// import 'codemirror/addon/fold/markdown-fold.js' // 代码折叠
// import 'codemirror/addon/fold/comment-fold.js' // 代码折叠
import 'codemirror/addon/fold/foldcode.js' // 代码折叠
import 'codemirror/addon/fold/foldgutter.js' // 代码折叠
import 'codemirror/addon/fold/foldgutter.css' // 代码折叠样式
export default {
name: 'cmCodeEditor',
components: {
codemirror
},
model: {
prop: 'value',
event: 'input'
},
props: {
value: {
type: String,
default: ''
},
readonly: {
type: Boolean,
default: false
},
fileName: {
type: String,
default: ''
}
},
data() {
return {
editor: null,
cmoptions: {
tabSize: 4,
mode: 'javascript',
theme: 'idea',
lineNumbers: true, // 显示行号
readOnly: this.readonly, // 只读
indentUnit: 4, // 缩进单位为4
indentWithTabs: true, // 使用制表符进行缩进
styleActiveLine: true, // 当前行背景高亮
foldGutter: true, // 代码折叠
gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter'], // 代码折叠
lineWrapping: true, // 自动换行
scrollbarStyle: 'simple' // 滚动条样式
}
}
},
watch: {
value: {
handler(val) {
this.editor = val
},
immediate: true
},
fileName: {
handler(val) {
let fileType = val.split('.').pop()
if (!fileType) {
this.cmoptions.mode = 'javascript'
return
}
switch (fileType) {
case 'yaml':
this.cmoptions.mode = 'yaml'
break
case 'conf':
this.cmoptions.mode = 'nginx'
break
default:
this.cmoptions.mode = 'javascript'
break
}
},
immediate: true
}
},
methods: {
onInput(val) {
this.$emit('input', val)
}
}
}
</script>
<style lang="scss">
.codemirror-box {
border: 1px solid rgb(107, 105, 105);
.CodeMirror {
background: #fff !important;
height: 500px;
width: 100%;
font-size: 14px;
line-height: 1.5;
font-family: 'Source Code Pro', monospace;
}
}
.CodeMirror-gutters {
background: #f5f5f5 !important;
}
.CodeMirror-linenumber {
color: #6c6c6c !important;
}
</style>
vue3
- 安装
只安装 vue-codemirror 会报错,用vue-codemirror同时需要安装 codemirror
yarn add codemirror
yarn add vue-codemirror
// 语言包
yarn add @codemirror/lang-javascript
yarn add @codemirror/language
yarn add @codemirror/legacy-modes // 这里也包含了JavaScript 语言包,但是没有折叠
- 封装编辑框
引入Codemirror-vue(6.11)的组件属性:
<!-- codeEditor.vue -->
<template>
<div class="codemirror-box">
<Codemirror
ref="cm"
class="code-input"
v-model="code"
:disabled="props.readonly"
:extensions="extensions"
@change="inputChange"
></Codemirror>
</div>
</template>
<script setup>
import { ref, defineProps, watch, defineEmits, computed } from 'vue'
import { Codemirror } from 'vue-codemirror' // 引入组件
import { javascript } from "@codemirror/lang-javascript" // 引入语言包
import { basicSetup } from "codemirror" // 引入语言包
import { StreamLanguage } from "@codemirror/language"
import { yaml } from "@codemirror/legacy-modes/mode/yaml" // 引入语言包
import { nginx } from "@codemirror/legacy-modes/mode/nginx" // 引入语言包
// import { oneDark } from "@codemirror/theme-one-dark" // 引入主题包
const props = defineProps({
value: {
type: String,
default: ''
},
readonly: {
type: Boolean,
default: false
},
fileName: {
type: String,
default: ''
}
})
const code = ref(`console.log('Hello, world!');console.log('Hello, world!');`)
const getOptions = (fileName) => {
if (!fileName.includes('.')) {
return 'javascript'
}
const ext = fileName.split('.').pop()
switch(ext) {
case 'yaml':
return 'yaml'
case 'conf':
return 'nginx'
default:
return 'javascript'
}
}
// extensions 在支持多种语言时,优先采用第一种,会导致第二种语言无法高亮
const extensions = computed(() => {
let _extensions = []
const option = getOptions(props.fileName)
switch(option) {
case 'yaml':
_extensions = [
basicSetup,
StreamLanguage.define(yaml)
]
break;
case 'nginx':
_extensions = [
basicSetup,
StreamLanguage.define(nginx)
]
break;
default:
_extensions = [
basicSetup,
javascript()
]
break;
}
return _extensions
})
watch(
() => props.value,
(val) => {
code.value = val
},
{
immediate: true
}
)
const emit = defineEmits(['input'])
const inputChange = (val) => {
emit('input', val)
}
</script>
<style lang="scss">
.codemirror-box {
width: 100%;
height: 500px;
overflow-y: scroll;
border: 1px solid #333;
.code-input {
width: 100%;
min-height: 500px;
border: 0;
}
}
.ͼ1.cm-focused {
outline: none;
}
</style>
// 调用 codeEditor组件
<template>
<code-editor v-model:value="content" ref="cmCodeEditor" @input="codeChange" :file-name="fileName" :readonly="readonly"></code-editor>
</template>
<script setup>
import codeEditor from './codeEditor.vue'
</script>