Webコードエディタの構築
公開: 2022-03-10オンラインWebコードエディタは、コードエディタアプリケーションを使用する機会がない場合、またはコンピュータや携帯電話でWeb上で何かをすばやく試してみたい場合に最も役立ちます。 コードエディタの構築方法に関する知識があると、一部の機能を表示するためにコードエディタを統合する必要がある他のプロジェクトにアプローチする方法についてのアイデアが得られるため、これも興味深いプロジェクトです。
この記事を続けるために知っておく必要のあるReactの概念をいくつか示します。
- フック、
- コンポーネント構造、
- 機能コンポーネント、
- 小道具。
CodeMirrorの使用
CodeMirrorという名前のライブラリを使用してエディターを構築します。 CodeMirrorは、ブラウザ用にJavaScriptで実装された用途の広いテキストエディタです。 これは特にコードの編集用であり、より高度な編集機能のための多くの言語モードとアドオンが付属しています。
豊富なプログラミングAPIとCSSテーマシステムを使用して、CodeMirrorをアプリケーションに合わせてカスタマイズし、新しい機能で拡張できます。 これにより、Web上で実行され、コードの結果をリアルタイムで表示するリッチコードエディターを作成する機能が提供されます。
次のセクションでは、新しいReactプロジェクトをセットアップし、Webアプリを構築するために必要なライブラリをインストールします。
新しいReactプロジェクトの作成
新しいReactプロジェクトを作成することから始めましょう。 コマンドラインインターフェイスで、プロジェクトを作成するディレクトリに移動し、Reactアプリケーションを作成してcode_editor
という名前を付けましょう。
npx create-react-app code_editor
新しいReactアプリケーションを作成したら、コマンドラインインターフェイスでそのプロジェクトのディレクトリに移動しましょう。
cd code_editor
ここにインストールする必要があるライブラリは、 codemirror
とreact-codemirror2
2つです。
npm install codemirror react-codemirror2
このプロジェクトに必要なライブラリをインストールしたら、タブを作成し、エディターに表示される3つのタブ(HTML、CSS、およびJavaScriptの場合)間のタブ切り替えを有効にします。
ボタンコンポーネント
個々のボタンを作成する代わりに、ボタンを再利用可能なコンポーネントにしましょう。 私たちのプロジェクトでは、必要な3つのタブに応じて、ボタンには3つのインスタンスがあります。
src
フォルダーにcomponents
という名前のフォルダーを作成します。 この新しいcomponents
フォルダに、 Button.jsx
という名前のJSXファイルを作成します。
Button
コンポーネントに必要なすべてのコードは次のとおりです。
import React from 'react' const Button = ({title, onClick}) => { return ( <div> <button style={{ maxWidth: "140px", minWidth: "80px", height: "30px", marginRight: "5px" }} onClick={onClick} > {title} </button> </div> ) } export default Button
上記で行ったことの完全な説明は次のとおりです。
-
Button
という名前の機能コンポーネントを作成し、それをエクスポートしました。 - コンポーネントに入ってくる小道具から
title
とonClick
を分解しました。 ここで、title
はテキストの文字列であり、onClick
はボタンがクリックされたときに呼び出される関数です。 - 次に、
button
要素を使用してボタンを宣言し、style
属性を使用してボタンのスタイルを設定して見栄えを良くしました。 -
onClick
属性を追加し、非構造化されたonClick
関数の小道具をそれに渡しました。 - このコンポーネントで最後に気付くのは、
button
タグのコンテンツとして{title}
を渡すことです。 これにより、ボタンコンポーネントが呼び出されたときに、そのインスタンスに渡されるpropに基づいて、タイトルを動的に表示できます。
再利用可能なボタンコンポーネントを作成したので、次に進んでコンポーネントをApp.js.
に取り込みます。 App.js
に移動し、新しく作成されたボタンコンポーネントをインポートします。
import Button from './components/Button';
どのタブまたはエディターが開いているかを追跡するには、開いているエディターの値を保持するための宣言状態が必要です。 useState
Reactフックを使用して、タブのボタンがクリックされたときに現在開いているエディタータブの名前を格納する状態を設定します。
これが私たちのやり方です:
import React, { useState } from 'react'; import './App.css'; import Button from './components/Button'; function App() { const [openedEditor, setOpenedEditor] = useState('html'); return ( <div className="App"> </div> ); } export default App;
ここで、私たちは自分たちの状態を宣言しました。 現在開いているエディターの名前を取ります。 値html
が状態のデフォルト値として渡されるため、HTMLエディターはデフォルトで開いているタブになります。
次に進み、 setOpenedEditor
を使用して、タブボタンがクリックされたときの状態の値を変更する関数を記述します。
注: 2つのタブが同時に開いていない可能性があるため、関数を作成するときにそれを考慮する必要があります。
onTabClick
という名前の関数は次のようになります。
import React, { useState } from 'react'; import './App.css'; import Button from './components/Button'; function App() { ... const onTabClick = (editorName) => { setOpenedEditor(editorName); }; return ( <div className="App"> </div> ); } export default App;
ここでは、現在選択されているタブの名前である単一の関数引数を渡しました。 この引数は、関数が呼び出される場所であればどこでも提供され、そのタブの関連する名前が渡されます。
必要な3つのタブ用にButton
の3つのインスタンスを作成しましょう。
<div className="App"> <p>Welcome to the editor!</p> <div className="tab-button-container"> <Button title="HTML" onClick={() => { onTabClick('html') }} /> <Button title="CSS" onClick={() => { onTabClick('css') }} /> <Button title="JavaScript" onClick={() => { onTabClick('js') }} /> </div> </div>
これが私たちがしたことです:
- まず、
p
タグを追加しました。これは、基本的に、アプリケーションの内容にコンテキストを与えるためです。 - タブボタンをラップするために
div
タグを使用しました。div
タグには、このチュートリアルの後半でCSSファイルのグリッド表示にボタンのスタイルを設定するために使用するclassName
が含まれています。 - 次に、
Button
コンポーネントの3つのインスタンスを宣言しました。 思い出してくださいButton
コンポーネントは、title
とonClick
の2つの小道具を取ります。Button
コンポーネントのすべてのインスタンスで、これら2つの小道具が提供されます。 -
title
プロップはタブのタイトルを取ります。 -
onClick
プロパティは、作成したばかりの関数onTabClick
を取ります。この関数は、選択したタブの名前という1つの引数を取ります。
現在選択されているタブに基づいて、JavaScriptの三項演算子を使用してタブを条件付きで表示します。 これは、 openedEditor
状態の値がhtml
に設定されている場合(つまりsetOpenedEditor('html')
)、HTMLセクションのタブが現在表示されているタブになることを意味します。 以下で行うと、これをよりよく理解できます。
... return ( <div className="App"> ... <div className="editor-container"> { openedEditor === 'html' ? ( <p>The html editor is open</p> ) : openedEditor === 'css' ? ( <p>The CSS editor is open!!!!!!</p> ) : ( <p>the JavaScript editor is open</p> ) } </div> </div> ); ...
上記のコードを平易な英語で調べてみましょう。 openedEditor
の値がhtml
の場合、HTMLセクションを表示します。 それ以外の場合、 openedEditor
の値がcss
の場合は、CSSセクションを表示します。 それ以外の場合、値がhtml
でもcss
でもない場合、 openedEditor
状態の可能な値は3つしかないため、値はjs
でなければならないことを意味します。 したがって、JavaScriptのタブを表示します。
三項演算子条件のさまざまなセクションに段落タグ( p
)を使用しました。 先に進むにつれて、エディターコンポーネントを作成し、 p
タグをエディターコンポーネント自体に置き換えます。
もうここまで来ました! ボタンがクリックされると、それが表すタブをtrue
に設定するアクションが起動され、そのタブが表示されます。 現在、アプリは次のようになっています。
ボタンを保持しているdiv
コンテナに小さなCSSを追加しましょう。 上の画像のように垂直に積み重ねるのではなく、ボタンをグリッドに表示する必要があります。 App.css
ファイルに移動し、次のコードを追加します。
.tab-button-container{ display: flex; }
3つのタブボタンを保持するdiv
タグの属性としてclassName="tab-button-container"
を追加したことを思い出してください。 ここでは、CSSを使用してその表示をflex
に設定し、そのコンテナーのスタイルを設定しました。 結果は次のとおりです。
この点に到達するためにあなたがどれだけしたかを誇りに思ってください。 次のセクションでは、エディターを作成し、 p
タグをそれらに置き換えます。
エディターの作成
作業するライブラリはCodeMirrorエディタ内にすでにインストールされているので、先に進んで、 components
フォルダにEditor.jsx
ファイルを作成しましょう。
コンポーネント>Editor.jsx
新しいファイルを作成したら、その中に初期コードを記述しましょう。
import React, { useState } from 'react'; import 'codemirror/lib/codemirror.css'; import { Controlled as ControlledEditorComponent } from 'react-codemirror2'; const Editor = ({ language, value, setEditorState }) => { return ( <div className="editor-container"> </div> ) } export default Editor
これが私たちがしたことです:
- 必要になるため、
useState
フックと一緒にReactをインポートしました。 - CodeMirror CSSファイルをインポートしました(これは、インストールしたCodeMirrorライブラリからのものであるため、特別な方法でインストールする必要はありません)。
-
Controlled
をreact-codemirror2
からインポートし、わかりやすくするために名前をControlledEditorComponent
に変更しました。 これはまもなく使用します。 - 次に、
Editor
関数コンポーネントを宣言しました。ここでは、returnステートメントにclassName
が含まれ、div
が空のreturnステートメントがあります。
機能コンポーネントでは、 language
、 value
、 setEditorState
など、小道具からいくつかの値を分解しました。 これらの3つの小道具は、 App.js
で呼び出されたときに、エディターの任意のインスタンスで提供されます。
ControlledEditorComponent
を使用して、エディターのコードを記述しましょう。 これが私たちがすることです:
import React, { useState } from 'react'; import 'codemirror/lib/codemirror.css'; import 'codemirror/mode/xml/xml'; import 'codemirror/mode/javascript/javascript'; import 'codemirror/mode/css/css'; import { Controlled as ControlledEditorComponent } from 'react-codemirror2'; const Editor = ({ language, value, setEditorState }) => { return ( <div className="editor-container"> <ControlledEditorComponent onBeforeChange={handleChange} value= {value} className="code-mirror-wrapper" options={{ lineWrapping: true, lint: true, mode: language, lineNumbers: true, }} /> </div> ) } export default Editor
ここで行ったことを見ていき、CodeMirrorの用語をいくつか説明しましょう。
CodeMirrorモードは、エディターの対象言語を指定します。 このプロジェクトには3つのエディターがあるため、3つのモードをインポートしました。
- XML:このモードはHTML用です。 XMLという用語を使用します。
- JavaScript:これ(
codemirror/mode/javascript/javascript
)はJavaScriptモードをもたらします。 - CSS:これ(
codemirror/mode/css/css
)はCSSモードになります。
注:エディターは再利用可能なコンポーネントとして構築されているため、エディターに直接モードを設定することはできません。 したがって、分解したlanguage
小道具を介してモードを提供します。 ただし、これによって、動作するためにモードをインポートする必要があるという事実は変わりません。
次に、 ControlledEditorComponent
の内容について説明しましょう。
-
onBeforeChange
これは、エディターに書き込んだり、エディターから削除したりするたびに呼び出されます。 これは、変更を追跡するために入力フィールドに通常あるonChange
ハンドラーのように考えてください。 これを使用すると、新しい変更があったときにいつでもエディターの値を取得して、エディターの状態に保存することができます。 先に進むにつれて、{handleChange}
関数を記述します。 -
value = {value}
これは、いつでも編集者のコンテンツにすぎません。value
という名前の非構造化プロップをこの属性に渡しました。value
propsは、そのエディターの値を保持している状態です。 これは、エディターのインスタンスから提供されます。 -
className
="code-mirror-wrapper"
このクラス名は、私たちが自分で作成したスタイルではありません。 これは、上記でインポートしたCodeMirrorのCSSファイルから提供されます。 -
options
これは、エディターに必要なさまざまな機能を利用するオブジェクトです。 CodeMirrorには多くのすばらしいオプションがあります。 ここで使用したものを見てみましょう:-
lineWrapping: true
これは、行がいっぱいになると、コードが次の行に折り返される必要があることを意味します。 -
lint: true
これにより、リンティングが可能になります。 -
mode: language
このモードは、前述のように、エディターが使用される言語を使用します。 言語はすでに上記でインポートされていますが、エディターは、プロップを介してエディターに提供されたlanguage
値に基づいて言語を適用します。 -
lineNumbers: true
これは、エディターが各行に行番号を持つ必要があることを指定します。
-
次に、 onBeforeChange
ハンドラーのhandleChange
関数を記述できます。
const handleChange = (editor, data, value) => { setEditorState(value); }
onBeforeChange
ハンドラーを使用するとeditor, data, value
3つにアクセスできます。
値が必要なのは、 setEditorState
で渡したいvalue
だからです。 setEditorState
propは、 App.js
で宣言した各状態の設定値を表し、各エディターの値を保持します。 次に進むにつれて、これを小道具としてEditor
コンポーネントに渡す方法を見ていきます。
次に、エディターのさまざまなテーマを選択できるドロップダウンを追加します。 それでは、CodeMirrorのテーマを見てみましょう。
CodeMirrorテーマ
CodeMirrorには、選択できる複数のテーマがあります。 公式ウェブサイトにアクセスして、利用可能なさまざまなテーマのデモを確認してください。 ユーザーがエディターで選択できるさまざまなテーマでドロップダウンを作成しましょう。 このチュートリアルでは、5つのテーマを追加しますが、いくつでも追加できます。
まず、 Editor.js
コンポーネントにテーマをインポートしましょう。
import 'codemirror/theme/dracula.css'; import 'codemirror/theme/material.css'; import 'codemirror/theme/mdn-like.css'; import 'codemirror/theme/the-matrix.css'; import 'codemirror/theme/night.css';
次に、インポートしたすべてのテーマの配列を作成します。
const themeArray = ['dracula', 'material', 'mdn-like', 'the-matrix', 'night']
選択したテーマの値を保持するuseState
フックを宣言し、デフォルトのテーマをdracula
として設定しましょう。
const [theme, setTheme] = useState("dracula")
ドロップダウンを作成しましょう:
... return ( <div className="editor-container"> <div style={{marginBottom: "10px"}}> <label for="cars">Choose a theme: </label> <select name="theme" onChange={(el) => { setTheme(el.target.value) }}> { themeArray.map( theme => ( <option value={theme}>{theme}</option> )) } </select> </div> // the rest of the code comes below... </div> ) ...
上記のコードでは、 label
HTMLタグを使用してドロップダウンにラベルを追加し、次にselect
タグを追加してドロップダウンを作成しました。 select
要素のoption
タグは、ドロップダウンで使用可能なオプションを定義します。
作成したthemeArray
のテーマ名をドロップダウンに入力する必要があるため、 .map
arrayメソッドを使用してthemeArray
をマップし、 option
タグを使用して名前を個別に表示しました。
ちょっと待ってください—上記のコードの説明はまだ終わっていません。 開始select
タグで、 onChange
属性を渡して、ドロップダウンで新しい値が選択されるたびにtheme
の状態を追跡および更新します。 ドロップダウンで新しいオプションが選択されるたびに、返されるオブジェクトから値が取得されます。 次に、状態フックのsetTheme
を使用して、新しい値を状態が保持する値に設定します。
この時点で、ドロップダウンを作成し、テーマの状態を設定し、新しい値で状態を設定する関数を記述しました。 CodeMirrorにテーマを使用させるために必要な最後のことは、 ControlledEditorComponent
のoptions
オブジェクトにテーマを渡すことです。 options
オブジェクトで、 theme
という名前の値を追加し、その値を、 theme
という名前の選択したテーマの状態の値に設定しましょう。
ControlledEditorComponent
は次のようになります。
<ControlledEditorComponent onBeforeChange={handleChange} value= {value} className="code-mirror-wrapper" options={{ lineWrapping: true, lint: true, mode: language, lineNumbers: true, theme: theme, }} />
これで、エディターで選択できるさまざまなテーマのドロップダウンが作成されました。
現在、 Editor.js
の完全なコードは次のようになっています。
import React, { useState } from 'react'; import 'codemirror/lib/codemirror.css'; import 'codemirror/theme/dracula.css'; import 'codemirror/theme/material.css'; import 'codemirror/theme/mdn-like.css'; import 'codemirror/theme/the-matrix.css'; import 'codemirror/theme/night.css'; import 'codemirror/mode/xml/xml'; import 'codemirror/mode/javascript/javascript'; import 'codemirror/mode/css/css'; import { Controlled as ControlledEditorComponent } from 'react-codemirror2'; const Editor = ({ language, value, setEditorState }) => { const [theme, setTheme] = useState("dracula") const handleChange = (editor, data, value) => { setEditorState(value); } const themeArray = ['dracula', 'material', 'mdn-like', 'the-matrix', 'night'] return ( <div className="editor-container"> <div style={{marginBottom: "10px"}}> <label for="themes">Choose a theme: </label> <select name="theme" onChange={(el) => { setTheme(el.target.value) }}> { themeArray.map( theme => ( <option value={theme}>{theme}</option> )) } </select> </div> <ControlledEditorComponent onBeforeChange={handleChange} value= {value} className="code-mirror-wrapper" options={{ lineWrapping: true, lint: true, mode: language, lineNumbers: true, theme: theme, }} /> </div> ) } export default Editor
スタイルを設定する必要があるclassName
は1つだけです。 App.css
に移動し、次のスタイルを追加します。
.editor-container{ padding-top: 0.4%; }
編集者の準備ができたので、 App.js
に戻ってそこで使用しましょう。
src> App.js
最初に行う必要があるのは、ここにEditor.js
コンポーネントをインポートすることです。
import Editor from './components/Editor';
App.js
で、HTML、CSS、JavaScriptエディターのコンテンツをそれぞれ保持する状態を宣言しましょう。
const [html, setHtml] = useState(''); const [css, setCss] = useState(''); const [js, setJs] = useState('');
思い出してください。編集者のコンテンツを保持および提供するには、これらの状態を使用する必要があります。
次に、条件付きレンダリングでHTML、CSS、およびJavaScriptに使用した段落( p
)タグを、作成したばかりのエディターコンポーネントに置き換えます。また、エディターの各インスタンスに適切なプロパティを渡します。成分:
function App() { ... return ( <div className="App"> <p>Welcome to the edior</p> // This is where the tab buttons container is... <div className="editor-container"> { htmlEditorIsOpen ? ( <Editor language="xml" value={html} setEditorState={setHtml} /> ) : cssEditorIsOpen ? ( <Editor language="css" value={css} setEditorState={setCss} /> ) : ( <Editor language="javascript" value={js} setEditorState={setJs} /> ) } </div> </div> ); } export default App;
これまでフォローしてきた場合は、上記のコードブロックで行ったことを理解できます。
ここでは平易な英語ですp
タグ(プレースホルダーとして存在していた)をエディターコンポーネントのインスタンスに置き換えました。 次に、対応する状態に一致するように、それぞれlanguage
、 value
、およびsetEditorState
プロップを提供しました。
ここまで来ました! これが私たちのアプリが今どのように見えるかです:
Iframeの紹介
インラインフレーム(iframe)を使用して、エディターに入力されたコードの結果を表示します。
MDNによると:
HTMLインラインフレーム要素(
<iframe>
)は、ネストされたブラウジングコンテキストを表し、現在のページに別のHTMLページを埋め込みます。
IframeがReactでどのように機能するか
Iframeは通常、プレーンHTMLで使用されます。 ReactでIframeを使用する場合、多くの変更は必要ありません。主な変更は、属性名をキャメルケースに変換することです。 この例は、 srcdoc
がsrcDoc
になることです。
Web上のIframeの未来
Iframeは、引き続きWeb開発で非常に役立ちます。 あなたがチェックしたいと思うかもしれない何かはポータルです。 ダニエルブレインが説明するように:
「ポータルは、このミックスに強力な新しい機能セットを導入します。 これで、iframeのような感覚で、シームレスにアニメーション化およびモーフィングして、ブラウザウィンドウ全体を引き継ぐことができるものを構築することが可能になりました。」
ポータルが解決しようとしていることの1つは、URLバーの問題です。 iframeを使用する場合、iframeでレンダリングされたコンポーネントは、アドレスバーに一意のURLを持ちません。 そのため、ユースケースによっては、これはユーザーエクスペリエンスに適さない場合があります。 ポータルはチェックする価値があります。そうすることをお勧めしますが、これは私たちの記事の焦点ではないため、ここで説明するのはこれだけです。
結果を格納するためのIframeの作成
編集者の結果を格納するiframeを作成して、チュートリアルを進めましょう。
return ( <div className="App"> // ... <div> <iframe srcDoc={srcDoc} title="output" sandbox="allow-scripts" frameBorder="1" width="100%" height="100%" /> </div> </div> );
ここでは、iframeを作成し、 div
コンテナタグに格納しました。 iframeで、必要ないくつかの属性を渡しました。
-
srcDoc
srcDoc
属性はキャメルケースで記述されています。これはReactでiframe属性を記述する方法であるためです。 iframeを使用する場合、ページに外部Webページを埋め込むか、指定したHTMLコンテンツをレンダリングできます。 外部ページを読み込んで埋め込むには、代わりにsrc
プロパティを使用します。 この場合、外部ページをロードしていません。 むしろ、結果を格納する新しい内部HTMLドキュメントを作成したいと思います。 このためには、srcDoc
属性が必要です。 この属性は、埋め込みたいHTMLドキュメントを取得します(まだ作成していませんが、間もなく作成します)。 -
title
title属性は、インラインフレームのコンテンツを説明するために使用されます。 -
sandbox
このプロパティには多くの目的があります。 この例では、allow-scripts
値を使用してiframeでスクリプトを実行できるようにするために使用しています。 JavaScriptエディターを使用しているため、これはすぐに役立ちます。 -
frameBorder
これは、iframeの境界線の太さを定義するだけです。 -
width
とheight
これは、iframeの幅と高さを定義します。
これらの用語は、あなたにとってより意味のあるものになるはずです。 次に進んで、 srcDoc
のHTMLテンプレートドキュメントを保持する状態を宣言しましょう。 上記のコードブロックをよく見ると、 srcDoc
属性に値を渡したことがわかります: srcDoc
={srcDoc}
。 useState()
Reactフックを使用してsrcDoc
状態を宣言しましょう。 これを行うには、 App.js
ファイルで、他の状態を定義した場所に移動し、次の状態を追加します。
const [srcDoc, setSrcDoc] = useState(` `);
状態を作成したので、次に行うことは、コードエディタに入力するたびに結果を状態で表示することです。 しかし、私たちが望んでいないのは、キーを押すたびにコンポーネントを再レンダリングすることです。 それを念頭に置いて、先に進みましょう。
結果を表示するためのIframeの設定
HTML、CSS、JavaScriptのいずれかのエディターにそれぞれ変更があるたびに、 useEffect()
がトリガーされ、更新された結果がiframeにレンダリングされます。 App.js
ファイルでこれを行うためにuseEffect()
を書いてみましょう:
まず、 useEffect()
フックをインポートします。
import React, { useState, useEffect } from 'react';
useEffect()
を次のように記述しましょう。
useEffect(() => { const timeOut = setTimeout(() => { setSrcDoc( ` <html> <body>${html}</body> <style>${css}</style> <script>${js}</script> </html> ` ) }, 250); return () => clearTimeout(timeOut) }, [html, css, js])
ここでは、HTML、CSS、およびJavaScriptエディターに対して宣言した値が変更または更新されたときに常に実行されるuseEffect()
フックを作成しました。
なぜsetTimeout()
を使用する必要があったのですか? それなしでこれを書いた場合、エディターでキーを1回押すたびに、iframeが更新されますが、これは一般的なパフォーマンスには適していません。 そのため、 setTimeout()
を使用して更新を250ミリ秒遅らせ、ユーザーがまだ入力しているかどうかを知るのに十分な時間を与えます。 つまり、ユーザーがキーを押すたびにカウントが再開されるため、iframeは、ユーザーが250ミリ秒アイドル状態(入力していない)の場合にのみ更新されます。 これは、キーが押されるたびにiframeを更新する必要がないようにするための優れた方法です。
上記で次に行ったことは、 srcDoc
を新しい変更で更新することでした。 上で説明したように、 srcDoc
コンポーネントは、指定されたHTMLコンテンツをiframeにレンダリングします。 このコードでは、ユーザーがHTMLエディターに入力したコードを含むhtml
状態を取得し、テンプレートのbody
タグの間に配置して、HTMLテンプレートを渡しました。 また、ユーザーがCSSエディターで入力したスタイルを含むcss
状態を取得し、それをstyle
タグ間で渡しました。 最後に、ユーザーがJavaScriptエディターに入力したJavaScriptコードを含むjs
状態を取得し、 script
タグ間で渡しました。
setSrcDoc
の設定では、通常の引用符( ' '
)の代わりにバッククォート( ` `
)を使用していることに注意してください。 これは、上記のコードで行ったように、バックティックによって対応する状態値を渡すことができるためです。
useEffect()
フックのreturn
ステートメントは、メモリリークを回避するために、完了時にsetTimeout()
をクリアするクリーンアップ関数です。 ドキュメントには、 useEffect
に関する詳細があります。
現在のプロジェクトは次のようになります。
CodeMirrorアドオン
CodeMirrorアドオンを使用すると、他のコードエディターにあるような機能でエディターを拡張できます。 開始タグが入力されたときに自動的に閉じタグが追加される例と、開始ブラケットが入力されたときに自動的に閉じられるブラケットの別の例を見ていきましょう。
最初に行うことは、このアドオンをApp.js
ファイルにインポートすることです。
import 'codemirror/addon/edit/closetag'; import 'codemirror/addon/edit/closebrackets';
ControlledEditorComponent
オプションでそれを渡しましょう:
<ControlledEditorComponent ... options={{ ... autoCloseTags: true, autoCloseBrackets: true, }} />
これが私たちが持っているものです:
これらのアドオンを大量にエディターに追加して、より豊富な機能を提供することができます。 ここでは、それらすべてを確認することはできませんでした。
これで完了です。アプリのアクセシビリティとパフォーマンスを向上させるためにできることについて簡単に説明しましょう。
ソリューションのパフォーマンスとアクセシビリティ
私たちのWebコードエディタを見ると、いくつかの点が間違いなく改善される可能性があります。
私たちは主に機能性に注意を払っていたので、デザインを少し無視したかもしれません。 アクセシビリティを向上させるために、このソリューションを改善するためにできることがいくつかあります。
- 現在開いているエディターのボタンに
active
クラスを設定できます。 ボタンを強調表示すると、ユーザーが現在作業しているエディターを明確に示すことができるため、アクセシビリティが向上します。 - エディターがここにあるものよりも多くの画面スペースを占めるようにしたい場合があります。 もう1つ試すことができるのは、横のどこかにドッキングされているボタンをクリックするだけでiframeをポップアップさせることです。 そうすることで、エディターにより多くの画面スペースが与えられます。
- この種のエディターは、モバイルデバイスで簡単なエクササイズを実行したい人に役立つため、モバイルに完全に適合させる必要があります(上記のモバイルに関する両方のポイントは言うまでもありません)。
- 現在、ロードした複数のテーマの中からエディターコンポーネントのテーマを切り替えることができますが、ページの一般的なテーマは同じです。 ユーザーがレイアウト全体でダークテーマとライトテーマを切り替えることができるようにすることができます。 これはアクセシビリティに優れており、明るい画面を長時間見ていることによる人々の目の負担を軽減します。
- 主に、外部ドキュメントではなく内部HTMLドキュメントをiframeに読み込んでいたため、iframeのセキュリティ問題については検討しませんでした。 したがって、iframeはユースケースに適しているため、これを慎重に検討する必要はありません。
- iframeの場合、別の考慮事項はページの読み込み時間です。これは、iframeに読み込まれるコンテンツは、通常、制御できないためです。 私たちのアプリでは、iframeコンテンツが外部にないため、これは問題ではありません。
パフォーマンスとアクセシビリティは、アプリケーションを構築するときに、ユーザーにとってアプリケーションがどれだけ有用で使いやすいかを決定するため、多くの検討に値します。
Shedrackは、Reactアプリのパフォーマンスを改善および最適化する方法をうまく説明してきました。 チェックする価値があります!
結論
さまざまなプロジェクトに取り組むことで、さまざまなテーマについて学ぶことができます。 この記事を読み終えたので、コードエディターをより充実させ、UIを刷新し、上記で概説したアクセシビリティとパフォーマンスの問題を修正するために、より多くのアドオンを試して、経験を自由に拡張してください。
- このプロジェクトのコードベース全体は、GitHubで入手できます。
Codesandboxのデモは次のとおりです。
リンクと資料
- 「GoogleChromeのポータル:Iframeと同じですが、より良く、より悪く」、Daniel Brain
- 「パフォーマンスの最適化」、Reactドキュメント
- 「ユーザーマニュアルおよびリファレンスガイド」、CodeMirrorドキュメント