일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |
- 리액트
- alias설정
- createPortal
- BFC
- useQueryClient
- 제어컴포넌트
- CustomHook
- ?? #null병합연산자
- BlockFormattingContext
- 문제해결
- 화살표2개
- 함수형프로그래밍
- vite
- tailwindCSS
- QueryClient
- debouncing
- 부모패딩
- transition
- ignore padding
- 조건부스타일
- DOM
- 부모요소의 패딩 무시
- es6
- 서초구보건소 #무료CPR교육
- Carousel
- react
- accordian
- twoarrow
- parent padding
- 이즐 #ezl #욕나오는 #교통카드
- Today
- Total
프론트엔드 첫걸음
김민태 프론트엔드 강의 - javascript로 React 만들기 본문
React 없이, JSX를 직접 쓰고, 가상 DOM을 만들고,
그걸 진짜 DOM으로 만들어서 화면에 그리는 기능을 직접 구현한다.
구성 요소 역할
createElement | JSX를 가상 DOM 객체로 변환함 |
createDOM | 가상 DOM 객체를 실제 DOM 요소로 변환 |
render | 만들어진 DOM을 브라우저에 붙임 |
//JSX를 가상 DOM 객체로 변환함
export function createVNode(tag, props, ...children) {
return { tag, props, children };
}
//가상 DOM 객체를 실제 DOM 요소로 변환
export function createDOM(node) {
if (typeof node === 'string') {
return document.createTextNode(node);
}
const element = document.createElement(node.tag);
Object.entries(node.props)
.forEach(([name, value]) => element.setAttribute(name, value));
node.children
.map(createDOM)
.forEach(element.appendChild.bind(element));
return element;
}
// 만들어진 DOM을 브라우저에 붙임
export function render(vdom, container) {
container.appendChild(createDOM(vdom));
}
const Title = <div><h1>Hello</h1></div>
render(<Title/>, document.querySelector('#root'));
1단계 - JSX로 코드 작성
/* @jsx createVNode */
const Title = () => <div><h1>Hello</h1></div>;
*@jsx 주석 지시어 를 통해 바벨로 하여금 JSX를 어떤 함수로 변환할지 설정함.
React.createElement 대신 우리가 만든 createVNode 함수를 써야 하니까,
Babel에게 createVNode 사용하라고 알려주기 위해 @jsx 주석 지시어 사용.
(React 16 이전에는 ) 바벨이 import React from "react"; 통해서
jsx를 const element = React.createElement("h1", null, "Hello"); 변환과정 거쳤음.
React 17 이후에는 import 안해도 자동으로 react 패키지의 jsx-runtime 모듈에 정의된 jsx() 함수"를 Babel이 자동으로 import해서
const el = _jsx("h1", { children: "Hello" });
React.createElement를 대체함
JSX 코드
import React from "react"; /* 17 이전에는 React.createElement가 동작해야하므로 import React 필요*/
const element = <div><h1>Hello</h1></div>;
바벨 변환결과
const element = createVNode(
"div",
null,
createVNode("h1", null, "Hello")
);
//JSX를 가상 DOM 객체로 변환함
export function createVNode(tag, props, ...children) {
return { tag, props, children };
}
- React에서 컴포넌트는 반드시 함수여야 하고, 대문자로 시작해야 한다.
이 경우 Babel이 내부적으로 대문자로 시작하는 JSX 태그를 일반 문자열이 아니라 JavaScript 변수(컴포넌트)로 취급하여 React.createElement를 호출한다.
- tag가 함수 컴포넌트인지 확인 (typeof tag === 'function').
-
- 함수 컴포넌트 라면 tag(props)를 호출하여 실행 결과를 반환
- children이 1개면 단일 값으로 전달, 2개 이상이면 배열로 전달.
- <Title>이름</Title>
- <Title><Item>1</Item><Item>2</Item></Title> 구분
//jsx 코드로부터 변환된 vdom
const element = {
tag: "div",
props: null,
children: [
{
tag: "h1",
props: null,
children: ["Hello"]
}
]
};
render(<Title/>, document.querySelector('#root'));
이것은 즉
render( VDOM, document.querySelector('#root')); 인데
render함수는 vDom과 container를 받아 vDom 을 Dom으로 만들어 돔에 붙이는 함수임.
// 만들어진 DOM을 브라우저에 붙임
export function render(vdom, container) {
container.appendChild(createDOM(vdom));
}
//가상 DOM 객체를 실제 DOM 요소로 변환
export function createDOM(node) {
if (typeof node === 'string') {
return document.createTextNode(node);
}
const element = document.createElement(node.tag);
Object.entries(node.props)
.forEach(([name, value]) => element.setAttribute(name, value));
node.children
.map(createDOM)
//.forEach(element.appendChild.bind(element));
.forEach(child => element.appendChild(child));
return element;
}
vdom.children
.map(createDOM) // 자식들을 DOM으로 변환 → [<p>, <span>]
.forEach(child => element.appendChild(child)); // <div>에 붙이기
핵심 요약
.map(createDOM) → VDOM 배열 → DOM 배열
.forEach(...) → 그 배열을 현재 요소에 붙이는 작업
'개발 공부 > React' 카테고리의 다른 글
redux persist migration (0) | 2024.10.10 |
---|---|
useLocation (0) | 2023.07.18 |
forEach(parent.appendChild.bind(parent)) 이해하기 (0) | 2023.03.03 |
[칼럼] React 컴포넌트를 커스텀 훅으로 제공하기 (0) | 2023.02.22 |
QueryClient 대신 useQueryClient 사용하는 이유 (0) | 2023.02.20 |