美文网首页
react-monaco-editor 的使用

react-monaco-editor 的使用

作者: _一九九一_ | 来源:发表于2019-07-12 16:43 被阅读0次

    react-monaco-editor官方git地址

    这是我写的一个demo(最新版)

    https://github.com/ysk1991/react-monaco-editor

    • 支持光标处插入
    • 支持提示语 输入 sin cos tan 会出现提示语 输入冒号 : 会出现支持的所有提示语

    bug描述

    • 遇到一个坑,解决了很久,结果用最蠢的方式,sessionStorage解决的,如果有好的方式请留言

    • 寻找过的解决方案,但是未果,比如在组件componentWillUnmount的时候销毁这个editor,比如react-monaco-editor的api里,源码里寻找editor自带的销毁的方法,销毁的方法有,但是react-monaco-editor并没有封装提供,给我的感觉就是react-monaco-editor 提供的api太少,可能也是我源码看得不够彻底,希望有大神可以指导一下

    • 以下是bug的截图,在使用react-monaco-editor 的自定义按键代码提示时,出现了重复的数据,每一次路由变动,再次进入这个页面时,我的自定义按键提示就会多push一次,数据重复两次


    • 每一次路由变动,我的按键提示就会多push一次,数据重复三次


    • 实现自定义按键提示的方法 以及 bug的解决方式

    editorDidMountHandle = async (editor, monaco) => {
        // sessionStorage记录当前我是否来过这个页面 也就是说 是否加载执行过  monaco.languages.registerCompletionItemProvider 
       // 执行过就不再执行 当页面关闭就重新记录 因为多次执行了这个方法导致重复数据
        const isLoadDEditor = sessionStorage.getItem('isLoadDEditor');
        if (!isLoadDEditor) {
          sessionStorage.setItem('isLoadDEditor', true);
          await this.requestList();
          const { suggestions, tipList } = this.state;
          if (suggestions.length) {
            monaco.languages.registerCompletionItemProvider('plaintext', {
              provideCompletionItems() {
               console.log('这个地方,每一次路由变动,就会多执行一次,导致我的按键提示重复展示')
                return {
                  suggestions: suggestions.map(item => ({ ...item, kind: monaco.languages.CompletionItemKind.Variable }))
                };
              },
              triggerCharacters: tipList
            });
          }
          this.timeouter = setTimeout(() => {
            editor.getAction('editor.action.formatDocument').run();
          }, 300);
        }
      };
    
    • 提供以下完整代码
    import React from 'react';
    import MonacoEditor from 'react-monaco-editor';
    import { get_rule_function } from '../../services/api.js';
    
    
    class DEditor extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          tipList: [],     // 储存计算框提示语的首字母
          suggestions: [], // 储存提示语
          calculateValue: '',
        };
      }
    
      componentWillMount() {
        // 拦截判断是否离开当前页面
        window.addEventListener('beforeunload', this.beforeunload);
      }
    
      componentDidMount() {
        this.setState({
          calculateValue: this.props.calculateValue
        })
      }
    
      componentWillReceiveProps(nextProps) {
        if (this.state.calculateValue !== nextProps.calculateValue) {
          this.setState({
            calculateValue: nextProps.calculateValue,
          })
        }
      }
    
      beforeunload() {
        // 如果是刷新页面 清空sessionStorage
        sessionStorage.removeItem('isLoadDEditor');
      }
    
      // 自定义按键提示的数据请求
      requestList = async () => {
        const list = [];
        const tipList = [':'];
        const res = await get_rule_function()
        if (res.data.responseCode) return
        const responseData = res.data.responseData;
        responseData.map(item => {
          const obj = {};
          obj.label = item.content;
          obj.insertText = item.content;
          obj.detail = item.symbolName;
          list.push(obj);
          tipList.push(item.content.substring(0, 1));
          return null;
        })
        this.setState({
          suggestions: list,
          tipList: tipList
        }) 
      }
    
      onBlur = () => {
        const { calculateValue } = this.state;
        this.props.value(calculateValue);
        if (calculateValue) {
          this.props.isEditorErrFn(false);
        }
      };
    
      onChangeHandle = (value, e) => {
        this.setState({
          calculateValue: value
        });
      }
    
      editorDidMountHandle = async (editor, monaco) => {
        // sessionStorage记录当前我是否来过这个页面 也就是说 是否加载执行过  monaco.languages.registerCompletionItemProvider 
        // 执行过就不再执行 当页面关闭就重新记录 因为多次执行了这个方法导致重复数据
        const isLoadDEditor = sessionStorage.getItem('isLoadDEditor');
        // console.log(isLoadDEditor)
        if (isLoadDEditor !== '1') {
          // console.log('如果没有加载过,就执行一次,加载过就不会再进入')
          sessionStorage.setItem('isLoadDEditor', '1');
          await this.requestList();
          const { suggestions, tipList } = this.state;
          if (suggestions.length) {
            monaco.languages.registerCompletionItemProvider('plaintext', {
              provideCompletionItems() {
                // console.log('这个地方,每一次路由变动,就会多执行一次,导致我的按键提示重复展示')
                return {
                  suggestions: suggestions.map(item => ({ ...item, kind: monaco.languages.CompletionItemKind.Variable }))
                };
              },
              triggerCharacters: tipList
            });
          }
          this.timeouter = setTimeout(() => {
            editor.getAction('editor.action.formatDocument').run();
          }, 300);
        }
      };
    
      options = {
        selectOnLineNumbers: true,
        renderSideBySide: false
      };
    
      render() {
        return (
          <div onBlur={this.onBlur}>
            <MonacoEditor
              ref="monaco"
              width="900"
              height="200"
              language="plaintext"
              theme="vs-dark"
              value={this.state.calculateValue}
              options={this.options}
              onChange={this.onChangeHandle}
              editorDidMount={this.editorDidMountHandle}
            />
          </div>
        )
      }
    }
    
    export default DEditor;
    

    以下是react-monaco-editor 代码高亮配置 webpack配置:

    • 安装monaco-editor-webpack-plugin依赖
    
    const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin');
    module.exports = {
      plugins: [
           new MonacoWebpackPlugin(['apex', 'azcli', 'bat', 'clojure', 'coffee', 'cpp', 'csharp', 'csp', 'css', 'dockerfile', 'fsharp', 'go', 'handlebars', 'html', 'ini', 'java', 'javascript', 'json', 'less', 'lua', 'markdown', 'msdax', 'mysql', 'objective', 'perl', 'pgsql', 'php', 'postiats', 'powerquery', 'powershell', 'pug', 'python', 'r', 'razor', 'redis', 'redshift', 'ruby', 'rust', 'sb', 'scheme', 'scss', 'shell', 'solidity', 'sql', 'st', 'swift', 'typescript', 'vb', 'xml', 'yaml']),
      ]
    };
    

    一个坑

    • 与antd冲突 不得进行如下配置


    • package.json里面的scripts配置不得改动:

    "scripts": {
        "start": "node scripts/start.js",
        "build": "node scripts/build.js",
        "test": "node scripts/test.js"
      },
    

    相关文章

      网友评论

          本文标题:react-monaco-editor 的使用

          本文链接:https://www.haomeiwen.com/subject/ovqykctx.html