• 编辑器reactcodemirror2的封装组件简单使用


    1、下载安装

    npm install react-codemirror2 codemirror --save

    2、引入

    //引入Codemirror组件
    import Cm from './extendCodeMirror.js'; import { UnControlled as CodeMirror } from 'react-codemirror2';
      //样式
      import 'codemirror/lib/codemirror.css';
      import 'codemirror/lib/codemirror.js';

      import 'codemirror/theme/dracula.css';   //主题
     
      //代码折叠
     
      import 'codemirror/addon/fold/foldgutter.css';
      import 'codemirror/addon/lint/lint.css';
      import 'codemirror/addon/fold/foldcode.js';
      import 'codemirror/addon/fold/foldgutter.js';
      import 'codemirror/addon/fold/brace-fold.js';
      import 'codemirror/addon/hint/javascript-hint.js';
      import 'codemirror/addon/hint/show-hint.js';
      import 'codemirror/addon/lint/lint.js';
      import 'codemirror/addon/lint/json-lint.js';
      import 'codemirror/addon/lint/javascript-lint.js';
      import 'codemirror/addon/display/placeholder.js';
      import 'codemirror/mode/javascript/javascript.js';
     
      import 'codemirror/mode/sql/sql.js';
     
     
      很多属性配置,需要将对应文件引入才生效
     
     
     
    //详细信息配置可以查看:https://codemirror.net,我这里用的是json/js/sql ,
    //https://www.tun6.com/projects/code_mirror//  这里的也很全面
       

       

    import React, { useState, useEffect, useRef, useCallback } from 'react';
    import { connect } from 'dva';
    import { Form, Input, Button } from 'antd';
    import styles from './style.less';
    import Cm from './extendCodeMirror.js';
    import { UnControlled as CodeMirror } from 'react-codemirror2';
    
    // import * as sqlFormatter from 'sql-formatter';
    
    import 'codemirror/lib/codemirror.css';
    import 'codemirror/lib/codemirror.js';
    
    import 'codemirror/theme/dracula.css';
    import 'codemirror/addon/fold/foldgutter.css';
    
    import 'codemirror/addon/lint/lint.css';
    import 'codemirror/addon/fold/foldcode.js';
    import 'codemirror/addon/fold/foldgutter.js';
    import 'codemirror/addon/fold/brace-fold.js';
    import 'codemirror/addon/hint/javascript-hint.js';
    import 'codemirror/addon/hint/show-hint.js';
    import 'codemirror/addon/lint/lint.js';
    import 'codemirror/addon/lint/json-lint.js';
    import 'codemirror/addon/lint/javascript-lint.js';
    import 'codemirror/addon/display/placeholder.js';
    import 'codemirror/mode/javascript/javascript.js';
    import 'codemirror/mode/sql/sql.js';
    
    const sqlFormatter = require('sql-formatter');
    
    const Editors = (props) => {
      const { dispatch, title, type, editorList, rules, editorListErr } = props;
    
      const [editorVal, sEditorVal] = useState('');
      const formRefs = useRef(null);
      const [editorBorder, sEditorBorder] = useState('none');
      // let editor = null;
    
      useEffect(() => {
        if (formRefs.current) {
          // console.log(editorList,title+'title')
          editorList.map((val) => {
            if (val.name == title) {
              if (editorVal != val.value) {
                sEditorVal(val.value);
              }
            }
          });
        }
      }, [editorList]);
    
      useEffect(() => {
        //点击按钮校验
        if (editorListErr && editorListErr != 1) {
          takeEditorValue();
        }
      }, [editorListErr]);
    
      const onEditorDidMount = (editors) => {
        // editor.setSize('width', 'height'); // 设置编辑器宽高
        // 绑定其他快捷键, 这里以按下ctrl-1 格式化编辑器代码做示例
        // editor.addKeyMap({
        //   F1: autoFormatSelection(),
        // });
      };
    //格式化 const autoFormatSelection
    = () => { let editor = formRefs.current.editor; if (props.type != 'sql') { // console.log(editor, 1); const script_length = editor.getValue().length; const startPos = { line: 0, ch: 0, sticky: null }; const endPos = editor.doc.posFromIndex(script_length); editor.setSelection(startPos, endPos); editor.autoFormatRange(startPos, endPos); editor.commentRange(false, startPos, endPos); } else { let splCont = ''; splCont = editor.getValue(); editor.setValue(sqlFormatter.format(splCont)); } };
    //失焦点保存 const takeEditorValue
    = () => { let text = formRefs.current ? formRefs.current.editor.getValue() || '' : ''; // console.log(editorList,'editortexttexttexttextList') rules && !text ? sEditorBorder('1px solid red') : sEditorBorder('none'); props.getEditorList( { name: title, value: text, }, editorList ); }; // console.log(props.type); return ( <div className={styles.editors} style={{ border: editorBorder }} key={props.title + 'editors'}> <CodeMirror className={styles.editorsDom} ref={formRefs} key={props.title} editorDidMount={onEditorDidMount} value={editorVal} options={{ lineNumbers: true, mode: { name: props.type == 'sql' ? 'text/x-sql' : 'application/json' }, extraKeys: { Ctrl: autoFormatSelection }, autofocus: false, styleActiveLine: true, theme: 'dracula', lineWrapping: true, foldGutter: true, gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter'], lint: false, indentUnit: 2, cursorHeight: 0.85, placeholder: props.placeholder || '', }} onBlur={() => { takeEditorValue(); //失去焦点保存 }} /> {editorBorder != 'none' ? ( <div className={styles.editorsErrTxext} key={props.title + 'editorsErrTxext'} style={{ display: 'flex', justifyContent: 'flex-start', alignItems: 'center', color: '#f5222d' }} > {props.placeholder} </div> ) : ( '' )} </div> ); }; export default Editors;

    算了,直接贴代码吧,不想写了,只是想打断一下将近两年没来的记录

    .editors{
         100%;
        height: 100%;
        position: relative;
        
        .editorsDom{
            font-size: 16px;
            line-height: 26px;
            // border: 1px solid #e8e8e8;
        }
        .editorsErrTxext{
            position: absolute;
            left: 0;
            bottom: -24px;
            clear: both;
            min-height: 24px;
            margin-top: -2px;
            color: rgba(0, 0, 0, 0.45);
            font-size: 15px;
            line-height: 1.5;
            transition: color 0.3s cubic-bezier(0.215, 0.61, 0.355, 1)
        }
        :global(.CodeMirror) {
            min-height: 218px !important;
            height: auto !important;
            max-height: 747px !important;
        }
        :global(.CodeMirror-scroll) {
            min-height: 218px !important;
            height: auto !important;
            max-height: 747px !important;
        }
    
        :global(.CodeMirror-gutter-wrapper) {
            left: -40px !important;
        }
    }

    嗯。。。样式。。。

     嗯。。。效果

    这个是封装的组件,好了,就这吧。

    extendCodeMirror.js文件,我优化了一下

    // extendCodeMirror.js
    /* eslint-disable */
    import * as CodeMirror from 'codemirror';
    
    CodeMirror.extendMode("css", {
    commentStart: "/*",
    commentEnd: "*/",
    newlineAfterToken: function(type, content) {
      return /^[;{}]$/.test(content);
    }
    });
    
    CodeMirror.extendMode("javascript", {
    commentStart: "/*",
    commentEnd: "*/",
    // FIXME semicolons inside of for
    newlineAfterToken: function(type, content, textAfter, state) {
      if (this.jsonMode) {
        return /^[\[,{]$/.test(content) || /^}/.test(textAfter)|| /^]/.test(textAfter);
      } else {
        if (content == ";" && state.lexical && state.lexical.type == ")") return false;
        return /^[;{}]$/.test(content) && !/^;/.test(textAfter);
      }
    }
    });
    
    CodeMirror.extendMode("xml", {
    commentStart: "<!--",
    commentEnd: "-->",
    newlineAfterToken: function(type, content, textAfter) {
      return type == "tag" && />$/.test(content) || /^</.test(textAfter);
    }
    });
    
    // Comment/uncomment the specified range
    CodeMirror.defineExtension("commentRange", function (isComment, from, to) {
    var cm = this, curMode = CodeMirror.innerMode(cm.getMode(), cm.getTokenAt(from).state).mode;
    cm.operation(function() {
      if (isComment) { // Comment range
        cm.replaceRange(curMode.commentEnd, to);
        cm.replaceRange(curMode.commentStart, from);
        if (from.line == to.line && from.ch == to.ch) // An empty comment inserted - put cursor inside
          cm.setCursor(from.line, from.ch + curMode.commentStart.length);
      } else { // Uncomment range
        var selText = cm.getRange(from, to);
        var startIndex = selText.indexOf(curMode.commentStart);
        var endIndex = selText.lastIndexOf(curMode.commentEnd);
        if (startIndex > -1 && endIndex > -1 && endIndex > startIndex) {
          // Take string till comment start
          selText = selText.substr(0, startIndex)
          // From comment start till comment end
            + selText.substring(startIndex + curMode.commentStart.length, endIndex)
          // From comment end till string end
            + selText.substr(endIndex + curMode.commentEnd.length);
        }
        cm.replaceRange(selText, from, to);
      }
    });
    });
    
    // Applies automatic mode-aware indentation to the specified range
    CodeMirror.defineExtension("autoIndentRange", function (from, to) {
    var cmInstance = this;
    this.operation(function () {
      for (var i = from.line; i <= to.line; i++) {
        cmInstance.indentLine(i, "smart");
      }
    });
    });
    
    // Applies automatic formatting to the specified range
    CodeMirror.defineExtension("autoFormatRange", function (from, to) {
    var cm = this;
    var outer = cm.getMode(), text = cm.getRange(from, to).split("\n");
    var state = CodeMirror.copyState(outer, cm.getTokenAt(from).state);
    var tabSize = cm.getOption("tabSize");
    
    var out = "", lines = 0, atSol = from.ch == 0;
    function newline() {
      out += "\n";
      atSol = true;
      ++lines;
    }
    
    for (var i = 0; i < text.length; ++i) {
      var stream = new CodeMirror.StringStream(text[i], tabSize);
      while (!stream.eol()) {
        var inner = CodeMirror.innerMode(outer, state);
        var style = outer.token(stream, state), cur = stream.current();
        stream.start = stream.pos;
        if (!atSol || /\S/.test(cur)) {
          out += cur;
          atSol = false;
        }
        if (!atSol && inner.mode.newlineAfterToken &&
            inner.mode.newlineAfterToken(style, cur, stream.string.slice(stream.pos) || text[i+1] || "", inner.state))
          newline();
      }
      if (!stream.pos && outer.blankLine) outer.blankLine(state);
      if (!atSol) newline();
    }
    
    cm.operation(function () {
      cm.replaceRange(out, from, to);
      for (var cur = from.line + 1, end = from.line + lines; cur <= end; ++cur)
        cm.indentLine(cur, "smart");
      cm.setSelection(from, cm.getCursor(false));
    });
    });
    // console.log("初始化CodeMirror完成");
    export default CodeMirror;
     <EditorDom
        title={item.name}
        editorListErr={editorListErr}      //嗯,忘了干啥了,时间有点长。。。可能也没啥用吧,刚学react时候写的
        placeholder={item.placeholder} //为空显示  
        type="json"                    
        key={'JsonEditors'}        
        rules={item.rules}           //是否校验不为空
        editorList={editorList}      //数据,多个编辑器情况下
        getEditorList={getEditorList}    // 拿到最新内容,修改editorList
    />

    就这了吧,有很多可优化的地方,也不改了吧,就这吧。

  • 相关阅读:
    plsql调试存储过程卡住的原因以及处理
    JavaWeb三大组件(Servlet、Filter、Listener)的区别
    单点登录原理
    Oracle 导表异常处理方案 (解决空表导出出错问题)
    在Oracle中删除用户时提示:ORACLE无法删除当前连接用户
    VisualSvn的权限管理
    MySql常用命令总结
    Oracle 常用SQL
    参数
    java
  • 原文地址:https://www.cnblogs.com/wy120/p/16145402.html
Copyright © 2020-2023  润新知