コードエディターのような完全にレンダリング可能で編集可能なコンテンツサーフェスに変換するための小さな反応フック。
useEditable 、完全にレンダリング可能である間に要素がcontenteditableようにする小さなフックです。これは、わずか2kBで小規模なコードエディターや散文Textareasを作成するのに最適です。
それは、通常の反応要素をレンダリングすることができながら、任意の要素を編集可能にすることを目的としています。これは、 innerHTMLやraw HTMLへの操作またはレンダリングに対処する必要がありません。
prism-react-rendererを使用して、CodeSandboxの完全なデモをご覧ください!
最初にreactと一緒にuse-editableインストール:
yarn add use-editable
# or
npm install --save use-editableその後、 useEditable HTMLElement refとonChangeハンドラーを渡すことができるようになります。
import React , { useState , useRef } from 'react' ;
import { useEditable } from 'use-editable' ;
const RainbowCode = ( ) => {
const [ code , setCode ] = useState ( 'function test() {}nconsole.log("hello");' ) ;
const editorRef = useRef ( null ) ;
useEditable ( editorRef , setCode ) ;
return (
< div className = "App" >
< pre
style = { { whiteSpace : 'pre-wrap' , fontFamily : 'monospace' } }
ref = { editorRef }
>
{ code . split ( / r?n / ) . map ( ( content , i , arr ) => (
< React . Fragment key = { i } >
< span style = { { color : `hsl( ${ ( ( i % 20 ) * 17 ) | 0 } , 80%, 50%)` } } >
{ content }
</ span >
{ i < arr . length - 1 ? 'n' : null }
</ React . Fragment >
) ) }
</ pre >
</ div >
) ;
} ;そして、そのように、私たちはeditorRefにuseEditable editorRefに接続しました。これは、レンダリングされている<pre>要素と、コードを含む状態を駆動するsetCodeを指します。
このライブラリは、以下を使用して適切に動作する必要があります。
IE 11では、 MutationObserverメソッドがcontenteditable型を介して削除されたテキストノードを読み取ることができないため、既知の問題があります。
伝統的に、Reactの編集面を選択する際には3つのオプションがありました。 Prosemirror / Codemirrorなどの大規模なプロジェクトに行くことができますdivこれは、編集およびレンダリングの多くのイベントtextarea制御するため、むしろcontenteditableを述べることができます。
3つのオプションはすべて、実際にレンダリングされるものという点で多くのカスタマイズを許可していません。また、編集可能なコンテンツをレンダリングおよび管理することがどれほど簡単かについて不合理な制限を設けません。
それでは、 contenteditable要素へのレンダリングをとても難しいのはなぜですか?
通常、これはDOMを直接編集するため、難しいです。これにより、根底にある仮想Domsが実際のDOM構造と一致しなくなっているため、反応やプアクトなどのほとんどのレンダリングライブラリが混乱します。この問題を防ぐためにuse-editableは、 contenteditable要素に加えられたすべての変更を監視するMutationObserverを作成します。これらの変更を報告する前に、反応するためにそれは最初にすべての変更をDOMにロールバックするため、Reactが期待するものを確認します。
さらに、それはまた、CARETの現在の位置、選択、およびそれを復元すると、ReactがDOM自体を更新した後に復元します。これは、 contenteditable編集者にとってはかなり一般的な手法ですが、 MutationObserver追加はuse-editableものが別のビューライブラリが要素のコンテンツを更新できるようにすることを可能にします。
現在、レンダリングされた要素のテキストコンテンツは、最終的にコード入力と正確に一致する必要があるか、実装がレンダリングされたテキストコンテンツを状態として使用しているものに変換できる必要があります。これは、実際のDOMコンテンツのみをキャプチャするため、 contenteditableがどのように機能するかの制限です。 use-editable 、レンダリングサイクルを管理する完全なコンポーネントになることを目指していないため、追加の状態を維持する必要はありませんが、DOMのテキストをonChangeコールバックに渡すだけです。
onChangeコールバックを使用すると、カーソル位置、現在のライン番号、およびラインの内容を記述するPositionオブジェクトも受け取ります。これは、カーソルの位置を更新useEditableために使用できるupdate関数で適用できる自動接続に役立つカーソルに役立ちます。
最初の引数はelementRefであり、編集可能になる要素を指す型RefObject<HTMLElement>のrefオブジェクトを受け入れます。このrefは、フックの実行時にnullまたは変更を許可されます。 Refの変更がReactによってトリガーされる限り、すべてが予想どおりに動作するはずです。
2番目の引数はonChangeあり、タイプのコールバック(text: string, pos: Position) => voidを受け入れますcontenteditableこれは、要素のコンテンツのrerenderをトリガーするようにセットアップする必要があります。
onChange受信するtextは、要素の内容のテキスト表現にすぎませんが、受信するPositionには、カーソルの現在の位置、ライン番号(ゼロインデックス)、および現在のラインの内容が、自動ゲストに役立つカーソルまで上にあります。
3番目の引数は、オプションのoptionsオブジェクトです。これは現在、フックの編集動作を変更する2つのオプションを受け入れます。
disabledオプションは、編集contentEditable属性を再度削除することにより、編集可能な編集を無効にします。indentationオプションは、インデントのための多くの表示されたスペースである場合があります。これにより、改良されたTabのキーの動作が可能になります。これにより、シフトが保持されるときに現在のラインまたは現在のラインが焦点を当てます(これにより、編集者がフォーカストラップとして機能することに注意してください!) options.indentationが設定されている場合、 useEditable場合は、タブ文字の挿入を防ぎ、代わりに指定された量のホワイトスペースを挿入します。これにより、列の処理がはるかに簡単になります。
さらに、 useEditableフックは、以下に文書化するように、いくつかの方法を備えたEditハンドルを返します。
Edit.update(content: string): void
カレットの位置を調整しながら、編集可能なコンテンツ全体を交換します。これにより、カレットは現在のコンテンツと渡されたコンテンツの長さの違いによってシフトします。
Edit.insert(append: string, offset?: number): void
オフセットの範囲でテキストを削除しながら、新しいテキストを世話の位置に挿入します(ネガティブオフセットを受け入れます)。たとえば、 offsetが-1に設定されている場合、新しいテキストを挿入する前に、1つの文字がカレットの左側に削除されます。 2に設定されている場合、1つの右側に2つのキャラクターが削除されます。 appendテキストは、テキストを挿入せずに削除のみを適用するために、空の文字列に設定することもできます。テキストが選択されると、単に最初に消去され、 offsetが無視されます。
Edit.move(pos: number | { row: number; column: number }): void
これにより、カレットが指定された位置に移動します。位置は、文字インデックス( number )であるか、 rowとcolumn個別に指定する座標です。
Edit.getState(): { text: string; position: Position }
この方法により、編集可能な現在の状態を取得できます。これは、 onChange通常受信するものと同じです。これは、キーダウンハンドラーにカスタム編集アクションを追加する場合、または編集可能なものが選択されている間にプログラム的にonChangeを模倣する場合に役立ちます。
react-liveは、初期の小さなcontenteditable編集者の1つでした。 (しかし、生のHTMLの更新を使用して)react-simple-code-editorスプリットテキストアレアとレンダリングサーフェスの実装を使用した最初の(?)ライブラリであり、編集APIがどのように見えるかを示しました。codejarは、選択を管理するための最良のトリックが含まれていますが、Firefoxの回避策はいくつかありません。また、RAW HTMLのハイライト /更新も使用します。codemirror.next 、テキスト入力とDOMの更新トリックを処理する際にさまざまな手法を見るための非常に貴重なソースです。 Stable: Fromidableは、このプロジェクトの新機能を開発する予定ではありません。私たちはまだバグレポートとセキュリティの懸念に対応しています。私たちはまだこのプロジェクトのPRSを歓迎していますが、新機能を含むPRSは小さく、統合しやすく、変更を壊すべきではありません。