클래스란?
객체 지향 프로그래밍에서 클래스는 특정 객체를생성하기 위해 변수와 함수를 정의하는 일종의 틀을 말한다. 객체를 정의하기 위한 상태와 함수로 구성되어 있다. 객체 단위로 코드를 그룹화하고 쉽게 재사용하려고 사용한다.
class Cat {
// 생성자 함수
constructor(name) {
// 여기서 this는 이 클래스입니다.
this.name = name;
}
// 함수
showName(){
console.log(this.name);
}
}
let cat = new Cat('perl');
cat.showName();
console.log(cat);
클래스를 상속한다는 건, 이미 만들어 둔 어떤 클래스를 가지고 자식 클래스를 만든다는 것이다.
class Cat {
// 생성자 함수
constructor(name) {
// 여기서 this는 이 클래스입니다.
this.name = name;
}
// 함수
showName(){
return this.name;
}
}
// extends는 Cat 클래스를 상속 받아 온단 뜻입니다.
class MyCat extends Cat {
// 생성자 함수
constructor(name, age) {
// super를 메서드로 사용하기
super(name);
this.age = age;
}
// 부모 클래스가 가진 것과 같은 이름의 함수를 만들 수 있습니다.
// 오버라이딩한다고 해요.
showName(){
// super를 키워드로 사용하기
return '내 고양이 이름은 '+super.showName()+'입니다.';
}
showAge(){
console.log('내 고양이는 '+this.age+'살 입니다!');
}
}
let my_cat = new MyCat('perl', 4);
my_cat.showName();
my_cat.showAge();
super 키워드
- 메소드로 사용할 수 있다.(constructor 안에서)
- 부모의 constructor를 호출하면서 인수를 전달한다.
- this를 쓸 수 있게 해준다.
- 키워드로 사용할 수 있다.
- 부모 클래스에 대한 필드나 함수를 참조할 수 있다.
let, const와 Scope
스코프(Scope)가 뭘까? 우리가 어떤 변수를 선언했을 때, 그 변수를 사용할 수 있는 유효범위를 스코프라고 부른다. 변수에 접근할 수 있는 범위다.
var: 함수 단위
let : block 단위 (변수 : let으로 선언한 변수는 값이 변할 수 있다.)
const : block 단위(상수: 한번 선언한 값은 바꿀 수 없다.)
function scope(){
const a = 0;
let b = 0;
var c = 0;
// {} 증괄호 안에 든 내용을 블럭이라고 표현해요.
if(a === 0){
const a = 1;
let b = 1;
var c = 1;
console.log(a, b, c);
}
// 앗! c는 값이 변했죠?
// 그렇습니다. var는 함수 단위라서 if문 밖에서 선언한 값이 변했어요.
// let과 const로 선언한 겂은 어떤가요? if문 안쪽 내용이 바깥 내용에 영향을 끼치지 않죠?
console.log(a, b, c);
}
Spread 연산자 (Spread 문법)
어떤 객체 안에 있는 요소들을 객체 바깥으로 꺼내주는 연산자다.
let array = [1,2,3,4,5];
// ... <- 이 점 3개를 스프레드 문법이라고 불러요.
// 배열 안에 있는 항목들(요소들)을 전부 꺼내준다는 뜻입니다.
// 즉 [...array]은 array에 있는 항목을 전부 꺼내
// 새로운 배열([] => 이 껍데기가 새로운 배열을 뜻하죠!)에 넣어주겠단 말입니다!
let new_array = [...array];
console.log(new_array);
//[ 1, 2, 3, 4, 5 ]
삼항 연산자는 if문의 단축 형태입니다. 사용법: 조건 ? 참일 경우 : 거짓일 경우
let info = {name: "mean0", id: 0};
let is_me = info.name === "mean0"? true : false;
console.log(is_me);
//true
Array 내장 함수
map
배열에 속한 항목을 변환할 때 많이 사용한다.
어떤 배열에 속한 항목을 원하는 대로 변환하고, 변환한 값을 새로운 배열로 만들어 준다.
원본 배열은 값이 변하지 않는다.
간단히 설명하면 원 배열의 값을 하나하나 불러와서 array_item에 담아서 오른쪽 함수 안의 구문을 반복한다는 것이다. for of와 조금 비슷하다.
const array_num = [0, 1, 2, 3, 4, 5];
const new_array = array_num.map((array_item) =>{
return array_item + 1;
});
// 새 배열의 값은 원본 배열 원소에 +1 한 값입니다.
console.log(new_array);
// 원본 배열은 그대로 있죠!
console.log(array_num);
//[ 1, 2, 3, 4, 5, 6 ]
//[ 0, 1, 2, 3, 4, 5 ]
filter
어떤 조건을 만족하는 항목들만 골라서 새 배열로 만들어주는 함수이다.
원본 배열은 변하지 않고, 원하는 배열을 하나 더 만들 수 있다.
const array_num = [0, 1, 2, 3, 4, 5];
// forEach(콜백함수)
const new_array = array_num.filter((array_item) => {
// 특정 조건을 만족할 때만 return 하면 됩니다!
// return에는 true 혹은 false가 들어가야 해요.
return array_item > 3;
});
console.log(new_array);
//[ 4, 5 ]
concat
배여로가 배열을 합치거나 배열에 특정 값을 추가해주는 함수이다.
원본 배열은 변하지 않는다.
const array_num01 = [0, 1, 2, 3];
const array_num02 = [3, 4, 5];
const merge = array_num01.concat(array_num02);
// 중복 항목(숫자 3)이 제거되었나요? 아니면 그대로 있나요? :)
console.log(merge);
//[0, 1, 2, 3, 3, 4, 5]
concat은 중복 항목을 제거해주지 않는다.
다른 내장함수와 함께 사용해서 제거해야 한다.
중복 제거를 원할 시에는 Set()을 사용하면 된다.
const array_num01 = [0, 1, 2, 3];
const array_num02 = [3, 4, 5];
// Set은 자바스크립트의 자료형 중 하나로,
// 중복되지 않는 값을 가지는 리스트입니다. :)!
// ... <- 이 점 3개는 스프레드 문법이라고 불러요.
// 배열 안에 있는 항목들(요소들)을 전부 꺼내준다는 뜻입니다.
// 즉 [...array_num01]은 array_num01에 있는 항목을 전부 꺼내
// 새로운 배열([] 이 껍데기가 새로운 배열을 뜻하죠!)에 넣어주겠단 말입니다!
const merge = [...new Set([...array_num01, ...array_num02])];
// 중복 항목(숫자 3)이 제거되었나요? 아니면 그대로 있나요? :)
console.log(merge);
from
쓰임새가 다양하다.
배열로 만들고자 하는 것이나 유사배열을 복사해서 새로운 배열로 만들 때 사용한다.
새로운 배열을 만들 때 사용한다. (초기화한다고도 표현한다.)
유사배열이란?
[a,b,c,b] 이 모양으로 생겼지만 배열의 내장 함수를 사용하지 못하는 것들이다. DOM nodelist같은 게 유사배열이다.
// 배열화 하자!
const my_name = "mean0";
const my_name_array = Array.from(my_name);
console.log(my_name_array);
// 길이가 문자열과 같고, 0부터 4까지 숫자를 요소로 갖는 배열을 만들어볼거예요.
const text_array = Array.from('hello', (item, idx) => {return idx});
console.log(text_array);
// 새 배열을 만들어 보자!(=> 빈 배열을 초기화한다고도 해요.)
// 길이가 4고, 0부터 3까지 숫자를 요소로 갖는 배열을 만들어볼거예요.
const new_array = Array.from({length: 4}, (item, idx)=>{ return idx;});
console.log(new_array);
//[ 'm', 'e', 'a', 'n', '0' ]
//[ 0, 1, 2, 3, 4 ]
//[ 0, 1, 2, 3 ]
quiz.
고양이들만 새 배열에 넣기.
const animals = ["복슬 강아지", "검정 고양이", "노란 햄스터", "강아지", "노랑 고양이", "고양이", "흰 토끼"];
let cats = [];
for (let i = 0; i < animals.length; i++) {
let animal = animals[i];
// indexOf는 파라미터로 넘겨준 텍스트가 몇 번째 위치에 있는 지 알려주는 친구입니다.
// 파라미터로 넘겨준 텍스트가 없으면 -1을 반환해요!
// 즉 아래 구문은 고양이라는 단어를 포함하고 있니? 라고 묻는 구문이죠!
if (animal.indexOf("고양이") !== -1) {
cats.push(animal);
}
}
console.log(cats);
filter로 변환하면 아래와 같다.
const animals = ["복슬 강아지", "검정 고양이", "노란 햄스터", "강아지", "노랑 고양이", "고양이", "흰 토끼"];
let cats = animals.filter((animal) => {
return animal.indexOf("고양이") !== -1;
})
console.log(cats)
=======================================
리액트로 넘어가 보자.
nvm 을 이용해 원하는 버전 node를 설치한다.
nvm install [설치할 버전]
nvm install 14.17.6
nvm ls # nvm으로 설치한 노드 버전 리스트 확인 명령어
node -v # 노드 버전 확인 명렁어
nvm use 사용할 노드 버전
npm으로 yarn을 설치했다. -g는 글로벌이라는 의미이다.
npm install -g yarn
# 옵션 global은 전역에 이 패키지를 깔겠다는 뜻입니다.
yarn add global create-react-app
CRA란 웹사이트를 만들 때 필요한 것을 몽땅 때려넣은 만든 패키지이다. 레고의 해리포터 성 만들기 같은 거라고 생각하면 편하다.
첫 리액트 프로젝트(week-1)를 만든다.
# yarn create react-app [우리의 첫 리액트 프로젝트 이름]
# 우리가 설치한 create-react-app 패키지를 써서 프로젝트를 만들어요.
# 주의! 꼭 sparta_react 폴더 경로에서 입력해주세요!
yarn create react-app week-1
week-1을 만들었으니 이동해서 시동해보자
cd week-1 # week-1 폴더로 이동합니다.
yarn start
하하 귀여운 첫페이지가 완성되었다.
JSX
HTML을 품은 JS === JSX!
import './App.css';
function App() {
const div_back_styles = {
width: '100vw',
maxWidth: '400px',
margin: '30px auto',
flexDirection: 'column',
}
const color_green = {color:"green"}
const div_styles = {
height : "70px",
borderBottom : "2px solid black",
padding: "20px",
width: '100vw',
maxWidth: '400px',
margin: '30px auto',
flexDirection: 'column'
}
return (
<div className="App">
<div style={div_back_styles}>
<div style={div_styles}>
<h1 style={color_green}>안녕하세요!</h1>
</div>
<p style={{textAlign:'left'}}>이름을 입력해주세요.</p>
<input type="text"/>
</div>
</div>
);
}
export default App;
간단한 퀴즈를 풀어보았다.
Component란?
위에서 리액트는 레고라고 말씀 드렸죠? 컴포넌트는 블록이다!
이 웹사이트를 HTML로 간단히 표현해보면 아래와 같다.
<!DOCTYPE html>
<html lang="en">
<head>
</head>
<body>
<header>
...
</header>
<div class="container">
<div id="image-banner">
...
</div>
<div id="contents-1">
...
</div>
</div>
<footer>
...
</footer>
</body>
</html>
이 코드를 조각조각 내보면 아래와 같이 나눌 수 있을 거예요. 나눈 조각 하나하나를 컴포넌트라고 부른다.
- <header/>
- <container/>
- <imagebanner/>
- <contents1/>
- <footer/>
즉, 이 웹 사이트는, 크게 <header/>, <container/>, <footer/> 세 개의 컴포넌트가 있고, <container/> 컴포넌트는, <imagebanner/>, <contents1/> 컴포넌트로 이루어져 있는 거죠!
State
state는 Component가 가지고 있는 데이터입니다.
Props
props는 Component가 부모 Component로부터 받아온 데이터입니다.
Component
함수형 컴포넌트
// 리액트 패키지를 불러옵니다.
import React from 'react';
// 함수형 컴포넌트는 이렇게 쓸 수도 있고
// function Bucketlist(props){
// return (
// <div>버킷 리스트</div>
// );
// }
// 이렇게 쓸 수도 있어요. =>가 들어간 함수를 화살표 함수라고 불러요.
// 저희는 앞으로 화살표 함수를 사용할거예요.
// 앗 () 안에 props! 부모 컴포넌트에게 받아온 데이터입니다.
// js 함수가 값을 받아오는 것과 똑같이 받아오네요.
const BucketList = (props) => {
// 컴포넌트가 뿌려줄 ui 요소(리엑트 엘리먼트라고 불러요.)를 반환해줍니다.
return (
<div>
버킷 리스트
</div>
);
}
// 우리가 만든 함수형 컴포넌트를 export 해줍니다.
// export 해주면 다른 컴포넌트에서 BucketList 컴포넌트를 불러다 쓸 수 있어요.
export default BucketList;
클래스형 컴포넌트
import React from 'react';
import logo from './logo.svg';
import './App.css';
// BucketList 컴포넌트를 import 해옵니다.
// import [컴포넌트 명] from [컴포넌트가 있는 파일경로];
import BucketList from './BucketList';
// 클래스형 컴포넌트는 이렇게 생겼습니다!
class App extends React.Component {
constructor(props){
super(props);
// App 컴포넌트의 state를 정의해줍니다.
this.state = {
list: ['영화관 가기', '매일 책읽기', '수영 배우기'],
};
}
// 랜더 함수 안에 리액트 엘리먼트를 넣어줍니다!
render() {
return (
<div className="App">
<h1>내 버킷리스트</h1>
{/* 컴포넌트를 넣어줍니다. */}
<BucketList/>
</div>
);
}
}
export default App;
1주차 과제도 해보았다.
import logo from './logo.svg';
import './App.css';
import React from "react";
import Start from "./Start";
class App extends React.Component{
constructor(props){
super(props);
this.state = {
name: "고양이"
};
}
render () {
return (
<div className="App">
{ <Start name={this.state.name}/> /*name으로 state의name값을 보낸다. */}
</div>
)
}
}
export default App;
import React from "react";
import img from "./neko.jpg";
const Start = (props) => {
// 컬러셋 참고: https://www.shutterstock.com/ko/blog/pastel-color-palettes-rococo-trend/
return (
<div
style={{
display: "flex",
height: "100vh",
width: "100vw",
overflow: "hidden",
padding: "16px",
boxSizing: "border-box",
}}
>
<div
className="outter"
style={{
display: "flex",
alignItems: "center",
justifyContent: "center",
flexDirection: "column",
height: "100vh",
width: "100vw",
overflow: "hidden",
padding: "0px 10vw",
boxSizing: "border-box",
maxWidth: "400px",
}}
>
<img src={img} style={{ width: "80%", margin: "16px" }} />
<h1 style={{ fontSize: "1.5em", margin: "0px", lineHeight: "1.4" }}>
나는{" "}
<span
style={{
backgroundColor: "#fef5d4",
padding: "5px 10px",
borderRadius: "30px",
}}
>
{ props.name /*여기서 props로 부모에게서 받은 리스트의 name값을 받아온다. */}
</span>
에 대해 얼마나 알고 있을까?
</h1>
<input
type="text"
style={{
padding: "10px",
margin: "24px 0px",
border: "1px solid #dadafc",
borderRadius: "30px",
width: "100%",
// backgroundColor: "#dadafc55",
}}
placeholder="내 이름"
/>
<button
style={{
padding: "8px 24px",
backgroundColor: "#dadafc",
borderRadius: "30px",
border: "#dadafc",
}}
>
시작하기
</button>
</div>
</div>
);
};
export default Start;
2주차!
SCSS를 쓰기위해
yarn add node-sass@4.14.1 open-color sass-loader classnames
로 설치해준다.
yarn add styled-components
styled-components란?
컴포넌트 스타일링 기법 중, 제가 가장 좋아하는 방식입니다! 😎 왜 좋아하냐구요? 많은 이유가 있지만, 두 개만 꼽아볼게요.
- class 이름 짓기에서 해방됩니다!
- 컴포넌트에 스타일을 적기 때문에, 간단하고 직관적입니다!
CSS-in-JS 라이브러리 중 하나입니다! 컴포넌트에 스타일을 직접 입히는 방식이라고 편하게 생각하셔도 됩니다!
라이프 사이클이란?
- 컴포넌트의 라이프 사이클(= 컴포넌트 생명주기)은 정말 중요한 개념입니다! 컴포넌트가 렌더링을 준비하는 순간부터, 페이지에서 사라질 때까지가 라이프 사이클이에요.
- 아래 도표는 어떻게 라이프 사이클이 흘러가는 지 그린 도표입니다.
-
- 컴포넌트는 생성되고 → 수정(업데이트)되고 → 사라집니다.
- 생성은 처음으로 컴포넌트를 불러오는 단계입니다.
- 수정(업데이트)는 사용자의 행동(클릭, 데이터 입력 등)으로 데이터가 바뀌거나, 부모 컴포넌트가 렌더링할 때 업데이트 됩니다. 아래의 경우죠!
- props가 바뀔 때
- state가 바뀔 때
- 부모 컴포넌트가 업데이트 되었을 때(=리렌더링했을 때)
- 또는, 강제로 업데이트 했을 경우! (forceUpdate()를 통해 강제로 컴포넌트를 업데이트할 수 있습니다.)
- 제거는 페이지를 이동하거나, 사용자의 행동(삭제 버튼 클릭 등)으로 인해 컴포넌트가 화면에서 사라지는 단계입니다.
-
- 컴포넌트는 생성되고 → 수정(업데이트)되고 → 사라집니다.
- 생성은 처음으로 컴포넌트를 불러오는 단계입니다.
- 수정(업데이트)는 사용자의 행동(클릭, 데이터 입력 등)으로 데이터가 바뀌거나, 부모 컴포넌트가 렌더링할 때 업데이트 됩니다. 아래의 경우죠!
- props가 바뀔 때
- state가 바뀔 때
- 부모 컴포넌트가 업데이트 되었을 때(=리렌더링했을 때)
- 또는, 강제로 업데이트 했을 경우! (forceUpdate()를 통해 강제로 컴포넌트를 업데이트할 수 있습니다.)
- 제거는 페이지를 이동하거나, 사용자의 행동(삭제 버튼 클릭 등)으로 인해 컴포넌트가 화면에서 사라지는 단계입니다.
라이프 사이클 함수는 클래스형 컴포넌트에서만 사용할 수 있습니다. 라이프 사이클을 아는 건 중요한데 왜 우리는 클래스형 컴포넌트보다 함수형 컴포넌트를 많이 쓰냐구요? 리액트 공식 매뉴얼에서 함수형 컴포넌트를 더 권장하기 때문입니다! (리액트 16.8버전부터 등장한 React Hooks으로 라이프 사이클 함수를 대체할 수 있거든요.) 더 많은 라이프 사이클 함수는 공식 문서에서 확인할 수 있어요 😉
06. Ref! 리액트에서 돔요소를 가져오려면?
React.createRef()
- 이제 가상돔이 뭔지, 돔이 뭔진 알겠죠? 라이프 사이클도 알구요. 그런데 만약에, 내가 어떤 인풋박스에서 텍스트를 가져오고 싶으면 어떻게 접근해야할까요? (render()가 끝나고 가져오면 될까요? 아니면 mount가 끝나고? 아니, 그 전에 가상돔에서 가져오나? 아니면 DOM에서? 😖) → 답은, 리액트 요소에서 가져온다!
- React 요소를 가지고 오는 방법
import React from "react";
import logo from "./logo.svg";
// BucketList 컴포넌트를 import 해옵니다.
// import [컴포넌트 명] from [컴포넌트가 있는 파일경로];
import BucketList from "./BucketList";
import styled from "styled-components";
// 클래스형 컴포넌트는 이렇게 생겼습니다!
class App extends React.Component {
constructor(props) {
super(props);
// App 컴포넌트의 state를 정의해줍니다.
this.state = {
list: ["영화관 가기", "매일 책읽기", "수영 배우기"],
};
// ref는 이렇게 선언합니다!
this.text = React.createRef();
}
componentDidMount(){
// 콘솔에서 확인해보자!
console.log(this.text);
console.log(this.text.current);
}
// 랜더 함수 안에 리액트 엘리먼트를 넣어줍니다!
render() {
return (
<div className="App">
<Container>
<Title>내 버킷리스트</Title>
<Line />
{/* 컴포넌트를 넣어줍니다. */}
{/* <컴포넌트 명 [props 명]={넘겨줄 것(리스트, 문자열, 숫자, ...)}/> */}
<BucketList list={this.state.list} />
</Container>
<div>
<input type="text" ref={this.text}/>
</div>
</div>
);
}
}
const Container = styled.div`
max-width: 350px;
min-height: 80vh;
background-color: #fff;
padding: 16px;
margin: 20px auto;
border-radius: 5px;
border: 1px solid #ddd;
`;
const Title = styled.h1`
color: slateblue;
text-align: center;
`;
const Line = styled.hr`
margin: 16px 0px;
border: 1px dotted #ddd;
`;
export default App;
********************************************************
새 프로젝트를 시작할 때 해야할 순서!!!!!
+ 예시로 네모 카운트 숫자에 따라 계속 찍어 내는 프로젝트
(1) 새 CRA 만들기
yarn create react-app nemo
(2) index.js에서 <React.StrictMode> 부분을 지우기
(3) App.js를 class형 컴포넌트로 바꾸고 시작!
// App component를 class형으로!
import React from 'react';
class App extends React.Component {
constructor(props){
super(props);
this.state = {}
}
componentDidMount(){
}
render(){
return (
<div className="App">
</div>
);
}
}
export default App;
state에 count라는 변수를 추가하고, count 숫자만큼 네모칸을 화면에 띄우기
import React from "react";
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 3, // 숫자넣기!
};
}
componentDidMount() {}
render() {
// 배열을 만듭니다.
// Array.from()은 배열을 만들고 초기화까지 해주는 내장 함수입니다.
// Array.from()의 첫번째 파라미터로 {length: 원하는 길이} 객체를,
// 두번째 파라미터로 원하는 값을 반환하는 콜백함수를 넘겨주면 끝!
// array의 내장함수 대부분은 콜백 함수에서 (현재값, index넘버)를 인자로 씁니다.
const nemo_count = Array.from({ length: this.state.count }, (v, i) => i);
// 콘솔로 만들어진 배열을 확인해봅니다. 숫자가 0부터 순서대로 잘 들어갔나요?
console.log(nemo_count);
return (
<div className="App">
{nemo_count.map((num, idx) => {
return (
<div key={idx}
style={{
width: "150px",
height: "150px",
backgroundColor: "#ddd",
margin: "10px",
}}
>
nemo
</div>
);
})}
</div>
);
}
}
export default App;
더하기, 빼기 버튼을 만들고,
return (
<div className="App">
{nemo_count.map((num, idx) => {
return (
<div key={idx}
style={{
width: "150px",
height: "150px",
backgroundColor: "#ddd",
margin: "10px",
}}
>
nemo
</div>
);
})}
<div>
<button>하나 추가</button>
<button>하나 빼기</button>
</div>
</div>
);
함수를 만들어서
addNemo = () => {
// this.setState로 count를 하나 더해줍니다!
this.setState({ count: this.state.count + 1 });
};
removeNemo = () => {
// 네모 갯수가 0보다 작을 순 없겠죠! if문으로 조건을 걸어줍시다.
if (this.state.count > 0) {
// this.setState로 count를 하나 빼줍니다!
this.setState({ count: this.state.count - 1 });
}else{
window.alert('네모가 없어요!');
}
};
연결하자!
<div>
{/* 함수를 호출합니다. 이 클래스 안의 addNemo 함수를 불러오기 때문에 this.addNemo로 표기해요. */}
<button onClick={this.addNemo}>하나 추가</button>
<button onClick={this.removeNemo}>하나 빼기</button>
</div>
오늘은 여기까지만... 너무 지친다...
'Today I Learned' 카테고리의 다른 글
13 TIL node aws 배포 명령어, 처음 시작 시 github remote add commit push 하기 (0) | 2021.09.30 |
---|---|
12 TIL 리액트 박살내기! (0) | 2021.09.29 |
10 TIL 2 WIL REST, Restful API, GraphQL 차이 장단점 , DOM, 서버리스, 파이어베이스 (0) | 2021.09.26 |
9TIL 항해99 13일차 (0) | 2021.09.25 |
7 TIL (0) | 2021.09.23 |