AceEditor && CodeMirror && jsondiffpatch 使用

419 阅读4分钟

一、 AceEditor

功能:支持搜索,代码折叠(json,java),编辑形式,或者只读形式,1M数据不卡顿

1. 安装步骤

安装 react-ace

react-ace 是一个 React 组件库,允许你在 React 项目中使用 Ace Editor。

npm install react-ace --save
yarn add react-ace --save

"react-ace": "12.0.0",

安装 ace-builds

ace-builds 包含 Ace Editor 的核心文件和模块。需要它来提供编辑功能。

npm install ace-builds --save
yarn add ace-builds --save

"ace-builds": "1.36.2",

2.使用 AceEditor

安装完这些包后,你可以在项目中进行引入并使用。

import React, { useEffect, useRef } from 'react'
import AceEditor from 'react-ace'
//支持json格式
import 'ace-builds/src-noconflict/mode-json'
//支持java格式
import 'ace-builds/src-noconflict/mode-java'
////支持各种样式
import 'ace-builds/src-noconflict/theme-monokai'
// import 'ace-builds/src-noconflict/theme-twilight'
// import 'ace-builds/src-noconflict/theme-solarized_dark'
// import 'ace-builds/src-noconflict/theme-dracula'
// import 'ace-builds/src-noconflict/theme-chaos'
// import 'ace-builds/src-noconflict/theme-terminal'
// import 'ace-builds/src-noconflict/theme-gruvbox'
// 导入搜索框扩展
import 'ace-builds/src-noconflict/ext-searchbox'
//引入自定义样式
import '@/pages/lark/styles/aceEditor.scss'
const CustomeCanvas = observer((props: any) => {

    const aceEditorRef = useRef<any>()
    useEffect(() => {
    if (aceEditorRef && aceEditorRef.current) {
      // 加载aceEditor搜索
      const editor = aceEditorRef.current.editor
      editor.commands.addCommand({
        name: 'showSearchBox',
        bindKey: { win: 'Ctrl-F', mac: 'Command-F' },
        exec: () => {
          editor.execCommand('find')
        },
      })
    }
    }, [aceEditorRef, aceEditorRef.current])
    return (
        <AceEditor
          ref={aceEditorRef}
          mode="json"
          theme="monokai"
          name="code_editor"
          onChange={onChangeJsonParams}
          fontSize={14}
          showPrintMargin
          showGutter
          highlightActiveLine={false}
          value={jsonParams}
          wrapEnabled // 启用代码换行
          // readOnly    //是否支持编辑
          setOptions={{
            enableBasicAutocompletion: true,
            enableLiveAutocompletion: true,
            enableSnippets: true,
            showLineNumbers: true,
            tabSize: 2, // 空格
            printMargin: false, // 隐藏中间的边距线
          }}
          style={{ width: '100%', height: '830px' }}
        />
    )
})
export default CustomeCanvas

自定义样式

.ace_editor .ace_line {
  line-height: 1.5; /* 设置行间距为1.5倍 */
}
//左侧序列号模块
.ace_gutter {
  background: #282c34;
  color: #7d8799;
}
.ace_layer .ace_gutter-layer .ace_folding-enabled {
  background: #282c34 !important;
  color: #7d8799 !important;
}
.ace_gutter-active-line .ace_gutter-cell {
  background: #282c34;
  color: #7d8799;
}
.ace-monokai .ace_gutter-active-line {
  background: #282c34;
  color: #7d8799;
}
.ace-monokai .ace_gutter {
  background: #282c34;
  color: #7d8799;
}
//右侧JSON数据展示模块
//整个模块背景色
.ace_scroller {
  background: #282c34;
  color: #7d8799;
  font-family: monospace;
}
//key
.ace_variable {
  color: #e06c75 !important;
}
//字符类型
.ace_string {
  color: #98c379 !important;
}
//Boolean类型
.ace-monokai .ace_constant.ace_character,
.ace-monokai .ace_constant.ace_language,
.ace-monokai .ace_constant.ace_numeric,
.ace-monokai .ace_constant.ace_other {
  color: #d19a66 !important;
}
//{}和[]的颜色
.ace_line_group {
  color: rgba(255, 255, 255, 0.6) !important; /* 白色,50%透明度 */
}
//选中数据的样式
.ace-monokai .ace_marker-layer .ace_selection {
  background-color: #72a1ff59;
  outline: 1px solid #457dff;
  border-radius: 0 !important;
}
.ace-monokai .ace_marker-layer .ace_selected-word {
  border: 1px solid #457dff;
  border-radius: 0 !important;
}

