일찍 자고 일찍 일어나는 생활습관을 가지니
어제 하다만 계산기 만들기를 마저 해보려구요
가 아니라 어제 얼추 만들었음
https://codepen.io/adckqaty-the-bold/pen/vYzYywm
코드펜에서 실행해볼 수 있습니다.
😎 얼마나 구현했는지
1. 입력창을 비워주는 clear 버튼 구현
2. 최근 입력한 것을 지워주는 백스페이스 버튼 구현
3. 여러자릿수의 사칙연산 구현
4. 실시간으로 입력한 값들을 볼 수 있도록 구현
5. = 버튼 구현
😎 이벤트 버블링 네가 뭔데..
이벤트 버블링이란 이벤트가 아래에서 위로 전파되는 것을 의미합니다.
사실상 이것덕분에 멘탈 터질뻔함
대략 이문제로 40분 정도 고민한 것 같다.
문제 상황은 이랬음
부모요소의 이벤트 핸들러에 시무룩 = "문자"
자식요소의 이벤트 핸들러에 시무룩 = "자문"
대충 이런식으로 되어있다면 난 자문이 출력되길 바라는데
자꾸 문자가 출력되는 상황이었던 것
처음엔 콜백함수가 문제인가? 뭐가 문제인가? 고민하면서
1. 콜백함수의 리턴값 외에 다른 값을 넣어보기
2. preventDefault() 함수로 기본동작 막아보기
3. value에 값을 할당하는게 아니라 textcontent등에 할당해보기
4. 값이 넘버타입이어서 그런건가해서 String()메서드로 문자열화해보기
등등을 해봤지만 전혀 해결되지 않았는데
결론은 이벤트핸들러의 문제였다.
코드를 줄이기 위해 if 케이스에 해당할때만 변수에 할당을 해주는게아니라
핸들러가 호출되면 마지막에 변수에 할당을 해주는 식으로 코드를 짰더니
버블링이 일어나면 원치않는 변경이 일어나는 것이었다.
만약 내가 버블링캡처링 개념을 모르고있었다면...;;;
이래서 내가 뭘 모르는지 아는것이 중요한 거구나 체감하게 되었다.
const btn = document.querySelector(".btn");
const eraser = document.querySelector(".eraser");
const result = document.querySelector(".result");
const comma = document.querySelector(".comma");
const equal = document.querySelector(".equal");
let stack = [];
const onClickStack = (e) => {
e.preventDefault();
let event = e.target.className;
let value = e.target.textContent;
if (event === "num") {
stack.push(value);
result.value = stack.join("");
}
if (event === "operator") {
if (isNaN(stack[stack.length - 1])) {
stack.pop();
stack.push(String(value));
result.value = stack.join("");
} else {
stack.push(String(value));
result.value = stack.join("");
}
}
};
const onClickEraser = (e) => {
e.preventDefault();
let event = e.target.className;
if (event === "back") {
stack.pop();
result.value = stack.join("");
}
if (event === "clear") {
stack = [];
result.value = stack.join("");
}
};
const makeResult = (stack) => {
let [n1, n2, op] = ["", "", ""];
let idx = 0;
for (i = 0; i < stack.length; i++) {
if (isNaN(stack[i])) {
op = stack[i];
idx = i;
break;
}
n1 += String(stack[i]);
}
for (i = idx + 1; i < stack.length; i++) {
n2 += String(stack[i]);
}
if (op == "*") return Number(n1) * Number(n2);
if (op == "/") return Number(n1) / Number(n2);
if (op == "+") return Number(n1) + Number(n2);
if (op == "-") return Number(n1) - Number(n2);
return 0;
};
const onClickEqual = (event) => {
let answer = makeResult(stack);
result.value = answer;
};
eraser.addEventListener("click", onClickEraser);
btn.addEventListener("click", onClickStack);
equal.addEventListener("click", onClickEqual);
내가 작성한 코드는 다음과 같다.
onClickEraser() 함수를 주목해서 보면
if케이스에 해당할때마다 result.value에 stack.join('')을 할당해주는 것을 알 수 있다.
원래는 두 if 케이스에 모두 result.value를 재할당해주니까
그냥 이벤트핸들러가 호출되면 맨마지막에 result.value 할당을 해주면
코드가 줄어드니까 좋은거 아닌가? 하고 짜놨는데
그렇게 했더니 이벤트 버블링이 일어났을 때 내가 원치않는 동작이 일어나게 되어버린 것
사칙연산은 stack을 이용해서 간단하게 구현해봤는데
사실 예외처리를 열심히 해주진 않아서 알고리즘에 오류도 있고 기능도 부족하다.
예컨대 위 코드는 n1은 음수를 넣을수있지만 n2에는 음수를 넣을 수 없다...!
또한 **과 같은 제곱연산도 불가능하다.
왜냐면 연산자는 반드시 두 연산자가 붙어있지 않도록 구성했기때문이다.
스택의 마지막이 연산자인데 또 연산자를 집어넣으면 pop()한뒤에
새 연산자를 집어넣어주는 구조이기 때문
ㅎㅎ;; ㅈㅅ;;
또한 isNaN을 통해 if케이스를 처리하기 때문에
후에 "." 소숫점을 구현하려고할 때 기존 코드에 수정이 필요해진다.
😎부족하다고 느낀 점
객체지향프로그래밍이나 디자인패턴을 찍어먹어보면서
뭐 이런 당연한 소리를... 이라고 생각하던 나를 반성하게 되었다.
막상 작성하려고하니 그런 디자인 패턴 같은건 생각도 못하고
구현 자체에서 가로막혀버리는 것
단일책임원칙..? 좋죠.. 근데... 난 그렇게 못 짰어요
stack을 해줄 함수가 이벤트 유형을 구분하는 일도 같이 하고있는건 너무나도 당연해요..
😎 CSS는 chatGPT한테 시켜보자
여러번 물어보니 이런 형태의 css를 제공해줬다.
뭐... 예쁘다고 하긴 뭐한데 그럴듯하긴 한 것 같은데..?
😎 CSS는 뒤돌아서면 까먹는 게 국룰
그래도.. 예전에 속터져가면서 과제를 쳐내던 건 헛되지 않았던 것 같다.
예전보단 내 예상대로 움직여주는 느낌이라고 해야하나
여전히 이해 안 되는 동작도 여럿 있지만 그냥 받아들인 상태
한번 꼬이면 아무리 수정을 해줘도 먹통이 되니까
처음 설계를 잘해야겠다는 생각이 들었고
예전에 언뜻 봤던 scss 같은 전처리기들의 기능이 필요하다는 생각이 들었다.
제일 많은 필요성을 느꼈던 부분은 역시 mixin 기능
css는 중복으로 작성하는 코드가 굉장히 많고
또 세트로 같이 사용하는 속성이 굉장히 많다보니
mixin 기능이 이래서 필요한거구나.. 몸으로 체감이 되었다.
text-align .. justify-content, align-items..... 으아아아악
그리고 간단한 작업이라 굳이 변수가 필요하진 않았지만
예전에 변수를 잔뜩 설정해두고 그 변수를 꺼내오는 식으로 작업했던게
확실히 더 효율적이란 생각이 들었는데...
변수를 어떻게 사용하는지를 깜빡해버렸다.ㅎㅎ;;
***
height 와 line-height를 같은값으로 주면 텍스트가 중앙정렬된다.
어렴풋이는 알고있었는데 이제 확실히 알게되었다.
하지만 또 뒤돌아서 까먹고 justify content와 align-items를 할 내가 예상됨
😎 CSS에서 변수를 정의해보자.
CSS에서 변수를 사용해보기 이전에 CSS에서 변수를 사용하면 뭐가 좋은걸까?
1. 값의 재사용성이 좋아진다.
2. 변수 값을 바꿔주는 것만으로 그 변수를 사용하는 모든 속성들의 값을 한번에 바꿔줄 수 있다.
:root {
--main-color: #ff0000;
}
변수는 이런식으로 작성한다. 이런식이 무슨식임?
이라고하면...
먼저 :root {} 에 작성하는것은 :root 선택자가 최상위 요소인 html을 가리키기때문입니다.
따라서 :root {}에 작성해둔 변수는 문서 전체에서 사용할 수 있어요!
게다가 변수를 중복 선언 혹은 재정의하더라도
:root 선택자에서 정의된 변수가 CSS의 계층구조에서 가장 높은 우선순위를 가지기 때문에
:root 에 정의해둔 변수가 우선 사용된답니다.
root.css 파일을 만들어두고 거기에 나만의 규칙을 갖고
margin, padding, color 등을 정의해두면 통일성있게 CSS를 작성할 수 있을 것입니다.
또한 변수명을 정의할 때에는 반드시 앞에 --를 넣어줘야합니다.
--변수명 : 값
이런식으로요!
😎 이제 정의하는건 알겠는데 어케 씀?
.element {
color: var(--main-color);
}
속성의 값 부분에 var(변수명)을 넣어주면 됩니다.
실제로 사용해본 결과.. 변수를 쓰는 기분은 좋은데
var(--)이걸 치고있는 내 손이 너무 귀찮은 거 빼면 참 좋습니다.
😎border box를 사용해야하는 이유
그냥 box-sizing = borderbox로 쓰셈 알겠음?? 만 하면 납득이 안되죠
css는 기본적으로 content-box를 사용합니다.
border-box는 따로 설정을 해줘야하는데 보통 border-box를 주로 사용하니
최상위 속성 *나 root에 box-sizing : border-box를 줍니다.
border-box는 테두리와 안쪽 여백이 요소의 크기를 변경하지 않습니다.
패딩과 보더(테두리)의 크기를 포함해서 생각한다는거죠!
만약에 contentbox를 사용한다고 생각을 했을때
div의 크기는 반드시 가로세로 200px이어야한다고 가정해봅시다.
padding 20px 줬으니까 20더하고... border 5px 줬으니까 5더하고...
그럼 크기는 175px로 지정하면 딱 200px이네!
이거 할맛 나겠음? 쨰트킥
따라서 border box를 사용해주는 편이 계산을 훨씬 직관적으로 할 수 있기에 사용한다는것..
😎 CSS의 선택자
CSS에는 굉장히 세밀하게 선택자가 존재합니다.
그걸 생각 못 하고 모든 태그에 서로다른 클래스와 아이디를 때려박으면서
하나하나 클래스를 주면서 CSS를 작성하던 때도 있었으나 그것은 좀 더 과거의 일
유용하게 사용한 선택자들만 정리해보도록 하겠습니다.
E > F | > 자식선택자 | 직계자식 중 해당하는 걸 선택해줌 ol 태그의 자식 중 li 태그인 자식"들"을 선택한다는 의미 |
E ~ F | ~ 일반형제선택자 | 앞의 형제이면서 뒤의 조건을 만족하는 태그를 선택해줌 |
E F | 띄어쓰기 후손하위선택자 | > 선택자는 직계자식만 선택해주는데에 반해 띄어쓰기로 표현한것은 직계자식 뿐만아니라 자신의 자식으로 있는 모든 요소 중 해당하는 것을 선택해줌 |
E:first-child | 맨위의 자식 선택 | 말그대로다 |
E:last-child | 맨아래의 자식 선택 | 말그대로다 |
E:nth-child(n) | n번째 자식 선택 | 괄호값을 설정하지않으면 0부터시작 1이 제일 위의 요소임 2n << 짝수번째만 선택함 n+3 << 3번째 요소부터 선택해줌 |
E:not(S) | S가 아닌 E 선택 | 예를들면 특정 클래스를 갖고있지 않은 요소들만 선택해주고싶을때 사용할 수 있겠네요 |
😎 flex가 살짝 헷갈려
정확히는 flex의 basis, shark? 이런 늘어남을 제어해주는 속성들을
어떻게 써야 제대로 적용되는지가 헷갈린다.
조금만 구글링하면 바로 답이 나오는걸 알지만
머리를 굴리면서 이해하고 싶지는 않은 나약한 마음
😎 내일 할 일
내일은 첫 페어프로그래밍이 있다.
계산기의 html 목업과 css를 만드는 건데
페어니까 둘이서 한개를 만드는건가 했더니
그냥 각자 만드는걸 권장한다..?
엄.. 하지만 그렇다면 그런것이겠지요
flex에 대해서도 좀 더 헷갈리는 부분들을 찾아보고(basis!!)
grid도 예전에 포스팅해둔 글을 다시 찾아봐야겠다..
'TIL' 카테고리의 다른 글
2.20 TIL (0) | 2023.02.20 |
---|---|
02.17 TIL 계산기 목업 만들기 (0) | 2023.02.17 |
02.16 TIL 완전탐색, flex (0) | 2023.02.16 |
02.14 TIL 리눅스 명령어와 계산기 만들기 (0) | 2023.02.14 |
02.13 TIL (0) | 2023.02.13 |