4

一、背景

由于项目需要用到 json 编辑功能,尝试使用过 v-jsoneditor, vue-json-editorvue-codemirror, 使用都不尽人意,一番尝试之后,用 codemirror 成功满足需求,小记录一下。

二、codemirror介绍

CodeMirror 是使用 JavaScript 为浏览器实现的多功能文本编辑器。它专门用于编辑代码,并具有实现更高级编辑功能的多种语言模式 (language mode)和附加组件(addon)。
CodeMirror 具有丰富的 APICSS 主题系统,方便用户为其应用程序作定制化,并且易于扩展。本文主要聚焦于在 vue 工程中 json 的编辑功能。

三、codemirror使用

1. 所需依赖

npm install --save codemirror
npm install --save jsonlint

没有使用 vue-codemirror,直接在 vue 中使用 codemirror
此外,需要安装一个开发依赖 script-loader,方便引入 jsonlint

npm install --save-dev script-loader

我安装的版本如下:

"codemirror": "^5.59.2",
"jsonlint": "^1.6.3",
"script-loader": "^0.7.2",

2. JsonEditor 组件

直接封装好 JsonEditor 组件,在 src/components 新建 JsonEditor.vue 文件,如下
image.png
直接上代码

<template>
  <div class="json-editor">
    <textarea ref="textarea"></textarea>
  </div>
</template>
<script>
// 核心文件
import CodeMirror from 'codemirror'
import 'codemirror/lib/codemirror.css'
import 'codemirror/mode/javascript/javascript' // 代码高亮必须引入

// 代码错误检查
// eslint-disable-next-line import/no-webpack-loader-syntax
require('script-loader!jsonlint')
import 'codemirror/addon/lint/lint.css'
import 'codemirror/addon/lint/lint'
import 'codemirror/addon/lint/json-lint'

// 主题样式
import 'codemirror/theme/rubyblue.css'
// 括号显示匹配
import 'codemirror/addon/edit/matchbrackets'
import 'codemirror/addon/selection/active-line'
// 括号、引号编辑和删除时成对出现
import 'codemirror/addon/edit/closebrackets'


export default {
  name: 'JsonEditor',
  props: {
    json: {
      type: String,
      default: '',
    },
  },
  data() {
    return {
      jsonEditor: null,
    }
  },
  watch: {
    json(val) {
      const editorValue = this.jsonEditor.getValue()
      if (val !== editorValue) {
        this.jsonEditor.setValue(this.json)
      }
    },
  },
  mounted() {
    this.jsonEditor = CodeMirror.fromTextArea(this.$refs.textarea, {
      mode: 'application/json',
      theme: 'rubyblue', // 主日样式
      lint: true,
      tabSize: 2,
      smartIndent: true, // 是否智能缩进
      styleActiveLine: true, // 当前行高亮
      lineNumbers: true, // 显示行号
      gutters: ['CodeMirror-lint-markers'],
      lineWrapping: true, // 自动换行
      matchBrackets: true, // 括号匹配显示
      autoCloseBrackets: true, // 输入和退格时成对
      autoRefresh: true, // 自动刷新
    })
    this.jsonEditor.on('change', cm => {
      this.$emit('change', cm.getValue())
    })
  },
  methods: {
    refresh() {
      /*
       * refresh: Fires when the editor is refreshed or resized.
       * Mostly useful to invalidate cached values that depend on the editor or character size. 
       */ 
      this.jsonEditor && this.jsonEditor.refresh()
    },
  },
}
</script>
<style scoped>
  .json-editor {
    height: 100%;
    position: relative;
  }
  .json-editor >>> .CodeMirror {
    height: auto;
    min-height: 250px;
  }
  .json-editor >>> .CodeMirror-scroll {
     min-height: 250px;
  }
  .json-editor >>> .cm-s-rubyblue span.cm-string {
    color: #f08047;
  }
</style>

其中,需要注意的是代码主题样式可以根据自己的喜好去官网选择,并引入相应的 css 文件即可,我选择的是 rubyblue 这个主题
image.png
还有个坑就是当编辑器隐藏和显示时,容易出现样式错乱
image.png
解决方法是将 autoRefresh 设为 true,并且加上 refresh 函数,每次打开编辑器时刷新一下编辑器,具体可以参考一下这篇文章 https://www.cnblogs.com/wenru...

3. 使用

使用起来很方便,需要的地方直接引入 JsonEditor 组件,直接上代码

<template>
  <div>
    <json-editor
      ref="jsonEditor"
      :json="json"
      @change="handleJsonChange"
    />
  </div>
</template>
<script>
import JsonEditor from '@/components/JsonEditor'
export default {
  components: {
    JsonEditor,
  },
  data() {
    json: '',
  },
  mounted() {
    // 刷新jsonEditor
    this.$nextTick(() => {
      this.$refs.jsonEditor.refresh()
    })
  },
  methods: {
    handleJsonChange(val) {
      if (this.json !== val) {
        this.json = val
      }
    },
  }
}
</script>

这样就可以愉快地编写 json 代码了
image.png
也会提示格式错误。如果输入的 json 是需要提交的,可以通过 JSON.parse 来进行校验,阻止提交

// ...
// 判断表达式是否符合要求
if (this.json) {
  try {
    JSON.parse(this.json)
  } catch (e) {
    this.$message.warning('请输入正确的 json')
    return
  }
}
// ...

CodeMirror 功能非常强大,如代码自动补全、代码折叠、绑定 vim 和 设置快捷键等功能,可以官网上查找,本文只记录了笔者所用到的一些简单的功能。


见贤思齐
66 声望8 粉丝

写代码的