React+TypeScript項(xiàng)目中如何使用CodeMirror?
原文合集地址如下,有需要的朋友可以關(guān)注
本文地址
合集地址
@
前言
之前做需求用到過(guò)codeMirror這個(gè)工具,覺(jué)得還不錯(cuò),功能很強(qiáng)大,所以記錄一下改工具的基礎(chǔ)用法,分享給大家。 CodeMirror被廣泛應(yīng)用于許多Web應(yīng)用程序和開(kāi)發(fā)工具,例如代碼編輯器、集成開(kāi)發(fā)環(huán)境(IDE)、在線教育平臺(tái)等。它提供了一個(gè)可嵌入的、靈活的解決方案,讓開(kāi)發(fā)者可以輕松地在網(wǎng)頁(yè)中實(shí)現(xiàn)功能強(qiáng)大的代碼編輯器。
使用codeMirror
步驟1:安裝依賴 首先,你需要在React項(xiàng)目中安裝CodeMirror及其相關(guān)依賴??梢允褂靡韵旅钸M(jìn)行安裝:
npm?install?codemirror?react-codemirror2?@types/codemirror
步驟2:導(dǎo)入所需模塊、創(chuàng)建CodeMirror組件
import?React,?{?useRef,?useEffect?}?from?'react';
import?CodeMirror,?{?EditorFromTextArea?}?from?'codemirror';
import?'codemirror/lib/codemirror.css';
//?導(dǎo)入需要的語(yǔ)言模式和樣式主題
import?'codemirror/mode/javascript/javascript';
import?'codemirror/mode/xml/xml';
import?'codemirror/mode/css/css';
import?'codemirror/mode/htmlmixed/htmlmixed';
import?'codemirror/theme/material.css';??//?加載的樣式主題?https://codemirror.net/5/theme/
//?定義組件屬性類(lèi)型
interface?CodeMirrorEditorProps?{
??value:?string;
??language:?string;
??theme?:?string;
??height?:Number;
??width?:Number;
??onChange:?(value:?string)?=>?void;
??onShiftEnter?:?()?=>?void;
??onBlur?:?(value:?string)?=>?void;
??onChangeLine?:?()?=>?void;
}
const?CodeMirrorEditor:?React.FC<CodeMirrorEditorProps>?=?(props)?=>?{
??const?{?language?}?=?props;
??const?textareaRef?=?useRef<HTMLTextAreaElement>(null);
??const?editorRef?=?useRef<EditorFromTextArea>();
??useEffect(()?=>?{
????const?textarea?=?textareaRef.current;
????if?(!textarea)?return;
????initCodeMirror();
???
????return?()?=>?{
??????//?清理和銷(xiāo)毀編輯器實(shí)例
??????editorRef.current?.toTextArea();
????};
??},?[]);
??const?initCodeMirror?=?()=>{
????const?editorConfig?=?{
??????tabSize:?2,?//?制表符的寬度。默認(rèn)為?4。
??????fontSize:?'16px',?//?字體大小
??????autoCloseBrackets:?true,?//?在鍵入時(shí)自動(dòng)關(guān)閉括號(hào)和引號(hào)
??????showCursorWhenSelecting:?true,?//?當(dāng)選擇處于活動(dòng)狀態(tài)時(shí)是否應(yīng)繪制光標(biāo)。默認(rèn)為?false。這里設(shè)置成自動(dòng)補(bǔ)全
??????lineWrapping:?true,?//?,CodeMirror?是否應(yīng)該滾動(dòng)或換行。默認(rèn)為false(滾動(dòng))。這里設(shè)置成換行
??????lineNumbers:?true,?//?是否在編輯器左側(cè)顯示行號(hào)
??????fullScreen:?true,?//當(dāng)設(shè)置為?時(shí)true,將使編輯器全屏顯示(如占據(jù)整個(gè)瀏覽器窗口)。
??????mode:language,?//?使用模式
??????theme:?'material'?//?編輯器樣式的主題?必須確保.cm-s-[name]?加載定義相應(yīng)樣式的?CSS?文件。默認(rèn)值為"default",顏色包含在?中codemirror.css??梢砸淮问褂枚鄠€(gè)主題類(lèi),例如將和類(lèi)"foo?bar"都分配給編輯器。cm-s-foocm-s-bar
????};
????editorRef.current?=?CodeMirror.fromTextArea(textareaRef.current!,?editorConfig);
????//?監(jiān)聽(tīng)編輯器內(nèi)容變化事件
????editorRef.current.on('change',?codemirrorValueChange);
????editorRef.current.on('keydown',?keydown);
????editorRef.current.on('blur',?blur);
?????const?{?value,?width,?height?}?=?props;
?????editorRef.current.setValue(value?||?'');
?????if?(width?||?height)?{
??????editorRef.current.setSize(width,?height);
?????}
??}
??/**?失焦?*/
??const??blur?=?(instance:any)?=>?{
????if?(props.onBlur)?{
??????props.onBlur(instance.doc.getValue());
????}
??};
??/**?鍵盤(pán)按鍵按下?*/
??const?keydown?=?(_:any,?change:any)?=>?{
????if?(change.shiftKey?===?true?&&?change.keyCode?===?13)?{
??????if?(props.onShiftEnter)?{
????????props.onShiftEnter();
??????}
??????change.preventDefault();
????}
??};
??/**?編輯內(nèi)容變化?*/
??const?codemirrorValueChange?=?(doc:any,?change:any)?=>?{
??
????doc.eachLine((line:any)?=>?{
??????if(line.text.startsWith('//')?||?line.text.startsWith('#'))?{
????????doc.addLineClass(line,?'wrap',?'notes');
??????}?else?if?(line.wrapClass?===?'notes')?{
????????doc.removeLineClass(line,?'wrap',?'notes');
??????}
????});
????if?(change.origin?!==?'setValue')?{
??????if?(props.onChange)?{
????????props.onChange(doc.getValue());
??????}
????}
??};
??
??return?(
????<textarea?ref={textareaRef}?/>
??);
};
export?default?CodeMirrorEditor;
步驟:使用CodeMirror組件
在你的應(yīng)用程序中,使用MyComponent
組件來(lái)渲染CodeMirror。
import?React,?{?useState?}?from?'react';
import?CodeMirrorEditor?from?'CodeMirror';
const?CodeEditor:?React.FC?=?()?=>?{
??const?[code,?setCode]?=?useState<string>('');
??const?handleCodeChange?=?(value:?string)?=>?{
????setCode(value);
??};
??return?(
????<div>
??????<CodeMirrorEditor
????????value={code}
????????language="javascript"
????????onChange={handleCodeChange}
??????/>
??????<pre>{code}</pre>
????</div>
??);
};
export?default?CodeEditor;
步驟4:添加樣式 在添加了CodeMirror所需的樣式。
.CodeMirror?{
??height:?300px;
}
注冊(cè)Js代碼提示
因?yàn)樯厦嫱暾幕A(chǔ)代碼已有,下面的代碼我只寫(xiě)一些需要額外加進(jìn)去的部分。 關(guān)鍵字可以自己添加,這里只是給個(gè)例子看看。當(dāng)然也可以添加其他語(yǔ)言的提示,registerHelper函數(shù)的第二個(gè)參數(shù)就是所配置的語(yǔ)言,和editorConfig 里面的mode保持一致。
//?注冊(cè)JavaScript代碼提示
const?registerHelp?=?()?=>{
?CodeMirror.registerHelper('hint',?'javascript',?(editor,?options)?=>?{
???const?cursor?=?editor.getCursor();
???const?token?=?editor.getTokenAt(cursor);
???const?word?=?token.string;
?
???//?假設(shè)你的關(guān)鍵字列表存儲(chǔ)在keywords數(shù)組中
???const?keywords?=?['if',?'else',?'for',?'while',?'function',?'class'];
?
???const?list?=?keywords.filter((keyword)?=>?keyword.startsWith(word));
?
???return?{
?????list,
?????from:?CodeMirror.Pos(cursor.line,?token.start),
?????to:?CodeMirror.Pos(cursor.line,?token.end),
???};
?});
}
1、需要將上面的代碼放在初始化codeMirror之上
useEffect(()?=>?{
????const?textarea?=?textareaRef.current;
????if?(!textarea)?return;
????registerHelp();?//?注冊(cè)代碼提示
????initCodeMirror();
???
????return?()?=>?{
??????//?清理和銷(xiāo)毀編輯器實(shí)例
??????editorRef.current?.toTextArea();
????};
??},?[]);
2、在codemirrorValueChange函數(shù)里加入下面代碼
?/**?編輯內(nèi)容變化?*/
??const?codemirrorValueChange?=?(doc:any,?change:any)?=>?{
??
????doc.eachLine((line:any)?=>?{
??????if(line.text.startsWith('//')?||?line.text.startsWith('#'))?{
????????doc.addLineClass(line,?'wrap',?'notes');
??????}?else?if?(line.wrapClass?===?'notes')?{
????????doc.removeLineClass(line,?'wrap',?'notes');
??????}
????});
?//?判斷是輸入擇匹配出提示代碼
?if?(change.origin?===?'+input')?{
??????CodeMirror.commands.autocomplete(editor.current,?undefined,?{
????????completeSingle:?false,
??????});
????}
????if?(change.origin?!==?'setValue')?{
??????if?(props.onChange)?{
????????props.onChange(doc.getValue());
??????}
????}
??};
使用了 CodeMirror
庫(kù)的autocomplete
命令來(lái)觸發(fā)自動(dòng)完成功能。
CodeMirror.commands.autocomplete
接受三個(gè)參數(shù):
editor.current
:一個(gè)CodeMirror編輯器實(shí)例,它是你創(chuàng)建的編輯器對(duì)象的引用。第二個(gè)參數(shù)是可選的,用于指定觸發(fā)自動(dòng)完成的原因。可以傳入一個(gè)字符串作為原因,例如
"explicit"
表示顯式觸發(fā),或者傳入undefined
表示由編輯器自動(dòng)觸發(fā)。第三個(gè)參數(shù)是可選的配置對(duì)象,用于自動(dòng)完成的選項(xiàng)。在這里,
{ completeSingle: false }
設(shè)置了completeSingle
選項(xiàng)為false
,表示自動(dòng)完成功能不會(huì)在只有一個(gè)建議項(xiàng)時(shí)立即完成,而是等待更多的輸入或手動(dòng)觸發(fā)。
更多配置請(qǐng)自行去官網(wǎng)文檔查看https://codemirror.net/5/doc/manual.html#config