코드 편집기와 같이 Contentestable (및 Magic)과 같이 요소를 완전히 렌더링 가능하고 편집 가능한 컨텐츠 표면으로 바꾸는 작은 반응 후크.
useEditable 여전히 완전히 렌더링 가능한 요소를 contenteditable 수있는 작은 후크입니다. 이것은 단지 2kB 로 소형 코드 편집기 또는 산문 텍스트 레이아를 만드는 데 이상적입니다!
그것은 내부 반응 요소를 렌더링 할 수있는 동안 모든 요소를 편집 할 수있게하는 것을 목표로합니다. 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 >
) ;
} ; 그리고 우리가 useEditable editorRef 에 연결할 수있는 것처럼, 렌더링되는 <pre> 요소를 가리키고 일부 코드가 포함 된 상태를 구동하는 setCode 를 가리 킵니다.
이 라이브러리는 테스트되었으며 다음을 사용하여 올바르게 작동해야합니다 .
MutationObserver 방법이 contenteditable 통해 제거 된 텍스트 노드를 읽을 수 없기 때문에 IE 11 에는 알려진 문제가 있습니다.
전통적으로 반응에서 편집 표면을 선택할 때 세 가지 옵션이있었습니다. 하나는 ProSemirror / Codemirror와 같은 대규모 프로젝트를 진행할 수 있으며, 편집 및 렌더링 이벤트의 많은 부분을 제어 할 수 있으며, 따라서 의견을 제어 할 수 있거나 오히려 contenteditable 적용되거나 요소의 내용으로 대체되는 textarea div 로 렌더링 할 수 있습니다.
세 가지 옵션 모두 실제로 렌더링되거나 편집 가능한 컨텐츠를 렌더링하고 관리하는 것이 얼마나 쉬운 지에 대해 실제로 렌더링되거나 불합리한 제한 사항에 대해 많은 사용자 정의를 허용하지 않습니다.
그렇다면 contenteditable 요소에 대한 렌더링이 그렇게 어렵게 만드는 이유는 무엇입니까?
일반적으로 이것은 DOM을 직접 편집하기 때문에 힘든 일입니다. 이로 인해 REACT 및 PREACT와 같은 대부분의 렌더링 라이브러리가 혼란스러워집니다. 기본 가상 DOM은 더 이상 실제 DOM 구조와 일치하지 않기 때문입니다. 이 문제 contenteditable 방지하기 위해 use-editable MutationObserver 를 만듭니다. 반응을 위해 이러한 변경 사항을보고하기 전에 먼저 DOM에 대한 모든 변경 사항을 롤백하여 React가 기대하는 것을 확인합니다.
또한 CARET의 현재 위치를 유지하고 선택을 보존하고 React가 DOM 자체를 업데이트하면 복원합니다. 이것은 contenteditable 편집자에게는 다소 일반적인 기술이지만, MutationObserver 서버 추가는 use-editable 가능한 다른 뷰 라이브러리가 요소의 내용을 업데이트 할 수 있도록 할 수있게합니다.
현재 렌더링 된 요소의 텍스트 컨텐츠는 결국 코드 입력과 정확히 일치해야하거나 구현이 렌더링 된 텍스트 컨텐츠를 상태로 사용하는 내용으로 다시 변환 할 수 있어야합니다. 이것은 실제 DOM 컨텐츠 만 캡처하기 때문에 contenteditable 의 작동 방식을 제한합니다. use-editable 렌더 사이클을 관리하는 전체 구성 요소가되는 것을 목표로하지 않기 때문에 추가 상태를 유지할 필요는 없지만 DOM의 텍스트를 onChange 콜백으로 다시 전달합니다.
onChange 콜백을 사용하면 커서 위치, 현재 줄 번호 및 라인의 내용을 설명하는 Position 객체를 수신하여 자동 검색에 유용한 커서에 유용한 후 커서 위치를 업데이트하기 위해 useEditable update 기능으로 적용 할 수 있습니다.
첫 번째 인수 는 elementRef 이며 유형 RefObject<HTMLElement> 의 Ref 객체를 수락합니다. 이는 편집 가능한 요소를 가리 킵니다. 이 심판은 후크의 런타임 중에 null 되거나 변경 될 수 있습니다. Ref의 변화가 React에 의해 트리거되는 한, 모든 것이 예상대로 작동해야합니다.
두 번째 인수 는 onChange 이며 유형의 콜백 (text: string, pos: Position) => void 가 내용이 contenteditable 될 때마다 호출됩니다. 요소 내용의 레더를 트리거 할 수 있도록 설정해야합니다.
onChange 수신하는 text 는 요소 내용의 텍스트 표현 일뿐 아니라 수신하는 Position 에는 커서의 현재 위치, 줄 번호 (제로 인덱스) 및 현재 라인의 내용이 자동 이행에 유용한 커서까지의 내용을 포함합니다.
세 번째 인수 는 선택적 options 객체입니다. 이는 현재 후크의 편집 동작을 변경하는 두 가지 옵션을 수용합니다.
disabled 옵션은 contentEditable 속성을 다시 제거하여 편집 가능한 편집을 비활성화합니다.indentation 옵션은 계약을위한 다수의 표시된 공간 일 수 있습니다. 이를 통해 개선 된 Tab 키 동작이 가능하며, 이는 시프트가 유지 될 때 현재 선을 들여 보내거나 현재 라인을 둘러싸고 있습니다 (편집기가 포커스 트랩으로 작용할 것임을 알고 있어야합니다!). options.indentation 설정되면 useEditable 탭 문자의 삽입을 방지하고 대신 지정된 양의 공백을 삽입하여 열을 훨씬 쉽게 처리 할 수 있습니다.
또한 useEditable 후크는 아래에 문서화 된 것처럼 여러 가지 방법으로 Edit 핸들을 반환합니다.
Edit.update(content: string): void
간병 위치를 조정하면서 편집 가능한 전체 내용을 대체합니다. 이것은 현재 내용과 전달 된 컨텐츠의 길이 차이로 간병을 이동시킵니다.
Edit.insert(append: string, offset?: number): void
오프셋 범위에서 텍스트를 삭제하는 동안 캐럿 위치에 새 텍스트를 삽입합니다 (음수 오프셋을 허용). 예를 들어, offset -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 편집기 중 하나를 가졌습니다. (그러나 RAW HTML 업데이트 포함)react-simple-code-editor Split Textarea를 사용하고 표면 구현을 렌더링 한 최초의 (?) 라이브러리로, 멋진 편집 API가 어떻게 보일지 보여주었습니다.codejar 에는 일부 Firefox 해결 방법이 부족하지만 선택을 관리하는 가장 좋은 트릭이 포함되어 있습니다. 또한 RAW HTML 강조 / 업데이트를 사용합니다.codemirror.next 텍스트 입력 및 DOM 업데이트 트릭을 처리 할 때 다양한 기술을 볼 수있는 귀중한 소스입니다. 안정 : 강력한 것은이 프로젝트의 새로운 기능을 개발할 계획이 아닙니다. 우리는 여전히 버그 보고서 및 보안 문제에 응답하고 있습니다. 우리는 여전히이 프로젝트에 대한 PRS를 환영하고 있지만 새로운 기능을 포함하는 PR은 작고 통합이 쉽고 변경 사항을 포함하지 않아야합니다.