react 中 使用 Monaco Editor 编辑器

目录

Monaco Editor

react 中使用

安装

使用方法

Webpack 配置

属性

获取 monac

开发示例---自定义提示

自定义主题

 


Monaco Editor

 

微软之前有个项目叫做Monaco Workbench,后来这个项目变成了VSCode。

 

Monaco Editor下文简称monaco)就是从这个项目中成长出来的一个web编辑器,他们很大一部分的代码(monaco-editor-core)都是共用的,所以monaco和VSCode在编辑代码,交互以及UI上几乎是一摸一样的,有点不同的是,两者的平台不一样,monaco基于浏览器,而VSCode基于electron,所以功能上VSCode更加健全,并且性能比较强大。

 

注: electron --- 使用 JavaScript,HTML 和 CSS 构建跨平台的桌面应用程序


react 中使用react-monaco-editor

 

安装

yarn add react-monaco-editor

使用方法

import React from 'react';
import { render } from 'react-dom';
import MonacoEditor from 'react-monaco-editor';

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      code: '// type your code...',
    }
  }
  editorDidMount(editor, monaco) {
    console.log('editorDidMount', editor);
    editor.focus();
  }
  onChange(newValue, e) {
    console.log('onChange', newValue, e);
  }
  render() {
    const code = this.state.code;
    const options = {
      selectOnLineNumbers: true
    };
    return (
      <MonacoEditor
        width="800"
        height="600"
        language="javascript"
        theme="vs-dark"
        value={code}
        options={options}
        onChange={::this.onChange}
        editorDidMount={::this.editorDidMount}
      />
    );
  }
}

render(
  <App />,
  document.getElementById('root')
);

Webpack 配置

在Umijs 2.xx中使用, 项目配置config.js中 ---    plugins 中的 dll , 会导致 补全 提示 颜色...失效,所以用umijs3 ,或者不配置dll

yarn add monaco-editor-webpack-plugin -D 
  • 安装webpack 插件,添加 monaco-editor-webpack-plugin 到 webpack.config.js 中
const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin');
module.exports = {
  plugins: [
    new MonacoWebpackPlugin({
      // available options are documented at https://github.com/Microsoft/monaco-editor-webpack-plugin#options
      languages: ['json']
    })
  ]
};

插件与编辑器版本的对应关系

monaco-editor-webpack-pluginmonaco-editor
3.*.*0.22.*0.23.*
2.*.*0.21.*
1.9.*0.20.*
1.8.*0.19.*
1.7.*0.18.*

 

 

备注:Monaco Editor在内部使用CSS导入,如果您在项目中使用CSS模块化,您可能会遇到冲突。为了避免这种情况-为应用程序和monaco-editor软件包再分离出一个css的配置为其提供css-loader:

// Specify separate paths
const path = require('path');
const APP_DIR = path.resolve(__dirname, './src');
const MONACO_DIR = path.resolve(__dirname, './node_modules/monaco-editor');

{
  test: /\.css$/,
  include: APP_DIR,
  use: [{
    loader: 'style-loader',
  }, {
    loader: 'css-loader',
    options: {
      modules: true,
      namedExport: true,
    },
  }],
}, 
{
  test: /\.css$/,
  include: MONACO_DIR,
  use: ['style-loader', 'css-loader'],
}

属性

下列属性都是可配置的

  • width --- 默认100%
  • height --- 默认100%
  • value --- 编辑器中要展示的代码
  • defaultValue --- 编辑器中初始化展示的代码
  • language --- 编辑器支持的语言格式
  • theme --- 主题
  • options --- 请参阅 Monaco 官方API 接口文档
  • overrideServices --- 请参阅 Monaco 官方编辑器设置APi
  • onChange(newValue, event) --- 当编辑器内容发生变更触发事件
  • editorWillMount(monaco) --- 编辑器挂载之前发生的事件(类似于 componetWillMount React)
  • editorDIdMount(monaco) --- 编辑器挂载时发生从事件(类似于 componetDidMount React)

 

获取 monac

可以通过导入的方式获取 monaco

import { monaco } from 'react-monaco-editor';

开发示例---自定义提示

import React, { useState } from 'react';
import MonacoEditor from 'react-monaco-editor';
import tipData from './echarts_word.js';

