Draft.js가 간단한 테이블을 지원하도록 해보세요.

13944 단어 react

소개



내 요구 사항은 온라인 종이 조판 편집기를 구현하고 LaTeX에서 생성된 PDF를 내보내는 것입니다.

-- 업데이트됨 --
https://github.com/facebook/draft-js/pull/2590
-- 원본 --

프로젝트 링크: Eorg

관련 프로젝트는 Overleaf 및 Resumake입니다.

저는 React.js를 선호하기 때문에 역시 Facebook용으로 개발된 서식 있는 텍스트 편집기인 Draft.js를 선택했습니다. 종이 쓰기는 테이블 삽입에서 숨길 수 없지만 Draft.js에는 기성 테이블 플러그인이 없습니다. 테이블 생성을 위한 몇 가지 도구도 있습니다. 별도의 테이블 지원을 직접 작성할 필요는 전혀 없지만 사용자에게는 편리하고 테이블이 너무 복잡할 필요는 없습니다. booktabs 와 같은 테이블을 내보낼 수 있으니 직접 테이블 지원을 구현해보려고 합니다.

콘텐츠



아이디어:

A robust tablenew ContentBlock를 사용하여 block에 메타데이터를 쓰는 것입니다. 이는 Draft.js에 가까운 접근 방식입니다!


상대적으로 말하자면, 제 구현은 offical TeX example에서 차용한 더 트릭입니다. ,AtomicBlockUtils.insertAtomicBlock(newEditorState, entityKey, ' ') API를 사용하여 React.js 소품에 메타데이터를 추가합니다.
  • 행과 열

  • const contentStateWithEntity = contentState.createEntity(
        'TABLE',
        'IMMUTABLE',
        {
            row, column, caption,  // data
        },
    )
    
    // ...
    
    const { row, column, caption } = props // Table Component
    

  • 테이블 셀

  • // createTable.js
    
    /**
     * cell = {
     *     0: ["cell-0,0", "cell-0,1", ..., "cell-0,m"],
     *     1: ["cell-1,0", "cell-1,1", ..., "cell-1,m"],
     *     ...,
     *     n: ["cell-n,0", "cell-n,1", ..., "cell-n,m"],
     * }
     */
    const cell = Object.fromEntries(Array.from(
        { length: row },
        (_, i) => [
            i,
            Array.from({ length: column }, (_, j) => `cell-${i},${j}`)
        ])
    )
    
    const contentStateWithEntity = contentState.createEntity(
        'TABLE',
        'IMMUTABLE',
        {
            ..., cell, // data
        },
    )
    
    // ...
    
    const { ..., cell } = props // Table Component
    

    그리고 테이블 초기화:

    // TableBlock.js
    
    // tbody -- version 1
    const coordinate = []
    
    if (row > 1) {
        for (let i = 1; i < row; i += 1) {
        const cols = []
        for (let j = 0; j < column; j += 1) {
            cols.push(
            <td key={i + j} >
                {cell[i][j]}
            </td>,
            )
        }
        rows.push(<tr key={i}>{cols}</tr>)
        }
    }
    




    store row, column, caption, cell to React.js props


  • 셀 좌표 얻기:

  • 첫 번째 아이디어는 Dom 노드 위치를 계산하는 것입니다. 즉, <tr>에서 closest('td')의 인덱스closest('table')를 찾습니다.

    나중에 더 나은 접근 방식은 key<tr> 에서 <td> 값을 검색하는 것이며 좌표는 (x1, y1)입니다.

    // TableBlock.js
    
    // tbody -- version 2
    const coordinate = []
    
    if (row > 1) { // thead need to calculate separately
        for (let i = 1; i < row; i += 1) {
        const cols = []
        for (let j = 0; j < column; j += 1) {
            cols.push(
            <td
                key={i + j} // TODO key-1
                onDoubleClick={() => coordinate.push([i, j])}
            >
                {cell[i][j]}
            </td>,
            )
        }
        rows.push(<tr key={i}>{cols}</tr>)
        }
    }
    


    위의 키-1은 안정적이지 않습니다. nanoid 라이브러리로 작업할 수 있습니다.

    key = {`i+j+${nanoid()}`}
    


    이제 안정적이며 셀 값을 저장할 수 있습니다.

    // find the coordinate of the node clicked
    const x1 = coordinate[coordinate.length - 1][0]
    const y1 = coordinate[coordinate.length - 1][1]
    
    // update cell[i][j]
    cell[x1][y1] = evt.target.innerHTML
    




    cell-2,1 can be stored to props



    요약



    테이블은 아직 완료되지 않았습니다. 예를 들면 다음과 같습니다.
  • 커서 처리 방법
  • 변경 가능

  • 다음



    셀 추가 및 삭제를 지원합니다.

    좋은 웹페이지 즐겨찾기