二、 CodeMirror

功能:支持搜索,代码折叠(json,java),编辑形式,或者只读形式,100k以上数据卡顿,样式效果更美观

1. 安装步骤

安装 @uiw/react-codemirror

npm install @uiw/react-codemirror --save 
yarn add @uiw/react-codemirror --save

"@uiw/react-codemirror": "4.23.6",

安装 @codemirror/lang-json

npm install @codemirror/lang-json --save 
yarn add @codemirror/lang-json --save

"@codemirror/lang-json": "6.0.1",

安装 @codemirror/lang-java

npm install @codemirror/lang-java --save 
yarn add @codemirror/lang-java --save

"@codemirror/lang-java": "6.0.1",

安装 @codemirror/theme-one-dark

npm install @codemirror/theme-one-dark --save 
yarn add @codemirror/theme-one-dark --save

"@codemirror/theme-one-dark": "6.1.2",

安装 @codemirror/state

npm install @codemirror/state --save 
yarn add @codemirror/state --save

"@codemirror/state": "6.4.1",

2.使用 CodeMirror

安装完这些包后,你可以在项目中进行引入并使用。

const Public = observer((props: any) => {
    import React, { useEffect, useRef } from 'react' 
    import CodeMirror from '@uiw/react-codemirror'
    //支持json格式
    import { json } from '@codemirror/lang-json'
    //支持java格式
    import { java } from '@codemirror/lang-java'
    //暗色样式
    import { oneDark } from '@codemirror/theme-one-dark'
    
    import { EditorState } from '@codemirror/state'
    return (
        <CodeMirror
          value={
            isValidJSON(currentJsonRow[currentJsonType])
              ? JSON.stringify(JSON.parse(currentJsonRow[currentJsonType]), null, 2)
              : ''
          }
          height="620px"
          extensions={[
            json(),
            //java(),
            // EditorView.editable.of(false),
            EditorState.readOnly.of(true),  //不可编辑只读编辑时注释掉
            // keymap.of([...defaultKeymap, ...searchKeymap]),
          ]}
          theme={oneDark}
          // onChange={onChangeJsonParams}
        /> 
    )
})

三、 jsondiffpatch

功能:是一个用于结构化Diff对比 JSON 对象的工具库

1. 安装步骤

npm install jsondiffpatch
yarn add jsondiffpatch

2.使用 jsondiffpatch

import React, { useState, useEffect, useRef } from 'react'
import jsondiffpatch from 'jsondiffpatch'
import 'jsondiffpatch/dist/formatters-styles/html.css' // 引入默认样式
const VersionDia = observer((props: any) => {
    const [diffResult, setDiffResult] = useState<any>(null)
     //只能对比同层级对象里的数据,同一层级对象的数据可以乱序,每一层级对象里都需要筛选唯一标识
     // 创建自定义实例,根据 id 匹配对象
    const jsondiffpatchInstance = jsondiffpatch.create({
    objectHash: (obj: any) => {
      console.log('obj', obj, obj.bizIdList)
      if (obj.id && obj.component) {
        return obj.id
      }
      if (obj.name && obj.bizType && obj.sysType) {
        return obj.name
      }
      if (obj.strategyId && obj.expKey && obj.layerId) {
        return obj.strategyId
      }
      if (obj.label && obj.value) {
        return obj.label
      }
      return true
    }, // 使用 id 作为唯一标识符
    arrays: {
      detectMove: true, // 检测元素移动
      includeValueOnMove: true, // 显示移动的具体值
    },
    // propertyFilter(name: any) {
    //   return name !== '$$hashKey' // 忽略Angular的内部属性
    // },
    // cloneDiffValues: true,
    })

    // 处理当前node数据的dsl对比
    useEffect(() => {
    if (nodesDiff && nodesDiff[currentRow.nodeId]) {
      const leftTemp = nodesDiff[currentRow.nodeId].left
      const rightTemp = nodesDiff[currentRow.nodeId].right
      const delta: any = jsondiffpatchInstance.diff(leftTemp, rightTemp)
      setLeft(leftTemp)
      setDiffResult(delta || null)
    }
    }, [nodesDiff, currentRow])
    
    const renderDiff = () => {
    if (!diffResult || !left) return null
      const formatter = jsondiffpatch.formatters.html
      return (
        <div style={{ background: '#f5f5f5', padding: '10px' }}>
          <div dangerouslySetInnerHTML={{ __html: formatter.format(diffResult, left) }} />
        </div>
      )
    }
    return (
        <div>{renderDiff()}</div>
    )
})