React中CodeMirror插件的使用及封装

Posted 大聪明码农徐

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了React中CodeMirror插件的使用及封装相关的知识,希望对你有一定的参考价值。

目录

一、CodeMirror是什么

二、React中CodeMirror的基本使用介绍

(一)引入CodeMirror

1. 安装CodeMirror插件

2.引入 CodeMirror 插件

(二)引入文件配置

(三)关键属性解读

1.value

2.mode

3.theme

4.readOnly

5.options

(四)CodeMirror内容更新

三、CodeMirror的封装详解


一、CodeMirror是什么

        在前端交互丰富的业务场景中,难免会遇到需要编译器的情况。CodeMirror是一个代码编辑器组件,可以嵌入到Web页面中。用来满足代码书写的交互场景。

        例如:

二、React中CodeMirror的基本使用介绍

详细的中文文档参考博客:CodeMirror用户手册_LingMax2013的博客-CSDN博客_codemirror中文文档

英文文档参考官网:

 CodeMirror 5 User Manual

(一)引入CodeMirror

1. 安装CodeMirror插件

npm install codemirror react-codemirror2 --save      //安装CodeMirror

2.引入 CodeMirror 插件

import CodeMirror from 'react-codemirror';

(二)引入文件配置

require('codemirror/lib/codemirror.css');//关键信息引入
require('codemirror/theme/seti.css');//引入主题颜色
require('codemirror/addon/display/fullscreen.css');
require('../../styles/codemirror.less');//引入样式
require('codemirror/addon/display/panel');
require('codemirror/mode/xml/xml');//引入编辑语言  xml
require('codemirror/mode/javascript/javascript');//引入编辑语言  JavaScript
require('codemirror/mode/yaml/yaml');//引入编辑语言 yaml
require('codemirror/addon/display/fullscreen');
require('codemirror/addon/edit/matchbrackets');
require ('codemirror/addon/selection/active-line');//代码高亮
require ('codemirror/addon/fold/foldgutter.css'); // 代码折叠
require ('codemirror/addon/fold/foldcode.js');// 代码折叠
require ('codemirror/addon/fold/foldgutter.js');  // 代码折叠
require ('codemirror/addon/fold/brace-fold.js');  // 代码折叠
require ('codemirror/addon/fold/comment-fold.js');// 代码折叠

(三)关键属性解读

1.value

        作为插件的初始值,写入命令行内。

2.mode

        作为鉴定输入文本框的文本类型,如JavaScript和yaml文件。

3.theme

        引入的主题。

4.readOnly

        设置为是否可读。

5.options

        各类配置的集合,作为属性传入CodeMirror插件之中

(四)CodeMirror内容更新

        调用官方文档中的setValue方法,具体可查看官方文档。

        先获取dom节点,通过ref或者设置id拿到真实的dom节点,在通过dom.setValue设置新的内容。


//使用引入的codemirror组件
  <CodeMirror
       options=options
       value=text ? text :"-" 
       ref=(c) => this.myCodeMirror = c//添加ref属性获取dome节点
  />
//通过点击事件获取新的内容
    showDrawer = (val) => 
        if (this.myCodeMirror != (undefined || null))
            const editor = this.myCodeMirror.getCodeMirror();
            editor.setValue(val)
        
        this.setState(
            showDrawerswitch: !this.state.showDrawerswitch
        )
    

三、CodeMirror的封装详解

import  Upload  from 'antd';
import React,  PureComponent  from 'react';
import CodeMirror from 'react-codemirror';
import apiconfig from '../../../config/api.config';
import cookie from '../../utils/cookie';
import globalUtil from '../../utils/global';
import styles from './index.less';

require('codemirror/lib/codemirror.css');
require('codemirror/theme/seti.css');
require('codemirror/addon/display/fullscreen.css');
require('../../styles/codemirror.less');
require('codemirror/addon/display/panel');
require('codemirror/mode/xml/xml');
require('codemirror/mode/javascript/javascript');
require('codemirror/mode/yaml/yaml');
require('codemirror/addon/display/fullscreen');
require('codemirror/addon/edit/matchbrackets');