const initStr = ['function x() {', '\tconsole.log("Hello world!");', '}'].join('\n');

export default function SetMonaco(props) {
    const [code, setCode] = useState(initStr);
    const { suggestions } = props;

    //编辑器默认配置项
    const _initOptions = {
        selectOnLineNumbers: true,
        renderSideBySide: false,
        // scrollBeyondLastLine: false,
        // formatOnPaste: true,
        // contextmenu: false, // 禁止右键
        // fixedOverflowWidgets: true, // 超出编辑器大小的使用fixed属性显示
        // quickSuggestions: false, // 默认的提示关掉
        // minimap: {
        //     // 缩略图
        //     enabled: false,
        // },
        // scrollbar: {
        //     // 滚动条
        //     horizontalScrollbarSize: 6,
        //     verticalScrollbarSize: 6,
        // },
        // lineNumbersMinChars: 3, // 最少显示3位长的行号
        // lineNumbers: 'on', // 是否显示行号
        // wordWrap: 'on', // 是否可以换行
    };

    //提示文字默认配置
    const _initSuggestions = formatTipData(tipData);

    function _initChange(newValue, e) {
        // console.log(newValue);
        setCode(newValue);
        props.getCode && props.getCode(newValue);
    }

    //输入之后的回调
    const _editorDidMountHandle = (editor, monaco) => {
        let sug = _initSuggestions;
        if (suggestions instanceof Array && suggestions.length) {
            //检测提示信息的格式
            let flag = true;
            suggestions.forEach((item, index) => {
                if (!item.label) {
                    console.error(`自定义提示数组-序列${index}缺少label字段`);
                    flag = false;
                }
                if (!item.insertText) {
                    console.error(`自定义提示数组-序列${index}项缺少insertText字段`);
                    flag = false;
                }
            });

            //如果没有问题合并
            if (flag) {
                sug = _initSuggestions.concat(suggestions);
            }
        }

        monaco.languages.registerCompletionItemProvider('javascript', {
            provideCompletionItems() {
                return {
                    suggestions: sug.map((item) => {
                        return {
                            label: item.label,
                            kind: item.kind ? item.kind : monaco.languages.CompletionItemKind.Text,
                            insertText: item.label, // 实际粘贴上的值
                            detail: item.detail,
                        };
                    }),
                };
            },
            triggerCharacters: [':'], // 触发提示的字符,可以写多个
        });
        editor.focus();
    };

    return (
        <MonacoEditor
            width="100%"
            height="100%"
            language="javascript"
            defaultValue={code}
            theme="vs-dark"
            options={_initOptions}
            onChange={_initChange}
            editorDidMount={_editorDidMountHandle}
            {...props}
        />
    );
}

//转换自定义提示
function formatTipData(ary) {
    if (ary instanceof Array && ary.length) {
        return ary.map((item) => ({
            label: item,
            insertText: item,
            detail: '',
        }));
    }
}

 

自定义主题

import React, { useState } from 'react';
import MonacoEditor, {monaco}from 'react-monaco-editor';

const initStr = ['function x() {', '\tconsole.log("Hello world!");', '}'].join('\n');
export default function SetMonaco(props) {
    const [code, setCode] = useState(initStr);

    //自定义配置主题
    monaco.editor.defineTheme('myTheme', {
        base: 'vs',
        inherit: true,
        rules: [{ background: 'EDF9FA' }],
        colors: {
            'editor.foreground': '#000000',
            'editor.background': '#EDF9FA',
            'editorCursor.foreground': '#8B0000',
            'editor.lineHighlightBackground': '#0000FF20',
            'editorLineNumber.foreground': '#008800',
            'editor.selectionBackground': '#88000030',
            'editor.inactiveSelectionBackground': '#88000015'
        }
    });
    monaco.editor.setTheme('myTheme');


    //编辑器默认配置项
    const _initOptions = {
        selectOnLineNumbers: true,
        renderSideBySide: false
    };



    return (
        <MonacoEditor
            width="100%"
            height="100%"
            language="javascript"
            defaultValue={code}
            theme="myTheme"
            options={_initOptions}
         
           
        />
    );
}

 

 

  • 3
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值