프론트엔드 데브코스 5기 TIL 16 - 노션클로닝(1)

김영현·2023년 10월 17일
0

TIL

목록 보기
18/129

노션 클로닝

노션을 클론하는 프로젝트다.
기본적인 레이아웃은 노션과 같아야 한다.
상태를 어떻게 관리해줄지 생각해보면 되겠구먼?

일단 생각해보자

  1. 추가할땐 모달로 글을 작성한다.
    모달과 통신할땐 CustomEvent를 사용해보자
  2. 원래 있는 글을 수정하면 문서번호는 그대로, 업데이트만
  3. 문서의 리스트, 리스트의 정보를 왼-오 화면이 둘다 사용함. 따라서 App.js에서 상태관리 필요
  4. 모달에서 작성할때나 우측페이지의 원래있는글을 수정할때 둘 다Editor를 쓸것이다. 재사용성 용이하게.

여기서 더 생각해볼건, 저번처럼 클래스로 작성할것인지 아니면 함수로 작성할 것인지다.
쉽게쉽게 갈 수 있는건 클래스. 그런데, 강사님께서 js클래스는 문제점이 있다고 하셨다.
=> 본래 프로토타입 기반 언어라 클래스는 흉내밖에 안되서 그런가...자세히 알아봐야겠음.

결국 함수+프로토타입으로 결정.

일단 프로토타입 없이 제작하고, 공통기능을 뽑아서 추상화 해보자.
밑바닥부터 설계하는 실력은 아직 안된다...!

문제1. contentEditable 커서 위치

setState로 텍스트값을 넣어주면, render()가 실행되서 contentEditable의 내부 커서 위치를 잃고 blur된다.
어떻게 해결할까?
내가 생각한 방법은 이전의 커서 위치를 sessionStroage에 저장하는 방법이었다.
=> localStorage는 브라우저가 종료되도 남아있다. 굳이 커서위치를 종료시 남길 필요는 없음.

The given range isn't in document.

생각한대로 하던 도중 문제와 맞닥뜨렸다.
document.createRange()range객체를 받아와서 커서 위치를 수정해야하는데
render()함수가 한번 호출되고나서 커서 위치를 바꾸려니, 안된다.

=> selectionrange객체는 결국 선택한 영역에 초점이 맞춰져있다. 렌더로 이미 커서가 날아가니...

Failed to execute 'collapse' on 'Selection': There is no child at offset

collpase(node, offset)nodeoffset만큼 커서를 이동한채 포커스하는 메소드다.

contentEditable은 내부 value를 가진게 아니라, 하위노드(텍스트, 이후 div)를 생성하는 기능이다.
따라서 node자리에 자체 노드 말고, 하위 노드를 넣어주어야 정상 작동한다.
하지만 첫 텍스트 이후 엔터를 누르면 이후 div>br태그로 개행처리를 하니...통일성이 없다.

통일해주어야 잘 작동할것 같다.

key-up이벤트

lastchildbr인지 div인지 판단하여 개행처리를 통일하려했다.
keydown, keypress이벤트는 노드가 추가되기전에 이벤트가 발생하여 text노드까지 잡아버렸다.
그래서 keyup이벤트를 감지하려했는데, 아예 감지가 안됐다.
공식문서를 보니 keyup이벤트는 포커스동안만 감지가 된다.
=> render()때문에 포커스가 풀린다...흠.

문제1을 해결하기위해 공부한 것들

  • caret: 텍스트 안의 커서캐럿이라함.
  • window.selection: Ctrl+F같이 하이라이트되는 기능들을 selection이벤트라고 함.


    이러저러한 속성들이 있다.
    ahcor, base는 시작노드, extent,focus는 끝 노드를 가리킨다.
    isCollapse는 끝과 시작이 같냐는 의미!

아래 링크들을 더 공부해봐야겠다.
https://velog.io/@dishate/Selection-Object-window.getSelection-%EC%A0%95%EB%A6%AC
https://developer.mozilla.org/en-US/docs/Web/API/Selection/collapse
https://ko.javascript.info/selection-range
https://happy-playboy.tistory.com/entry/ContentEditable%EC%97%90%EC%84%9C-%EC%BB%A4%EC%84%9CCaret-%ED%99%9C%EC%9A%A9%ED%95%98%EA%B8%B01-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8
https://velog.io/@longroadhome/%EB%AA%A8%EB%8D%98JS-%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80-Range%EC%99%80-Selection

...시간이 너무 소요되니 일단 textarea쓰기로 함.


구조

대략적으로 화면을 두 개로 나누었다.
우측DocumentPage와 좌측NavPage.
그리고 NavPage내부에 DocumentList를 렌더링한다.
이때 DocumentList가 자식을 갖고있으면, 재귀적으로 렌더링하면 좋을 것 같다.
또한 DocumentList의 문서 제목과 DocumentPage의 문서 제목을 같은 컴포넌트로 묶는 것도 좋아보인다.

내일 인나서 생각해봐야지...

profile
모르는 것을 모른다고 하기

0개의 댓글