// eslint-disable-next-line react/no-redundant-should-component-update
class CodeMirrorForm extends PureComponent 
  constructor(props) 
    super(props);
    this.state = 
      fullScreen: false
    ;
    this.CodeMirrorRef = '';
  
  componentWillReceiveProps(nextProps) 
    const  name, data, setFieldsValue  = this.props;
    const  CodeMirrorRef  = this;
    if (data !== nextProps.data && CodeMirrorRef) 
      setFieldsValue(
        [name]: nextProps.data
      );
      if (CodeMirrorRef) 
        const editor = CodeMirrorRef.getCodeMirror();
        editor.setValue(nextProps.data);
      
    
  
  saveRef = ref => 
    this.CodeMirrorRef = ref;
    const  saveRef = false  = this.props;
    if (saveRef) 
      saveRef(ref);
    
  ;

  handleChangeUpload = info => 
    const  beforeUpload  = this.props;
    if (beforeUpload) 
      if (beforeUpload(info.file, false)) 
        this.handleFile(info);
      
      return null;
    

    return this.handleFile(info);
  ;
  handleFile = info => 
    let fileList = [...info.fileList];
    if (fileList.length > 0) 
      fileList = fileList.slice(-1);
      this.readFileContents(fileList, 'file_content');
    
  ;

  readFileContents = fileList => 
    let fileString = '';
    const  CodeMirrorRef  = this;
    const  name, setFieldsValue  = this.props;
    for (let i = 0; i < fileList.length; i++) 
      const reader = new FileReader(); // 新建一个FileReader
      reader.readAsText(fileList[i].originFileObj, 'UTF-8'); // 读取文件
      // eslint-disable-next-line no-loop-func
      reader.onload = evt => 
        // 读取完文件之后会回来这里
        fileString += evt.target.result; // 读取文件内容
        setFieldsValue(
          [name]: fileString
        );
        if (CodeMirrorRef) 
          const editor = CodeMirrorRef.getCodeMirror();
          editor.setValue(fileString);
        
      ;
    
  ;
  checkValue = (_, value, callback) => 
    const  message  = this.props;
    if (value === '' || !value || (value && value.trim() === '')) 
      callback(message);
      return;
    
    callback();
  ;

  render() 
    const 
      Form,
      getFieldDecorator,
      formItemLayout,
      data,
      label,
      name,
      message,
      width: proWidth,
      mode,
      action,
      beforeUpload,
      isHeader = true,
      isUpload = true,
      isAmplifications = true,
      disabled = false,
      titles,
      bg = '#333',
      help
     = this.props;
    const  fullScreen  = this.state;
    let defaultFullScreenStyle = 
      display: 'flex',
      justifyContent: 'space-between',
      cursor: 'pointer',
      top: '0',
      textAlign: 'left',
      background: bg,
      lineHeight: '1px',
      padding: '9px 0 6px 0'
    ;

    if (fullScreen) 
      defaultFullScreenStyle = Object.assign(defaultFullScreenStyle, 
        position: 'fixed',
        right: '5px',
        width: '100%',
        zIndex: 99
      );
     else 
      defaultFullScreenStyle = Object.assign(defaultFullScreenStyle, 
        position: 'absolute',
        width: proWidth || '100%',
        zIndex: 4
      );
    

    const options = 
      mode:  name: mode || 'javascript', json: true ,
      lineNumbers: true,
      theme: 'seti',
      fullScreen,
      lineWrapping: true,
      smartIndent: true,
      matchBrackets: true,
      scrollbarStyle: null,
      showCursorWhenSelecting: true,
      readOnly: disabled
    ;

    const token = cookie.get('token');
    const amplifications = (
      <span
        style= margin: '0 20px' 
        onClick=() => 
          this.setState( fullScreen: !this.state.fullScreen );
        
      >
        globalUtil.fetchSvg('amplifications')
      </span>
    );
    return (
      <Form.Item
        ...formItemLayout
        label=label
        help=help && <span style= color: 'red' >help</span>
        className=
          fullScreen
            ? `$styles.fullScreens $styles.childrenWidth`
            : styles.childrenWidth
        
      >
        getFieldDecorator(name, 
          initialValue: data || '',
          rules: [ required: true, validator: this.checkValue ]
        )(<CodeMirror options=options ref=this.saveRef />)
        amplifications
        isHeader && (
          <div style=defaultFullScreenStyle>
            <div
              style= lineHeight: '20px', paddingLeft: '30px', color: '#fff' 
            >
              titles || ''
            </div>
            <div>
              isUpload && (
                <Upload
                  action=
                    action ||
                    `$apiconfig.baseUrl/console/enterprise/team/certificate`
                  
                  showUploadList=false
                  withCredentials
                  headers= Authorization: `GRJWT $token` 
                  beforeUpload=beforeUpload || false
                  onChange=this.handleChangeUpload
                >
                  globalUtil.fetchSvg('uploads')
                </Upload>
              )
              isAmplifications && amplifications
            </div>
          </div>
        )
      </Form.Item>
    );
  


