@摩纳哥编辑/react·
摩纳哥的编辑器·使用任何React应用程序中的摩纳哥编辑器,而无需使用webpack(或lollup/parcel/etc)配置文件/插件
- ✅反应V19支持!
- ⌨️用打字稿重写
- ⚡已经支持多模型编辑器;享受?
- ?版本V4在这里 - 要查看新版本中的新事物以及如何从v3迁移,请阅读此文档(另外,如果您需要旧版本readme,它在这里)
- ?已创建了新部分开发 /游乐场 - 现在您可以运行操场并与图书馆的内部玩耍
- ?它已经与 @Monaco-editor/Loader集成了
概要
摩纳哥编辑器包装器,用于与任何React应用程序的轻松 /单行集成,而无需使用WebPack(或任何其他模块Bundler)配置文件 /插件。它可以与由Create-React-App,Create-SnowPack-App,vite,next.js或任何其他应用程序生成器生成的应用程序一起使用 -您无需弹出或重新打印它们。
动机
摩纳哥编辑是一个著名的基于Web技术的代码编辑器,可为代码提供动力。该库处理摩纳哥编辑器的设置过程,并提供干净的API与任何React环境中的摩纳哥互动
演示
一探究竟!
文档
- 安装
- 介绍
- 用法
- 简单用法
- 获得价值
- 编辑实例
- 摩纳哥实例
- usemonaco
- 加载程序/配置
- 多模型编辑器
- validate
- 笔记
- 创建自己的编辑器!
- 开发 /游乐场
- 道具
安装
npm install @monaco-editor/react # or @monaco-editor/react@next for React v19
或者
yarn add @monaco-editor/react
或者您可以使用CDN。这是一个例子
注意:对于打字稿类型的定义,此软件包将摩纳哥编辑软件包用作同行依赖性。因此,如果您需要类型并且还没有安装摩纳哥编辑包,则需要这样做
问AI
摩纳哥反应AI将帮助您更好地理解该存储库。您可以要求提供代码示例,安装指南,调试帮助等等。
介绍
除了类型外,库还导出编辑和差异器组件,以及加载程序实用程序和usemonaco钩子:
import Editor , { DiffEditor , useMonaco , loader } from '@monaco-editor/react' ;用法
简单用法
这是摩纳哥编辑与React项目简单集成的示例。
您只需要导入和渲染编辑器组件:
;
}
const rootElement = document.getElementById('root');
ReactDOM.render(
, rootElement);">
import React from 'react' ;
import ReactDOM from 'react-dom' ;
import Editor from '@monaco-editor/react' ;
function App ( ) {
return < Editor height = "90vh" defaultLanguage = "javascript" defaultValue = "// some comment" /> ;
}
const rootElement = document . getElementById ( 'root' ) ;
ReactDOM . render ( < App /> , rootElement ) ; codesandbox
扩展示例
);
}
const rootElement = document.getElementById('root');
ReactDOM.render(, rootElement);"> import React from 'react' ;
import ReactDOM from 'react-dom' ;
import Editor from '@monaco-editor/react' ;
function App ( ) {
function handleEditorChange ( value , event ) {
// here is the current value
}
function handleEditorDidMount ( editor , monaco ) {
console . log ( 'onMount: the editor instance:' , editor ) ;
console . log ( 'onMount: the monaco instance:' , monaco ) ;
}
function handleEditorWillMount ( monaco ) {
console . log ( 'beforeMount: the monaco instance:' , monaco ) ;
}
function handleEditorValidation ( markers ) {
// model markers
// markers.forEach(marker => console.log('onValidate:', marker.message));
}
return (
< Editor
height = "90vh"
defaultLanguage = "javascript"
defaultValue = "// some comment"
onChange = { handleEditorChange }
onMount = { handleEditorDidMount }
beforeMount = { handleEditorWillMount }
onValidate = { handleEditorValidation }
/>
) ;
}
const rootElement = document . getElementById ( 'root' ) ;
ReactDOM . render ( < App /> , rootElement ) ; codesandbox
获得价值
有两个选择可以获取当前值:
- 从编辑器实例获取当前的模型值
>
);
}
const rootElement = document.getElementById('root');
ReactDOM.render(
, rootElement);">
import React , { useRef } from 'react' ;
import ReactDOM from 'react-dom' ;
import Editor from '@monaco-editor/react' ;
function App ( ) {
const editorRef = useRef ( null ) ;
function handleEditorDidMount ( editor , monaco ) {
editorRef . current = editor ;
}
function showValue ( ) {
alert ( editorRef . current . getValue ( ) ) ;
}
return (
< >
< button onClick = { showValue } > Show value button >
< Editor
height = "90vh"
defaultLanguage = "javascript"
defaultValue = "// some comment"
onMount = { handleEditorDidMount }
/>
>
) ;
}
const rootElement = document . getElementById ( 'root' ) ;
ReactDOM . render ( < App /> , rootElement ) ; codesandbox
- 通过Onchange Prop获取当前的模型值
);
}
const rootElement = document.getElementById('root');
ReactDOM.render(, rootElement);"> import React from 'react' ;
import ReactDOM from 'react-dom' ;
import Editor from '@monaco-editor/react' ;
function App ( ) {
function handleEditorChange ( value , event ) {
console . log ( 'here is the current model value:' , value ) ;
}
return (
< Editor
height = "90vh"
defaultLanguage = "javascript"
defaultValue = "// some comment"
onChange = { handleEditorChange }
/>
) ;
}
const rootElement = document . getElementById ( 'root' ) ;
ReactDOM . render ( < App /> , rootElement ) ; codesandbox
(通过`编辑器实例获取“ diffeditor”值)
>
);
}
const rootElement = document.getElementById('root');
ReactDOM.render(, rootElement);"> import React , { useRef } from 'react' ;
import ReactDOM from 'react-dom' ;
import { DiffEditor } from '@monaco-editor/react' ;
function App ( ) {
const diffEditorRef = useRef ( null ) ;
function handleEditorDidMount ( editor , monaco ) {
diffEditorRef . current = editor ;
}
function showOriginalValue ( ) {
alert ( diffEditorRef . current . getOriginalEditor ( ) . getValue ( ) ) ;
}
function showModifiedValue ( ) {
alert ( diffEditorRef . current . getModifiedEditor ( ) . getValue ( ) ) ;
}
return (
< >
< button onClick = { showOriginalValue } > show original value button >
< button onClick = { showModifiedValue } > show modified value button >
< DiffEditor
height = "90vh"
language = "javascript"
original = "// the original code"
modified = "// the modified code"
onMount = { handleEditorDidMount }
/>
>
) ;
}
const rootElement = document . getElementById ( 'root' ) ;
ReactDOM . render ( < App /> , rootElement ) ; codesandbox
编辑实例
编辑实例是从onmount道具作为第一个参数暴露的,第二个是摩纳哥实例
);
}
const rootElement = document.getElementById('root');
ReactDOM.render(, rootElement);"> import React , { useRef } from 'react' ;
import ReactDOM from 'react-dom' ;
import Editor from '@monaco-editor/react' ;
function App ( ) {
const editorRef = useRef ( null ) ;
function handleEditorDidMount ( editor , monaco ) {
// here is the editor instance
// you can store it in `useRef` for further usage
editorRef . current = editor ;
}
return (
< Editor
height = "90vh"
defaultLanguage = "javascript"
defaultValue = "// some comment"
onMount = { handleEditorDidMount }
/>
) ;
}
const rootElement = document . getElementById ( 'root' ) ;
ReactDOM . render ( < App /> , rootElement ) ; codesandbox
摩纳哥实例
有三个选项可以获取摩纳哥实例:
- 通过onmount/beforemount
);
}
const rootElement = document.getElementById('root');
ReactDOM.render(, rootElement);"> import React , { useRef } from 'react' ;
import ReactDOM from 'react-dom' ;
import Editor from '@monaco-editor/react' ;
function App ( ) {
const monacoRef = useRef ( null ) ;
function handleEditorWillMount ( monaco ) {
// here is the monaco instance
// do something before editor is mounted
monaco . languages . typescript . javascriptDefaults . setEagerModelSync ( true ) ;
}
function handleEditorDidMount ( editor , monaco ) {
// here is another way to get monaco instance
// you can also store it in `useRef` for further usage
monacoRef . current = monaco ;
}
return (
< Editor
height = "90vh"
defaultLanguage = "javascript"
defaultValue = "// some comment"
beforeMount = { handleEditorWillMount }
onMount = { handleEditorDidMount }
/>
) ;
}
const rootElement = document . getElementById ( 'root' ) ;
ReactDOM . render ( < App /> , rootElement ) ; codesandbox
- 通过装载机实用程序
import { loader } from '@monaco-editor/react' ;
loader . init ( ) . then ( ( monaco ) => console . log ( 'here is the monaco instance:' , monaco ) ) ; codesandbox
- 通过Usemonaco Hook
;
}
const rootElement = document.getElementById('root');
ReactDOM.render(, rootElement);"> import React from 'react' ;
import ReactDOM from 'react-dom' ;
import Editor , { useMonaco } from '@monaco-editor/react' ;
function App ( ) {
const monaco = useMonaco ( ) ;
useEffect ( ( ) => {
if ( monaco ) {
console . log ( 'here is the monaco instance:' , monaco ) ;
}
} , [ monaco ] ) ;
return < Editor height = "90vh" defaultValue = "// some comment" defaultLanguage = "javascript" /> ;
}
const rootElement = document . getElementById ( 'root' ) ;
ReactDOM . render ( < App /> , rootElement ) ; codesandbox
usemonaco
usemonaco是一个返回摩纳哥实例的钩子。但是,应该考虑一个重要的说明:载荷实用程序( @Monaco-editor/loader的引用)正在处理初始化过程:该过程是异步完成的,并且仅一次。因此,如果初始化的第一个启动器是usemonaco钩子,则由于其异步安装,第一个返回的值将为null。只需检查返回的usemonaco的值
;
}
const rootElement = document.getElementById('root');
ReactDOM.render(, rootElement);"> import React , { useEffect } from 'react' ;
import ReactDOM from 'react-dom' ;
import Editor , { useMonaco } from '@monaco-editor/react' ;
function App ( ) {
const monaco = useMonaco ( ) ;
useEffect ( ( ) => {
// do conditional chaining
monaco ?. languages . typescript . javascriptDefaults . setEagerModelSync ( true ) ;
// or make sure that it exists by other ways
if ( monaco ) {
console . log ( 'here is the monaco instance:' , monaco ) ;
}
} , [ monaco ] ) ;
return < Editor height = "90vh" defaultValue = "// some comment" defaultLanguage = "javascript" /> ;
}
const rootElement = document . getElementById ( 'root' ) ;
ReactDOM . render ( < App /> , rootElement ) ; codesandbox
装载机config
库导出(命名)称为加载程序的实用程序。基本上,它是 @Monaco-editor/Loader的参考。默认情况下,正在从CDN下载摩纳哥文件。有能力改变这种行为,以及涉及摩纳哥AMD加载器的其他事情。我们有一个默认配置文件,您可以通过下面显示的方式进行修改:
import { loader } from '@monaco-editor/react' ;
// you can change the source of the monaco files
loader . config ( { paths : { vs : '...' } } ) ;
// you can configure the locales
loader . config ( { 'vs/nls' : { availableLanguages : { '*' : 'de' } } } ) ;
// or
loader . config ( {
paths : {
vs : '...' ,
} ,
'vs/nls' : {
availableLanguages : {
'*' : 'de' ,
} ,
} ,
} ) ; 将摩纳哥编辑用作NPM软件包
从版本v4.4.0开始,可以将摩纳哥编辑用作NPM软件包;从node_modules导入它,并将摩纳哥源包含在您的捆绑包中(而不是使用CDN)。为了使它起作用,您可以执行以下操作:
import * as monaco from 'monaco-editor' ;
import { loader } from '@monaco-editor/react' ;
loader . config ( { monaco } ) ;
// ...注意:您应该注意,这可能需要其他WebPack插件,例如摩纳哥编辑 - webpack-plugin,也可能不可能在CRA生成的应用程序中使用而不弹出它们。
如果使用Vite,则需要这样做:
import { loader } from '@monaco-editor/react' ;
import * as monaco from 'monaco-editor' ;
import editorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker' ;
import jsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker' ;
import cssWorker from 'monaco-editor/esm/vs/language/css/css.worker?worker' ;
import htmlWorker from 'monaco-editor/esm/vs/language/html/html.worker?worker' ;
import tsWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker?worker' ;
self . MonacoEnvironment = {
getWorker ( _ , label ) {
if ( label === 'json' ) {
return new jsonWorker ( ) ;
}
if ( label === 'css' || label === 'scss' || label === 'less' ) {
return new cssWorker ( ) ;
}
if ( label === 'html' || label === 'handlebars' || label === 'razor' ) {
return new htmlWorker ( ) ;
}
if ( label === 'typescript' || label === 'javascript' ) {
return new tsWorker ( ) ;
}
return new editorWorker ( ) ;
} ,
} ;
loader . config ( { monaco } ) ;
loader . init ( ) . then ( /* ... */ ) ; codesandbox
注意:您所传递的对象将与默认的对象深入合并
多模型编辑器
当您渲染编辑器组件时,正在创建一个默认模型。需要提到的是,当您更改语言或价值道具时,它们会影响在组件座上自动创建的相同模型。在大多数情况下,这是可以的,但是开发人员想实现多模型编辑器以支持标签/文件(例如IDES)时会面临问题。并且以前要处理多个模型,他们必须手动进行操作。现在,支持多模型API?让我们检查一下它的工作原理。有三个参数可以创建一个模型 - 价值,语言和路径(摩纳哥。您可以将最后一个(路径)视为模型的标识符。现在,编辑器组件具有路径道具。当您指定路径道具时,编辑器组件会检查其是否具有该路径的模型。如果是,将显示现有模型,否则,将创建(并存储)新模型。使用此技术,您可以与路径相通用文件,并创建一个完全多模型的编辑器。您可以打开文件,进行一些更改,选择另一个文件,当您返回第一个文件时,将使用整个视图状态,文本选择,撤消堆栈,滚动位置等显示上一个模型(简单演示)
这是一个简单的例子:让我们想象我们有一个像某种文件结构的JSON一样,类似的是:
const files = {
'script.js' : {
name : 'script.js' ,
language : 'javascript' ,
value : someJSCodeExample ,
} ,
'style.css' : {
name : 'style.css' ,
language : 'css' ,
value : someCSSCodeExample ,
} ,
'index.html' : {
name : 'index.html' ,
language : 'html' ,
value : someHTMLCodeExample ,
} ,
} ;这是我们简单的多模型编辑器实现:
>
);
}
const rootElement = document.getElementById('root');
ReactDOM.render(, rootElement);"> import React from 'react' ;
import ReactDOM from 'react-dom'
下载源码
通过命令行克隆项目:
git clone https://github.com/suren-atoyan/monaco-react.git