변화 시키기 편하고 변할때 동작범위 밖의 요소가 바뀌어선 안됨
0. 원래의 코드
function createElement(type, props) {
switch(type){
case 'h1' :
return [document.createElement('h1')]
.map(element => {
Object
.entries({...props, 'data-id': 'title'})
.forEach([name, value] => element.setAttribute(name,value))
return element;
})[0];
case 'div' :
return [document.createElement('div')]
.map(element => {
Object
.entries({...props, 'data-id': 'layout'})
.forEach([name, value] => element.setAttribute(name,value))
return element;
})[0];
}
}
function createH1(props) {
return [document.createElement('h1')]
.map(element => {
Object
.entries({...props, 'data-id': 'title'})
.forEach([name, value] => element.setAttribute(name,value))
return element;
})[0];
}
function createDiv(props) {
return [document.createElement('div')]
.map(element => {
Object
.entries({...props, 'data-id': 'layout'})
.forEach([name, value] => element.setAttribute(name,value))
return element;
})[0];
}
function createElement(type, props) {
switch(type){
case h1: return createH1(props)
case div: return createDiv(props)
}
}
function createH1(props) {
return [document.createElement('h1')]
.map(element => {
Object
.entries({...props, 'data-id': 'title'})
.forEach([name, value] => element.setAttribute(name,value))
return element;
})[0];
}
function createDiv(props) {
return [document.createElement('div')]
.map(element => {
Object
.entries({...props, 'data-id': 'layout'})
.forEach([name, value] => element.setAttribute(name,value))
return element;
})[0];
}
const creatorMap = {
h1: createH1,
div:createDiv,
};
function createElement(type, props) {
return creatorMap[type](props)
}
function createH1(props) {
return [document.createElement('h1')]
.map(element => {
Object
.entries({...props, 'data-id': 'title'})
.forEach([name, value] => element.setAttribute(name,value))
return element;
})[0];
}
function createDiv(props) {
return [document.createElement('div')]
.map(element => {
Object
.entries({...props, 'data-id': 'layout'})
.forEach([name, value] => element.setAttribute(name,value))
return element;
})[0];
}
const creatorMap = {
h1: createH1,
div:createDiv,
};
const coupler = map
=> (type, props) => map[type](props);
const createElement = coupler(creatorMap)
DOM API : html문서를 브라우저가 렌더링 하기 위해서 가공시켜 좋은 객체의 통칭
복잡도를 낮출 패턴
초기버전으로 코드분석해보기. 요즘 버전은 파악하기 어려움
문자열을 다루지 말자! 훨씬 다루기 쉬운 객체로 만들어 보자
그런 프로그램이 react
브라우저에 서빙하기 위해서는 번들링 과정이 필요하다.
여러개의 파일들을 하나의 파일을 만들어냄
빌드 할 수 있는 구조를 만들어보자
터미널 셋업시작!
{
"presets": ["@babel/preset-env"]
}
const HtmlWebpackPlugin = require('html-webpack-plugin')
const path = require('path');
module.export = {
mode: 'development',
entry: './app.js',
output: {
path: path.resolve(__dirname, 'dist'),
// (현재디렉토리, 출력디렉토리)
filename: 'bundle.js'
},
devServer: {
compress: true,
port: 9999,
},
module: {
rules: [ // 로더들을 지정하게 됨
{
test: /\.js$/, // 정규식. 바벨로더는 자바스크립트파일만 처리
exclude: /node_modules/, // 특정 디렉토리 제외
use: { // 설치한 바벨로더, 플러그인 셋팅
loader: 'babel-loader',
options: {
presets: ["@babel/preset-env","@babel/preset-react"]
}
}
}
]
},
plugins: [
new HtmlWebpackPlugin() // 인스턴스로 함수 호출
]
}
번들링 실행
npm run dev 데브서버연결
localhost:9999 브라우저로 확인
npm run build
개발할 때 쓰는 파일들은 src 폴더에 옮겨놓기
트리구조
// react.js
export function createElement(tag, props, ...children) {
// ...children 가변인자로 받기 때문에
return{
tag, props, children // children이 자연스럽게 배열이 됨
}
};
// app.js
const vdom = createElement('p', {},
createElement('h1',{}, "react 만들기"),
createElement('ul',{},
createElement('li',{},"1"),
createElement('li',{},"2"),
createElement('li',{},"3"),
),
);
프론트엔드 개발자들에게 가장 익숙한 포맷
소스코드안에 /* @jsx createElement */
react.js
export function createElement(tag, props, ...children ) {
return { tag, props, children
}
// app.js
import { createDOM, createElement, render } from './react';
const vdom = <p>
<ul>
<li>첫번째</li>
</ul>
</p>
리액트가 함수 컴포넌트를 만드는 방법
function Title(props) {
return <h1>{ props.children }</h1>;
}
함수에서 작성할 수 있는 코드들을 삽입할 수 있다는 장점
class Title extends Components {
render() {
return <h1 { this.props.children }</h1>;
}
}
dom처리는 react가, jsx로 컴포넌트 베이스의 개발방식을 만들어 줄수 있음