export default CodeMirrorForm;

codemirror angularjs 多文件自适应高亮编辑

一个项目的扫尾工作,在原来的angular项目上加一个代码编辑器,codemirror,插件支持大部分的代码编辑,高亮。下面来说一下codemirror插件的使用过程:

1.用npm安装angularjs的codemirror插件到项目中,目前使用的版本为0.3.0

2.安装完以后引入必要的依赖:

<link rel="stylesheet" href="../codemirror/lib/codemirror.css" />
<script src="../codemirror/lib/codemirror.js"></script>
<script src="../angular-ui-codemirror/ui-codemirror.js"></script>

需要高亮那种语言,引入不同的依赖,

<script src="../codemirror/mode/xml/xml.js"></script>
<script src="../codemirror/mode/markdown/markdown.js"></script>
<script src="../codemirror/mode/yaml/yaml.js"></script>
<script src="../codemirror/mode/javascript/javascript.js"></script>
......

 

3.在html文件中编写:

//多文件切换
<select style="margin-top: -19px" class="pull-right" ng-model="mode" ng-change="modeChanged()">
<option value="" selected="selected">-请选择修改-</option>
<option ng-repeat="m in modes" value="{{m.id}}">{{m.filename}}</option>
</select>
<div ui-codemirror="cmOption" ng-model="cmModel">

或者把div改成textarea标签,或者直接使用:<ui-codemirror>标签。

4.js初始化多文件切换

var j;
  $scope.cmOption = {
    lineWrapping : true,
    lineNumbers: true,
    indentWithTabs: true,
    onLoad : function(_cm){

      // HACK to have the codemirror instance in the scope...
      $scope.modeChanged = function(){
        var filename=‘‘;
        for(var d = 0;d < $scope.config.filecontent.length;d++){
          if($scope.mode===$scope.config.filecontent[d].id){
            filename = $scope.config.filecontent[d].filename;
          }
        }
        if(filename.indexOf(‘.md‘) >0){
          _cm.setOption("mode", ‘markdown‘);
        }else if(filename.indexOf(‘.yml‘) >0){
          _cm.setOption("mode", ‘yaml‘);
        }else if(filename.indexOf(‘.json‘) >0){
          _cm.setOption("mode", ‘javascript‘);
        }else{
          _cm.setOption("mode", ‘xml‘);
        }
        var i=0;
        for(;i < $scope.config.filecontent.length;i++){
          if($scope.mode===$scope.config.filecontent[i].id){
            $scope.cmModel = $scope.config.filecontent[i].filecontent;
            j = $scope.mode;
          }
        }

        // watch();
      };

    }
  };
  $scope.$watch(‘cmModel‘,function(newValue,oldValue, scope){
    console.log(j);
    for(var i = 0;i < $scope.config.filecontent.length;i++){
      if(j===$scope.config.filecontent[i].id){
        $scope.config.filecontent[i].filecontent = newValue;
      }
    }

  });

 

当前可以监控不同的文件,实时修改多个文件,一次提交。

 










以上是关于React中CodeMirror插件的使用及封装的主要内容,如果未能解决你的问题,请参考以下文章

CodeMirror使用

codemirror angularjs 多文件自适应高亮编辑

CodeMirror编辑器文本框Textarea代码高亮插件,CodeMirror的简单实用例子

作为初级前端我知道的插件(React版)

在线代码编辑器---codemirror插件

react项目可以引入jstree插件吗