📌 this 란

실행할 코드에 제공할 환경 정보들을 모아놓은 객체를 실행 컨텍스트(execution context) 라고 부른다. 자바스크립트 내부에서 이런 실행 컨텍스트를 스택(Stack)으로 관리하고 있으며, 실행되는 시점에서 자주 변경되는 실행 컨텍스트를 this 가 가리키고있다. 

 

스택 중 콜스택(Call Stack)에 쌓아올리며 가장 위에 쌓여있는 컨텍스트와 관련된 코드를 실행하는 방법으로 코드의 환경과 순서를 보장 할 수 있다.

 

 

객체 지향 언어에서 this는 클래스로 생성한 인스턴스를 말하지만, 자바스크립트에서 this는 언제 어디서나 사용할 수 있다.

this는 실행되는 코드의 실행 컨텍스트를 가리킨다!

💡 실행 컨텍스트 속 3가지
VariableEvironment
LexicalEvironment
ThisBinding 👉🏻 오늘 이해할 것

 

 

 

1. default binding

기본적으로 this는 전역 객체를 가리킨다. 브라우저 환경에서 this는 window를 가르키고, 노드 환경에서 this는 global을 가르킨다.

Browser

 

Node

 

 

 

2. 메서드 내부에서의 this

함수 함수는 호출의 주체가 없고 함수 그 자체로 독립적인 기능을 수행한다.
메서드 반대로 메서드는 호출 주체가 있으며 자신을 호출한 대상 객체에 대한 동작을 수행한다.

 

함수

함수명();
// CASE1 : 함수
// 호출 주체를 명시할 수 없기 때문에 this는 전역 객체를 의미
var func = function (x) {
console.log(this, x);
};
func(1); // Window { ... } 1

메서드

객체.메서드();
// CASE2 : 메서드
// 호출 주체를 명시할 수 있기 때문에 this는 해당 객체(obj)를 의미
// obj는 { method: func }
var obj = {
method: func,
};
obj.method(2); // { method: [Function: func] } 2

 

 

예외

메서드 내부에서도 독립적으로 호출한다면 this는 전역 객체를 의미한다.

var obj1 = {
    outer: function () {
        console.log(this); // (1)
        var innerFunc = function () {
            console.log(this); // (2), (3)
        }
        innerFunc();
        var obj2 = {
            innerMethod: innerFunc
        };
        obj2.innerMethod();
    }
};
obj1.outer();
실행결과
(1) : obj1
(2) : 전역객체
(3) : obj2

 

 

 

3. this 우회

화살표(=>)함수는 실행 컨텍스트를 생성할 때 바인딩 과정이 없다. 일반함수와 화살표 함수의 가장 큰 차이점은 this binding 의 여부이다.

var obj = {
    outer: function () {
        console.log(this); // (1) obj
        var innerFunc = () => {
            console.log(this); // (2) obj
        };
        innerFunc(); //함수로 호출해도 전역객체가 아닌 호출객체를 가리킴
    }
}
obj.outer();

 

화살표 함수 예외

obj 객체 안 print 메서드를 화살표 함수로 선언할 경우 this는 전역 객체를 가리킨다. 

var obj = {
    names: ["seo"],
    text: "님 안녕하세요",
    print: () => { console.log(this.text) } // undefined
}
obj.print()

 

 

4. 콜백함수 this

콜백함수도 함수이기때문에 this가 전역 객체를 가리키지만 콜백함수를 넘겨 받은 함수에서 콜백함수에 별도로 this를 지정해준 경우 예외로 그 대상을 참조한다.

 

 

별도의 지정이 없어 전역 객체를 가리킨다.

setTimeout(function () { console.log(this) }, 300);
[1, 2, 3, 4, 5].forEach(function(x) {
	console.log(this, x);
});

 

addEventListener 메서드는 콜백함수 호출 시, 자신의 this를 상속. 따라서 this는 button 을 가리킨다.

document.body.innerHTML += '<button id="a">클릭</button>';
document.body.querySelector('#a').addEventListener('click', function (e) {
    console.log(this, e);
});

 

 

5. 명시적 this 바인딩

 

자동으로 부여되는 상황별 this의 규칙을 깨고 this에 별도의 값을 저장하는 방법

call, apply, bind
call 호출 주체인 함수를 즉시 실행 첫번째 인자로 실행 컨텍스트를 인자로 전달
apply call과 동일하되 배열 형태로 넘김
bind 즉시 호출하지 않고, 함수에 this를 미리 적용하거나 부분적으로 적용  

 

 

5-1. Call 메서드

var obj = {
    string : "free",
    value : function(){
        console.log(this.string);
    },
}

var obj2 = {
    string : "not free",
}

obj.value(); //free
obj.value.call(obj2); //not free
var func = function (a, b, c) {
    console.log(this, a, b, c);
};
// no binding
func(1, 2, 3); // Window{ ... } 1 2 3

// 명시적 binding
func.call({ x: 1 }, 4, 5, 6}; // { x: 1 } 4 5 6
var obj = {
    a: 1,
    method: function (x, y) {
        console.log(this.a, x, y);
    }
};
obj.method(2, 3); // 1 2 3
obj.method.call({ a: 4 }, 5, 6); // 4 5 6

 

 

5-2. Apply 메서드

var func = function (a, b, c) {
    console.log(this, a, b, c);
};
func.apply({ x: 1 }, [4, 5, 6]); // { x: 1 } 4 5 6
var obj = {
    a: 1,
    method: function (x, y) {
        console.log(this.a, x, y);
    }
};
obj.method.apply({ a: 4 }, [5, 6]); // 4 5 6

 

 

5-3. Bind 메서드

call과는 다르게 즉시 호출하지는 않고 넘겨받은 this 및 인수들을 바탕으로 새로운 함수 를 반환하는 메서드

var func = function (a, b, c, d) {
    console.log(this, a, b, c, d);
};
func(1, 2, 3, 4); // window ... 1, 2, 3, 4

// 함수에 this 미리 적용
var bindFunc1 = func.bind({ x: 1 }); // 바로 호출X
bindFunc1(5, 6, 7, 8); // { x: 1 } 5 6 7 8

// 부분 적용 함수 구현
var bindFunc2 = func.bind({ x: 1 }, 4, 5); // 4와 5를 미리 적용
bindFunc2(6, 7); // { x: 1 } 4 5 6 7
bindFunc2(8, 9); // { x: 1 } 4 5 8 9

 

 

👀 브랜치란?

브랜치란 독립적으로 어떤 작업을 진행하기 위한 개념이다. 깃에서는 각각의 브랜치가 다른 브랜치의 영향을 받지 않기 때문에, 여러 작업을 동시에 진행할 수 있다.

브랜치를 나눠서 개발하는 이유는 여러 개발자가 하나의 저장소를 사용하는 환경에서 저장소를 효과적으로 활용하기 위함이다. 하지만 꼭 협업이 아니더라도 개인 프로젝트에서 구현할 기능이 많을 때도 각 기능별 브랜치를 나눠서 개발하기도 한다.

 


 

 

브랜치 생성

브랜치를 생성하는 명령어는 다음과 같다.

git branch [브랜치명]

 

 

브랜치로 이동하는 명령어는 다음과 같다.

git switch [브랜치명]
git checkout [브랜치명]

 

브랜치를 생성하고 생성한 브랜치로 이동하는 명령어는 다음과 같다.

git switch -c [브랜치명]
git checkout -b [브랜치명]

 

로컬/원격 저장소에 있는 브랜치 확인하는 명령어는 다음과 같다.

git branch -r : 원격저장소 브랜치 상태 확인
git branch -a : 로컬저장소 브랜치 상태 확인

 

 

브랜치 삭제 명령어는 다음과 같다.

git branch -d [브랜치명]

 

 

 

 

브랜치 업로드

변경사항을 로컬저장소의 깃에 add . -> commit 해준다.
그 다음 push는 다음 명령어를 통해 진행한다. 로컬의 깃 브랜치를 원격저장소 깃에 올리는 과정이다.

git add .
git commit -m
git push origin [브랜치명]

 

 

합치기

 

최종적으로 업로드하고자 했던 부분을 깃허브 main 브랜치에 합쳐보자

git merge origin [브랜치명]
git push origin [브랜치명]

 

하지만 실제론 최종 저장소 main 으로 merge 하는 명령어는 잘 사용하지 않는다고한다.

main에 합치기 전에 dev 라는 우선 테스트 저장소를 만들어 서로의 코드를 합쳐보는 것을 추천한다. 

 

 

여러 사람이 작업하기 때문에 각자 최종 코드를 로컬에 git pull 했을 때 충돌이 있을 수 있다. 그러니 꼭 dev 저장소를 만들어 main 전에 코드를 머지해서 충돌을 없애는 것이 좋다.

'Git & Github' 카테고리의 다른 글

깃허브 (Github) 란?  (0) 2024.04.15

 

 

🔗  이전 삽질

https://ejunyang.tistory.com/entry/TP-%EB%B0%94%EB%8B%90%EB%9D%BCJS%EB%A1%9C-%EC%BA%90%EB%9F%AC%EC%85%80%EA%B8%B0%EB%8A%A5-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0

 

[T.P] 바닐라JS로 캐러셀기능 구현하기

🔗 레퍼런스https://www.wavve.com/ Wavve(웨이브)세상 얕은 콘텐츠부터 세상 딥한 콘텐츠까지 JUST DIVE! Wavvewww.wavve.com  ✅  구현 사항1. 한 눈에 데이터 3개 노출하기 (swiper-slide)2. 버튼으로 슬라이드

ejunyang.tistory.com

 

 

 

 


✅  구현 사항

1. 한 눈에 데이터 3개 노출하기 (swiper-slide)

2. 버튼으로 슬라이드 동작 구현하기 (swipe-button-next / swipe-button-prev)

3. tmdb 데이터 가져와서 뿌리기


 

 

html

<!-- 슬라이드 영역 -->
        <div id="main-banner" class="swiper-container banner">
            <div class="main01-nav">
                <!-- prev, next -->
                <button class="swiper-button-next"></button>
                <button class="swiper-button-prev"></button>
            </div>

            <div id="wrapper" class="swiper-wrapper-banner">

            </div>
        </div>
<!-- 슬라이드 영역 -->

 

tmdb 데이터를 받아와서 dom을 생성해줄거라서 html에 원래 만들어놓은 코드는 빼고 시작! 전 코드보다 아주 많이 간결해졌다.

css는 건드린게 없어서 생략하고 바로 js 파일 수정을 해보자.

 

 

 

Javascript

//tmdb api
const options = {
    method: "GET",
    headers: {
        accept: "application/json",
        Authorization:
            "Bearer eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiI5ZDE3MGZlMGJlM2UwZDE3NzkyMGE3MDQxZmQ1NGM4NiIsInN1YiI6IjY2MjVkYTMzMjIxYmE2MDE3YzE1NDQ1ZSIsInNjb3BlcyI6WyJhcGlfcmVhZCJdLCJ2ZXJzaW9uIjoxfQ.tRZNYVownPtQj6yIFrodZCqJZfvFyuPxHjF_kH8JMyI",
    },
};

// 영화 장르 ID 정보
fetch("https://api.themoviedb.org/3/movie/popular?language=ko-KR&page=1", options)
    .then((response) => response.json())
    .then((data) => {
        let movieList = data['results'];
        initSlider(movieList);
    });

 

패치를 가져와서 정보를 movieList에 저장해주고, movieList 데이터를 인자로 받아 아래 만든 캐러셀 함수를 호출해준다. 패치 데이터 저장하는게 제일 쉽다 진짜.. 이것만 하고싶다..

 

function initSlider(movieList) {
    const wrapper = document.querySelector('.swiper-wrapper-banner')
    const prevBtn = document.querySelector(".swiper-button-prev");
    const nextBtn = document.querySelector(".swiper-button-next");

    movieList.forEach(a => {
        let slideimage = 'https://image.tmdb.org/t/p/w500' + a['poster_path'];
        let slidetitle = a['title'];
        let ogtitle = a['original_title'];
        let movieid = a['id'];
}

 

movieList 데이터를 순회해서 각 변수에 데이터 값을 할당해준다. 배너에 필요한 데이터는 이미지와 타이틀, 영문 타이틀이고, movieid는 배너를 눌렀을 때 id가 동일한 상세페이지로 이동해야하기 때문에 같이 선언해준다. 맨 위 wrapper, prevBtn, nextBtn은 따로 dom을 만들지 않고 이미 html에 있는 요소이므로 querySelector를 사용해서 가져왔다.

 

const swiper_slide = document.createElement('div');
        swiper_slide.className = 'swiper-slide';
        const img = document.createElement('img');
        img.className = 'banner-img';

        const slide_txt = document.createElement('div');
        slide_txt.className = 'slide-txt';
        const titleEl = document.createElement('h1');
        titleEl.className = 'slide-title'
        const ogtitleEl = document.createElement('p');
        ogtitleEl.className = 'slide-en-title';
        slide_txt.append(titleEl, ogtitleEl);


        img.src = slideimage;
        titleEl.innerText = slidetitle;
        ogtitleEl.innerText = ogtitle;

        swiper_slide.append(img, slide_txt);

 

이제 dom 을 만들어보자! 이 작업이 제일 신난다(?) 말 그대로 엘리먼트를 생성하고 생성한 엘리먼트에 클래스 네임을 붙여주어 만들어진 엘리먼트에 append하는 코드.. 쉽다 쉬워.. 이것만 하고싶다22 

 

const slide_txt = document.createElement('div'); 
const titleEl = document.createElement('h1'); 
const ogtitleEl = document.createElement('p');

 

배너 위에 올라가는 텍스트들은 slide-txt 안에 h1, p태그가 있는 구조인데 위처럼 엘리먼트만 생성해주면 slide_txt안에 h1, p태그가 생기는게 아니라 다 따로 생성되기 때문에 slide_txt.append(titleEl, ogtitleEl); 이걸 해줘야 slide_txt 안에 태그들이 들어간다.

 

 

이렇게 생긴다고 보면된다! 그래서 slide-txt에 css 를 주면 h1, p 태그 모두 적용이 가능하다. 배너 위에 올라가서 position : absolute; 를 주어야하는데 h1, p 태그 따로 주고싶지 않아서 append 했다.

 

swiper_slide.addEventListener("click", () => 
window.location.href = `detailed-page.html?id=${movieid}`
);
wrapper.append(swiper_slide);

 

배너를 클릭했을 때 id값이 동일한 상세페이지로 이동하게 해주고 html에 위에서 만든 dom을 뿌려주면 우선 영화 데이터 가져오기는 끝!

 

   const slideCount = 20; //array(20)
   //슬라이드 0번째에 있는 컨텐츠의 크기를 확인 => 이미지 사이즈 : 1250px / margin : 0 10px
   const size = 1270 

   //currentIndex = 1로 초기값 슬라이드[1]
   let currentIndex = 1;

   function updateSliderPosition() {
   	wrapper.style.transform = `translateX(${-size * currentIndex + 70}px)`; //-1270  * 1 + 70
}

 

다음은 슬라이드가 움직이도록 만들어보자. 우선 내가 가져온 영화의 수는 20개라서 slideCount도 동일하게 값을 주었다. 사이즈는 배너의 크기를 저장하는 변수로 이미지 사이즈 1250px에 margin 사이드 10px씩 더하면 메인 화면에 보이는 사이즈는 1270px 이다.

아래 +70은 메인 배너 사이드로 보이는 다음 배너와 이전배너가 조금씩 보여야하기 때문에 준 값이다.

 

function goToSlide(index) {
            wrapper.style.transition = "0.3s ease";
            //인덱스가 범위를 벗어 나는지 확인
            //노출되는 슬라이드
            if (index < 0) {
                currentIndex = slideCount - 1;
            } else if (index >= slideCount) {
                currentIndex = 0;
            } else {
                currentIndex = index;
            }
            updateSliderPosition();
        }

        //슬라이드 무한루프
        wrapper.addEventListener("transitionend", () => {
            // currentIndex가 마지막일 인덱스일 경우
            if (currentIndex === slideCount - 1) {
                //첫번째 인덱스로 돌아감
                currentIndex = 1;
                wrapper.style.transition = "0s";
                wrapper.style.transform = `translateX(${-size * currentIndex + 70}px)`;
            }
            // 첫번째 인덱스일 경우
            if (currentIndex === 0) {
                // 마지막 슬라이드 이전 슬라이드
                currentIndex = slideCount - 2;
                wrapper.style.transition = "0s";
                wrapper.style.transform = `translateX(${-size * currentIndex + 70}px)`;
            }
        });

        updateSliderPosition();

        nextBtn.addEventListener("click", () => goToSlide(currentIndex + 1));
        prevBtn.addEventListener("click", () => goToSlide(currentIndex - 1));
    });

 

데이터를 불러오기 전과 다른 점은 변수만 달라졌다는 것! 데이터가 할당된 변수로만 바꿔줬다. 

 


 

 

🔥 완성

 

흠이라면.. tmdb에서 제공하는 이미지의 화질이 좋지 않다는 것 .. img를 100% 채웠더니 다 깨진다 .. 영화진흥위원회 API를 사용해도된다고 했었는데 여긴 이미지 자체를 제공하지 않아서 기존에 작업하던 tmdb로 작업하라고 했다. 새로운 api를 사용할 수 있는 기회였는데 아쉽지만 차라리 잘됐다(?) 처음부터 시작하는 것보다 내가 원래 하던걸 제대로 마무리 하는게 나으니께 후후 "오늘도 나는 성장했다" 재훈이가 맨날 ㅋㅋㅋㅋ 오류 해결하고 하는 말인데 왠지 모르게 웃기면서도 뭔가 진짜 성장하는 것 같은 느낌이 든다..! 앞으로 나도 자주 써야할 듯~ㅋㅋ

 

🔗 레퍼런스

https://www.wavve.com/

 

Wavve(웨이브)

세상 얕은 콘텐츠부터 세상 딥한 콘텐츠까지 JUST DIVE! Wavve

www.wavve.com

 


 

✅  구현 사항

1. 한 눈에 데이터 3개 노출하기 (swiper-slide)

2. 버튼으로 슬라이드 동작 구현하기 (swipe-button-next / swipe-button-prev)

 


 

html

<!-- 슬라이드 영역 -->
            <div id="main-banner" class="swiper-container banner">
                <div class="main01-nav">

                    <!-- bullet -->
                    <div class="swiper-pagination swiper-pagination-bullets">
                        <span class="swiper-pagination-bullet"></span>
                        <span class="swiper-pagination-bullet"></span>
                        <span class="swiper-pagination-bullet"></span>
                        <span class="swiper-pagination-bullet"></span>
                        <span class="swiper-pagination-bullet"></span>
                    </div>

                    <!-- prev, next -->
                    <button class="swiper-button-next"></button>
                    <button class="swiper-button-prev"></button>
            
                </div>

                <div class="swiper-wrapper-banner">

                    <div class="swiper-slide">
                        <div class="slide-txt">
                            <h1>제목</h1>
                            <p>아웃라인 텍스트</p>
                            <p>텍스트</p>
                        </div>
                        <img src="assets/main5.png" alt="banner">
                    </div>
                    <div class="swiper-slide">
                        <div class="slide-txt">
                            <h1>제목</h1>
                            <p>아웃라인 텍스트</p>
                            <p>텍스트</p>
                        </div>
                        <img src="assets/main1.png" alt="banner">
                    </div>

                    <div class="swiper-slide">
                        <div class="slide-txt">
                            <h1>제목</h1>
                            <p>아웃라인 텍스트</p>
                            <p>텍스트</p>
                        </div>
                        <img src="assets/main2.png" alt="banner">
                    </div>

                    <div class="swiper-slide">
                        <div class="slide-txt">
                            <h1>제목</h1>
                            <p>아웃라인 텍스트</p>
                            <p>텍스트</p>
                        </div>
                        <img src="assets/main3.png" alt="banner">
                    </div>

                    <div class="swiper-slide">
                        <div class="slide-txt">
                            <h1>제목</h1>
                            <p>아웃라인 텍스트</p>
                            <p>텍스트</p>
                        </div>
                        <img src="assets/main4.png" alt="banner">
                    </div>

                    <div class="swiper-slide">
                        <div class="slide-txt">
                            <h1>제목</h1>
                            <p>아웃라인 텍스트</p>
                            <p>텍스트</p>
                        </div>
                        <img src="assets/main5.png" alt="banner">
                    </div>

                    <div class="swiper-slide">
                        <div class="slide-txt">
                            <h1>제목</h1>
                            <p>아웃라인 텍스트</p>
                            <p>텍스트</p>
                        </div>
                        <img src="assets/main1.png" alt="banner">
                    </div>
                </div>
            </div>

 

아직 슬라이드 안 텍스트들은 데이터 값을 받아온 상태가 아니라서 임의로 만들어놓았다. 캐러셀은 항상 api를 가져와서 사용했었는데 막상 직접 만드려고하니 머리가 띵했다.. 근데 어떻게.. 해야지.. 상단 구조를 잡아놓고 시작

swiper-container / banner : 최상위 클래스로 캐러셀의 전체 구조
swiper-wrapper-banner : 캐러셀 슬라이드의 전체 구조
swiper-slide : 캐러셀 이미지를 설정
swipe-button-prev / swipe-button-next : 캐러셀 사이드 버튼 설정

 

 

css

/* 슬라이드 */
.banner { 
    width: 100%;
    overflow: hidden;
    margin: 0 auto 80px;
    position: relative;
    min-width: 1250px;
    max-width: 3840px;
    min-height: 555px;
  }
  
  .banner .main01-nav {
    display: table;
    position: absolute;
    bottom: 5%;
    left: 50%;
    transform: translate(-50%, -50%);
    text-align: center;
    z-index: 2;
}
  
  .banner .main01-nav button[class^="btn"] {
    display: table-cell;
    width: 34px;
    height: 34px;
    vertical-align: middle;
  }
 

  .banner .swiper-pagination { /* pagination */
    display: table-cell;
    position: static;
    width: auto;
    font-size: 0;
    vertical-align: middle;
  }
  
  .swiper-pagination {
    position: absolute;
    text-align: center;
    transition: opacity 0.3s;
    z-index: 10;
  }
  

  .banner .swiper-button-prev {
    right: 500px;
    background-image: url(../assets/prev.png);
  }
  
  .banner .swiper-button-next,
  .banner .swiper-button-prev {
    position: absolute;
    top: -300px;
    z-index: 20;
    background-repeat: no-repeat;
    width: 100px;
    height: 100px;
    background-color: transparent;
    background-size: 100px auto;
    font-size: 0;
  }
  
  .swiper-button-next,
  .swiper-button-prev {
    position: absolute;
    top: 50%;
    z-index: 50;
    cursor: pointer;
    background-position: 50%;
    background-repeat: no-repeat;
  }
  
  .banner .swiper-button-next {
    left: 500px;
    background-image: url(../assets/next.png);
  }

 

우선 슬라이드에 pagination 슬라이드 이미지 가운데 배치 시키고 backgroun-image로 이전/다음 버튼을 넣어주었다. 

 

.swiper-slide > img {
    width: 100%;
  }
  
  .swiper-wrapper-banner {
    position: relative;
    width: 100%;
    height: 100%;
    z-index: 1;
    display: flex;
    box-sizing: content-box;
    transition: 0.3s ease-in-out;
  }
  
  .banner .swiper-slide {
    float: left;
    position: relative;
    overflow: hidden;
    width: 1250px;
    padding: 0 10px;
    border-radius: 12px;
  }
  
  .swiper-slide {
    flex-shrink: 0;
    width: 100%;
    height: 100%;
    position: relative;
  }


  .slide-txt{
    position: absolute;
    top:75%;
    left: 15%;
    transform: translate(-15%, -50%);
    color:#fff;
    font-size: 40px;
    line-height: 1.5em;
    font-weight: bolder;
  }

 

display : flex 로 슬라이드들을 가로로 정렬해주고 슬라이드의 가로 사이즈는 1250px로 맞춰주었다. 슬라이드마다 텍스트를 띄우기 위해 slide-txt가 들어가 있는 swiper-slide에 position:relative를 주고 왼쪽 아래 배치해 주었다.

 

Javascript

const sliderContainer = document.querySelector(".swiper-container");
const sliderWrapper = sliderContainer.querySelector(".swiper-wrapper-banner");
const slides = sliderWrapper.querySelectorAll(".swiper-slide");

const prevBtn = sliderContainer.querySelector(".swiper-button-prev");
const nextBtn = sliderContainer.querySelector(".swiper-button-next");
const pagination = sliderContainer.querySelector(".swiper-pagination");

 

필요한 요소들을 변수에 저장해준다. .swiper-slide는 배열로 가지고 올거기때문에 querySelectorAll 로 가지고 오자!

 

const slideCount = slides.length;
const size = slides[0].clientWidth; 
let currentIndex = 1;

 

slideCount에는 swiper-slide의 길이를 저장해주고, size는 슬라이드 0번째에 있는 컨텐츠의 크기를 확인할 수 있는 변수이다. slide의 사이즈는 css에서 1250px로 정했으니 size = 1250px이다.

currentIndex는 현재 위치를 저장하기 위한 변수이고 1번째 이미지를 메인으로 하기 위해 초기값을 1로 설정했다.

 

function updateSliderPosition() {
    sliderWrapper.style.transform = `translateX(${-size * currentIndex + 80}px)`; 
}

 

메인 배너가 배치되는 위치를 조정하는 함수로 updateSliderPosition()을 만들고 위치 값으로 슬라이드 사이즈와 현재 위치에 + 80px한 값을 넣어주었다. size = 1250px / currentIndex = 1 / + 80 으로 -1170 값이 나오는데 이 값은 처음 메인에 3개의 배너가 노출이 되어야 하기때문에 사이드에도 배너가 조금 보일 수 있게 밀어준 값이라고 생각하면 된다.

 

 

개발자 도구로 보면 이렇게 transform 으로 밀려있는걸 볼 수 있다!

 

function goToSlide(index) {
            sliderWrapper.style.transition = "0.3s ease";
            if (index < 0) {
                currentIndex = slideCount - 1;
            } else if (index >= slideCount) {
                currentIndex = 0;
            } else {
                currentIndex = index;
            }
            console.log(index);

            updateSliderPosition();
        }

 

다음으로 만들어야할 건 슬라이드를 움직이게 해주는 함수! 인덱스가 범위를 벗어나는지 확인하고 어떤 슬라이드가 노출되는지 조정한다. 이미지 슬라이드의 길이(이미지 장수)보다 커지면 안되므로 슬라이드에 포함된 이미지의 개수만큼만 작동할 수 있도록 인덱스가 슬라이드의 길이보다 크면 0으로 만들도록 했다.

 

//슬라이드 무한루프
        sliderWrapper.addEventListener("transitionend", () => {
            // currentIndex가 마지막일 인덱스일 경우
            if (currentIndex === slides.length - 1) {
                //첫번째 인덱스로 돌아감
                currentIndex = 1;
                sliderWrapper.style.transition = "0s";
                sliderWrapper.style.transform = `translateX(${-size * currentIndex + 80}px)`;
            }
            // 첫번째 인덱스일 경우
            if (currentIndex === 0) {
                // 마지막 슬라이드 이전 슬라이드
                currentIndex = slides.length - 2;
                sliderWrapper.style.transition = "0s";
                sliderWrapper.style.transform = `translateX(${-size * currentIndex + 80}px)`;
            }
        });

 

이제 슬라이드가 무한으로 돌아가는 루프를 만들어보자. 슬라이드의 이미지가 마지막에 도달했을 때 인덱스를 조정하는 무한 루프 함수를 만들었다. transitionend 이벤트를 사용해서 만들어보았다


✏️ transitionend

transitionend 이벤트는 CSS transition 이 완료되면 발생한다.
transition 속성이 제거되거나 display가 none으로 설정된 경우와 같이 완료 전에 
transition이 제거된 경우에는 이벤트가 생성되지 않는다.

 

currentIndex가 마지막일 인덱스일 경우 슬라이드의 길이에서 -1 한 값과 현재 위치가 같다면 처음 인덱스로 돌아가도록한다. 이때 transition을 0s로 해서 아무런 애니메이션 효과가 없도록한다. 

첫번째 인덱스일 경우 마지막 슬라이드가 첫번째의 이전 슬라이드가 되도록 슬라이드 길이에서 -2를 해준다. 

 

nextBtn.addEventListener("click", () => goToSlide(currentIndex + 1));
prevBtn.addEventListener("click", () => goToSlide(currentIndex - 1));

 

마지막으로 다음 버튼과 이전버튼에 이벤트 리스너를 달면 완성이다. 중간에 막히긴 했는데 첫번째 슬라이드 이미지 = 마지막 슬라이드 이미지를 넣고 마지막 슬라이드 이미지 = 첫번째 슬라이드 이미지를 넣으니까 해결 완료.. 마지막에 갔다가 다시 맨 처음으로 후리리릭 가는게 싫어서 참고사이트를 보고 한 꼼수다 후후.. 왜 이렇게 다들 잘할까.. 난..? 내일은 배너에 실제 api 데이터를 가지고 와야하는데 나 잘할 수 있게찌..

 

 

 

🔗 참고사이트

https://velog.io/@wjddnjswjd12/javascript%EB%A1%9C-carousel-slide-%EA%B5%AC%ED%98%84%ED%95%B4%EB%B3%B4%EA%B8%B0

 

javascript로 carousel slide 구현해보기

우선 html 코드와 css는 이런 상태로 시작했습니다: image연습용이라 css를 대충 지정했습니다..😂일단 slide_box에 overflow:hidden을 주지 않고 진행이 어떻게되나 확인하면서 시작했습니다.overflow:hidden

velog.io

https://velog.io/@reasonz/2022.05.23-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%BA%90%EB%9F%AC%EC%85%80-%EC%8A%AC%EB%9D%BC%EC%9D%B4%EB%93%9C-%EB%A7%8C%EB%93%A4%EA%B8%B0

 

[2022.05.23] 자바스크립트 캐러셀 슬라이드 만들기

그동안 공부한 내용을 바탕으로 직접 이미지 슬라이드를 만들어보기로 했다. 다음/이전 버튼을 누르면 이미지가 슬라이드되는 방식이다.먼저 html 구조는 이렇게 짰다.전체 슬라이드를 감싸서 ov

velog.io

 


https://ejunyang.tistory.com/entry/PP-TMDB-api-%EC%82%AC%EC%9A%A9%ED%95%B4-%EC%98%81%ED%99%94-%EB%AA%A9%EB%A1%9D-%EA%B0%80%EC%A0%B8%EC%98%A4%EA%B8%B0

 

[P.P] TMDB api 사용해 영화 목록 가져오기

https://ejunyang.tistory.com/entry/PP-TMDBThe-Movie-DB-api-%EC%82%AC%EC%9A%A9 [P.P] TMDB(The Movie DB) api 사용🚩 영화 검색 사이트 구현 Javascript과정을 마무리하며, JS 문법의 핵심을 적용해 볼 수 있는 영화 검색 사이

ejunyang.tistory.com


 

✅  필수 사항

1. jQuery 라이브러리 사용없이 순수 바닐라 자바스크립트 사용하기

2. TMDB 오픈 API를 이용하여 인기영화 데이터 가져오기

3. 영화정보 카드 리스트 UI 구현

- 카드에는 title(제목), overview(내용 요약), poster_path(포스터 이미지 경로), vote_average(평점) 이렇게 4가지 정보가 필수

- 카드 클릭 시에는 클릭한 영화 id 를 나타내는 alert 창을 띄우기

 

4. 영화 검색 UI 구현

5. Javascript 문법 요소를 이용하여 구현

- const와 let만을 이용한 변수 선언 필수

- 화살표 함수

- 배열 메소드 : 하기 예시 중 2개 이상 사용

  • forEach
  • map
  • filter
  • reduce
  • find

- DOM 제어하기 : 아래 api 목록 중 2개 이상 사용하기

document.createElement(tagName) //새로운 HTML 요소를 생성합니다.
document.getElementById(id) //id 속성을 기준으로 요소를 선택합니다.
document.getElementsByTagName(name) //태그 이름을 기준으로 요소를 선택합니다.
document.getElementsByClassName(name) //클래스 이름을 기준으로 요소를 선택합니다.
document.querySelector(selector) //CSS 선택자를 이용하여 요소를 선택합니다.
document.querySelectorAll(selector) //CSS 선택자를 이용하여 모든 요소를 선택합니다.
element.innerHTML //해당 요소 내부의 HTML 코드를 변경합니다.
element.textContent //해당 요소 내부의 텍스트를 변경합니다.
element.setAttribute(attr, value) //해당 요소의 속성 값을 변경합니다.
element.getAttribute(attr) //해당 요소의 속성 값을 가져옵니다.
element.style.property //해당 요소의 스타일 값을 변경합니다.
element.appendChild(child) //해당 요소의 하위 요소로 child를 추가합니다.
element.removeChild(child) //해당 요소의 하위 요소 중 child를 삭제합니다.
element.classList.add(class) //해당 요소의 클래스에 새로운 클래스를 추가합니다.
element.classList.remove(class) //해당 요소의 클래스 중에서 특정 클래스를 제거합니다.
element.classList.toggle(class) //해당 요소의 클래스 중에서 특정 클래스를 추가 또는 제거합니다.
element.addEventListener(type, listener) //해당 요소에서 이벤트가 발생했을 때 호출할 함수를 등록합니다.
element.removeEventListener(type, listener) //해당 요소에서 등록된 함수를 제거합니다.
event.preventDefault() //이벤트가 발생했을 때 기본 동작을 취소합니다.
event.stopPropagation() //이벤트의 버블링을 방지하기 위해 이벤트 전파를 중지합니다.
window.location.href //현재 페이지의 URL을 가져옵니다.
window.alert(message) //경고 메시지를 출력합니다.
window.confirm(message) //확인 메시지를 출력하고 사용자의 답변에 따라 Boolean 값을 반환합니다.

 


 

 

🔥 완성

 

각 영화 카드를 눌렀을 때 고유 id가 alert 뜨기도 했고, 영화 제목을 검색했을 때 해당 영화만 뜨도록 구현도 완료했다!

순수 바닐라는 너무 오랜만이고 실무에서도 제이쿼리만 쓰다보니 너무 헷갈리고 메서드도 잘 기억이 안난다

그래서 요즘은 알고리즘 문제들만 주구장창 푸는 중이다. 풀다보니 메서드 기억이 새록새록 올라와서 요즘 꽤 재미 붙이고있다.

 

 


 

👀 영화 검색하기

function searchMovies() {

    const mycards = document.querySelector('#mycards'); //카드 품은 wrap
    const movieCard = mycards.querySelectorAll('.col'); //카드
    const searchInput = document.querySelector('#searchInput'); //입력칸
    const searchBtn = document.querySelector("#searchBtn"); //검색버튼

}

 

사용자가 검색한 영화 제목이 포함되어있지 않은 카드들은 display:none; 하는 코드를 짜봤다. 우선, dom요소들을 가져오고 각 변수에 선언해준다. 검색 기능이 아예 감도 안잡힐 때 🧑🏻‍🦱은채 튜터님한테 물어봤는데 querySelector로 html 요소들을 가지고와서 작업하면 편리하다고 말씀해주셨다. 전에는 주구장창 getElementById만 써서 특정 아이디가 아니면 동작을 안해서 골머리를 썼는데.. 

 

function searchHandle(e){
        e.preventDefault();
        let userInput = searchInput.value;

        movieCard.forEach((el) => {
            el.classList.remove('hidden');
            let movieTitle = el.getElementsByTagName('h2')[0].innerText;
            if (!movieTitle.toLowerCase().includes(userInput)) {
                el.classList.add("hidden");
            }
        })
    }

 

let userInput = searchInput.value;

우선 검색 버튼을 눌렀을 때 실행하는 이벤트 핸들러를 만들어주고 userInput 변수에 사용자가 입력한 값을 할당해준다. 

 

movieCard.forEach((el) => {}

forEach문으로 이미 만들어진 무비 카드들에서 사용자가 입력한 값과 영화 제목이 일치하면 일치한 영화는 제외하고 나머지 카드들은 hidden 클래스는 add하면 된다.

 

let movieTitle = el.getElementsByTagName('h2')[0].innerText;

각 카드 안 <h2>태그의 0번째 텍스트를 movieTitle 변수에 할당해준다. 

 

<div class="col">
        <img src=${image} class="card-img-top" alt="포스터">
        <div class="card-body">
            <h2 class="card-title">${title}</h2>
            <p class="card-text">${overview}</p>
            <p class="card-vote">${vote}</p>
        </div>
    </div>

 카드가 위 구조로 짜여져 있다. <h2>태그는 .card-title 로 각 카드의 영화 제목을 담고있다.

 

if (!movieTitle.toLowerCase().includes(userInput)) {
   el.classList.add("hidden");
}

그리고 toLowerCase()로 대소문자 관계없이 값을 받을 수 있도록 하고, 사용자가 입력한 값과 영화 제목이 일치하지 않을 경우 카드를 모두 숨겨준다. hidden 클래스는 css파일에 미리 만들어두고, 간편하게 classList로 추가했다가 삭제했다. 

 

searchBtn.addEventListener("click", searchHandle);

마지막으로 검색 버튼에 이벤트 리스너를 붙여 클릭했을 때 위에 생성한 이벤트 핸들러가 동작하게 해주면 끝 !!

 

 


 

 

 if (movieTitle === movieTitleArr[i]) { // 배열 === 스트링 false
    document.getElementById('swipe').style = 'display:none';
    document.getElementById('title-area').style = 'display:none';
    movieArr[i].style = 'display:block';
}

처음 코드는 이렇게 짰었는데 피드백을 받고 위에 설명한 코드대로 수정했다. 이 코드는 특정 아이디 값의 html 요소에 직접적으로 style을 먹여줬다. 피드백받은 사항 중 하나였고 다시보니 코드가 그리 깨끗해 보이진 않는 것 같다.

구문

자바스크립트의 reduce함수는 배열의 각 요소를 순회하며 callback함수의 실행 값을 누적하여 하나의 결과값을 반환한다.

 

파라미터

callback function

- 다음 4가지의 인수를 가진다.

accumulator  (=acc) accumulator는 callback함수의 반환값을 누적
currentValue (=cur) 배열의 현재 요소
index(Optional) 배열의 현재 요소의 인덱스
array(Optional) 호출한 배열

 

- callback함수의 반환 값은 accumulator에 할당되고 순회중 계속 누적되어 최종적으로 하나의 값을 반환

 

nitialValue(Optional)

최초 callback함수 실행 시 accumulator 인수에 제공되는 값, 

초기값을 제공하지 않을경우 배열의 첫 번째 요소를 사용하고, 빈 배열에서 초기값이 없을 경우 에러가 발생

 

반환 값

배열을 순서대로 불러 각 요소에 대해 callback 함수을 실행한 결과를 누적한 값

 


 

✏️ 예제

 

👀  배열 값 전부 더하기

let arr = [55, 12, 65, 36];
const sum = arr.reduce((acc, cur) => acc + cur);

console.log(sum); //168
let arr = [55, 12, 65, 36];

function reduceFunc(acc, cur){
	return acc + cur;
}

const sum = arr.reduce(reduceFunc);
console.log(sum); // 168

 

👀  원하는 값만 더하기 

const users =  //배열 객체 생성
[ 
  {
    name: 'Anna',
    age: 25,
    job: 'student',
  },
  {
    name: 'Ori',
    age: 38,
    job: 'doctor',
  },
  {
    name: 'June',
    age: 33,
    job: 'ceo',
  }
];


const sum = users.reduce((acc, cur) => {
	acc + cur.age //현재 값에 age 만 가져오기
}, 0); // 초기값 필수!

console.log(sum); //96

 

👀 배열 비교하기

두 배열의 길이가 다르다면, 배열의 길이가 긴 쪽이 더 큽니다.
배열의 길이가 같다면 각 배열에 있는 모든 원소의 합을 비교하여 다르다면 
더 큰 쪽이 크고, 같다면 같습니다.

두 정수 배열 arr1과 arr2가 주어질 때, 위에서 정의한 배열의 대소관계에 대하여 
arr2가 크다면 -1, arr1이 크다면 1, 두 배열이 같다면 0을 return 하는 solution 함수를 작성해 주세요.
arr1 arr2 result
[49, 13] [70, 11, 2] -1
[100, 17, 84, 1] [55, 12, 65, 36] 1
[1, 2, 3, 4, 5] [3, 3, 3, 3, 3] 0

 

function solution(arr1, arr2) {
    const length1 = arr1.length;
    const length2 = arr2.length;
    if(length1 !== length2) return length1 > length2 ? 1 : -1 
    //삼항연산자
    //arr1.length와 arr2.length 길이가 다를 때 arr1.length 길면 1 반환 arr2.length 길면 -1 반환

    const sum1 = arr1.reduce((acc, cur) => acc+cur, 0) 
    const sum2 = arr2.reduce((acc, cur) => acc+cur, 0)
    //arr1, arr2 배열의 요소를 모두 합친 값을 각 변수에 저장
    if(sum1 === sum2) return 0 //각 배열의 합친 값이 같을 떄 0 반환
    return sum1 > sum2 ? 1: -1 //합친 값이 arr1이 더 클 경우 1 반환 아닐경우  -1 반환
}

 

 

 

🔥 정렬의 sort() 함수

배열을 상대로 sort()함수를 사용하면 오름차순으로 정렬된다.

[7,2,5,9].sort();
//[2,5,7,9]

 

배열 내 값들을 재배치하고 정렬된 배열을 다시 반환한다.

let num = [3,2,1,];
let sortNum = num.sort();
console.log(num, sortNum);
//[ 1, 2, 3 ] [ 1, 2, 3 ]

 

 

'-'(마이너스) 가 들어갔다고해서 음수가 아니라 배열 안에서는 그저 문자일 뿐이다.

그래서 정렬 전 내부적으로 문자열로 변환하곤하는데 이러한 부분때문에 숫자 배열을 정렬할 때 예상치 못한 결과 값이 나올 수 있다. 

[-3, 2, 0, 1, 3, -2, -1].sort();
// [-1, -2, -3, 0, 1, 2, 3]

 


 

구문

 

매개변수

compareFunction  정렬 순서를 정의하는 함수. 생략하면 배열은 각 요소의 문자열 변환에 따라 각 문자의 유니 코드 코드 포인트 값에 따라 정렬된다.
 

반환값

정렬한 배열. 원 배열이 정렬되는 것에 유의하세요. 복사본이 만들어지는 것이 아님.

 

 


 

sort()  규칙

첫 번째 인자가 두 번째 인자보다 작으면 음수를 반환
첫 번째 인자가 두 번째 인자보다 크면 양수를 반환
첫 번째 인자가 두 번째 인자와 같으면 0을 반환

 

오름차순으로 정렬하기 위해서는 첫번째 인자에서 두번째 인자를 빼준다.

[-3, 2, 0, 1, 3, -2, -1].sort((a, b) => a - b);
// [-3, -2, -1, 0, 1,  2,  3]

 

내림차순은 반대로 a-b 를 b-a로 바꿔주면 끝!

[-3, 2, 0, 1, 3, -2, -1].sort((a, b) => b - a);
// [3, 2, 1, 0, -1, -2, -3]

 


 

 

객체 배열 정렬

const user = [
  { no: 1, grade: "A", name: "July" },
  { no: 2, grade: "B", name: "Anna" },
  { no: 3, grade: "C", name: "Tom" },
  { no: 4, grade: "D", name: "May" },
  { no: 5, grade: "F", name: "Alice" },
];

 

user 배열을 하나 생성하고 오름차순 내림차순으로 정렬해보자.

 

no 기준으로 정렬

user.sort(function (a, b) {
    if (a.no > b.no) {
      return 1;
    }
    if (a.no < b.no) {
      return -1;
    }
    // a must be equal to b
    return 0;
  });

 

 


 

✏️ 예제

var stringArray = ["Blue", "Humpback", "Beluga"];
var numericStringArray = ["80", "9", "700"];
var numberArray = [40, 1, 5, 200];
var mixedNumericArray = ["80", "9", "700", 40, 1, 5, 200];

function compareNumbers(a, b) {
  return a - b;
}

console.log("Sorted:", stringArray.sort());
결과값 Sorted: [ 'Beluga', 'Blue', 'Humpback' ]

 

var stringArray = ["Blue", "Humpback", "Beluga"];
var numericStringArray = ["80", "9", "700"];
var numberArray = [40, 1, 5, 200];
var mixedNumericArray = ["80", "9", "700", 40, 1, 5, 200];

function compareNumbers(a, b) {
  return a - b;
}

console.log(
    "Sorted with compareNumbers:",
    numericStringArray.sort(compareNumbers),
  );
결과값 Sorted with compareNumbers: [ '9', '80', '700' ]

 

 

 

 

 

🔥 slice() 메서드로 특정 범위 요소 자르기

slice() 메서드는 어떤 배열의 begin 부터 end 까지(end 미포함)에 대한 얕은 복사본을 새로운 배열 객체로 반환한다.

 

구문

 

매개변수

begin 0을 시작으로 하는 추출 시작점에 대한 인덱스를 의미, slice(-2) 는 배열에서
마지막 두 개의 엘리먼트를 추출하고

begin이 undefined인 경우에는, 0번 인덱스부터 slice 한다. begin이 배열의 길이보다 큰 경우에는, 빈 배열을 반환
end 추출을 종료 할 0 기준 인덱스, slice 는 end 인덱스를 제외하고 추출하고 end가 생략되면 
slice()는 배열의 끝까지(arr.length) 추출

 

반환값

추출한 요소를 포함한 새로운 배열

 


✏️ 예제

const colors = ["red", "green", "blue", "orange", "yellow"];
const slicedColors = colors.slice(1, 3);

//[green, blue, orange]
const numbers = [1, 2, 3, 4, 5];

// 배열의 처음 3개 요소를 추출합니다.
const firstThree = numbers.slice(0, 3);

console.log(firstThree); // 출력: [1, 2, 3]

// 배열의 마지막 2개 요소를 추출합니다.
const lastTwo = numbers.slice(-2);

console.log(lastTwo); // 출력: [4, 5]
const num_list = [5,4,3,7,2,9,1,8];

function solution(num_list){
    return num_list.sort((a,b) => a-b).slice(0, 5);
    // 배열 처음부터 5번째까지 출력
}

 


https://ejunyang.tistory.com/entry/PP-TMDBThe-Movie-DB-api-%EC%82%AC%EC%9A%A9

 

[P.P] TMDB(The Movie DB) api 사용

🚩 영화 검색 사이트 구현 Javascript과정을 마무리하며, JS 문법의 핵심을 적용해 볼 수 있는 영화 검색 사이트를 제작합니다. 영화정보 오픈API인 TMDB(The Movie DB)를 사용합니다. TMDB API문서 https://dev

ejunyang.tistory.com


 

✅  필수 사항

1. jQuery 라이브러리 사용없이 순수 바닐라 자바스크립트 사용하기

2. TMDB 오픈 API를 이용하여 인기영화 데이터 가져오기

3. 영화정보 카드 리스트 UI 구현

- 카드에는 title(제목), overview(내용 요약), poster_path(포스터 이미지 경로), vote_average(평점) 이렇게 4가지 정보가 필수

- 카드 클릭 시에는 클릭한 영화 id 를 나타내는 alert 창을 띄우기

 

4. 영화 검색 UI 구현

5. Javascript 문법 요소를 이용하여 구현

- const와 let만을 이용한 변수 선언 필수

- 화살표 함수

- 배열 메소드 : 하기 예시 중 2개 이상 사용

  • forEach
  • map
  • filter
  • reduce
  • find

- DOM 제어하기 : 아래 api 목록 중 2개 이상 사용하기

document.createElement(tagName) //새로운 HTML 요소를 생성합니다.
document.getElementById(id) //id 속성을 기준으로 요소를 선택합니다.
document.getElementsByTagName(name) //태그 이름을 기준으로 요소를 선택합니다.
document.getElementsByClassName(name) //클래스 이름을 기준으로 요소를 선택합니다.
document.querySelector(selector) //CSS 선택자를 이용하여 요소를 선택합니다.
document.querySelectorAll(selector) //CSS 선택자를 이용하여 모든 요소를 선택합니다.
element.innerHTML //해당 요소 내부의 HTML 코드를 변경합니다.
element.textContent //해당 요소 내부의 텍스트를 변경합니다.
element.setAttribute(attr, value) //해당 요소의 속성 값을 변경합니다.
element.getAttribute(attr) //해당 요소의 속성 값을 가져옵니다.
element.style.property //해당 요소의 스타일 값을 변경합니다.
element.appendChild(child) //해당 요소의 하위 요소로 child를 추가합니다.
element.removeChild(child) //해당 요소의 하위 요소 중 child를 삭제합니다.
element.classList.add(class) //해당 요소의 클래스에 새로운 클래스를 추가합니다.
element.classList.remove(class) //해당 요소의 클래스 중에서 특정 클래스를 제거합니다.
element.classList.toggle(class) //해당 요소의 클래스 중에서 특정 클래스를 추가 또는 제거합니다.
element.addEventListener(type, listener) //해당 요소에서 이벤트가 발생했을 때 호출할 함수를 등록합니다.
element.removeEventListener(type, listener) //해당 요소에서 등록된 함수를 제거합니다.
event.preventDefault() //이벤트가 발생했을 때 기본 동작을 취소합니다.
event.stopPropagation() //이벤트의 버블링을 방지하기 위해 이벤트 전파를 중지합니다.
window.location.href //현재 페이지의 URL을 가져옵니다.
window.alert(message) //경고 메시지를 출력합니다.
window.confirm(message) //확인 메시지를 출력하고 사용자의 답변에 따라 Boolean 값을 반환합니다.

 


 

🦴 와이어 프레임

와이어 프레임으로 기획부터 하고 대충 어디에 뭘 가져다 놓을껀지 정해봤다

웨이브를 레퍼로 삼아서 했는데 결과물은 깔끔하게 나온 것 같다

 


 

TMDB api 페이지에 뿌리기

 

1. api 가져오기

패치를 실행했을 때 console창에서 results에 데이터가 저장되어있는지 확인할 수 있다.

const options = {
  method: 'GET',
  headers: {
    accept: 'application/json',
    Authorization: 'Bearer eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiI5ZDE3MGZlMGJlM2UwZDE3NzkyMGE3MDQxZmQ1NGM4NiIsInN1YiI6IjY2MjVkYTMzMjIxYmE2MDE3YzE1NDQ1ZSIsInNjb3BlcyI6WyJhcGlfcmVhZCJdLCJ2ZXJzaW9uIjoxfQ.tRZNYVownPtQj6yIFrodZCqJZfvFyuPxHjF_kH8JMyI'
  }
};

fetch('https://api.themoviedb.org/3/movie/popular?language=en-US&page=1', options)
  .then(response => response.json())
  .then(response => console.log(response))
  .catch(err => console.error(err));

 

2. movieList 변수에 영화 results 넣고, forEach 구문으로 순회해서 각 변수에 데이터 할당하기

// 영화 데이터 조회
fetch('https://api.themoviedb.org/3/movie/popular?language=ko-KR&page=1', options)
    .then(response => response.json())
    .then((data) => {
        let movieList = data['results'];
        const container = document.querySelector('#mycards')
        const movieArr = container.querySelectorAll('.col');

        let templete = ``; // const 하지말것, 재할당 불가
        movieList.forEach(a => {
            let image = 'https://image.tmdb.org/t/p/w500' + a['poster_path'];
            let title = a['title'];
            let overview = a['overview'];
            let vote = a['vote_average'].toFixed(1); // 소수점 1자리수까지 노출
            let movieid = a['id'];
 
 });

 

3. 카드 템플릿 생성

// 카드 템플릿 생성
            templete += `
            <div class="col">
            <a href=${movieid}>
                <img src=${image} class="card-img-top">
                 <div class="card-body">
                    <h2 class="card-title">${title}</h2>
                    <p class="card-text">${overview}</p>
                    <p class="card-vote">★ ${vote}</p>
                 </div>
             </a>
            </div>`;

 

3-1. 새로운 html 요소를 생성

(document.createElement)하고 생성한 태그에 클래스명(element.className)을 줘서 dom을 만드는 방법도 있다

const card = document.createElement('div');
            card.className = 'col';
            const img = document.createElement('img');
            img.className = 'card-img-top';
            const titleEl = document.createElement('h2');
            titleEl.className = 'card-title'
            const overviewEl = document.createElement('p');
            overviewEl.className = 'card-text';
            const voteEl = document.createElement('p');
            voteEl.className = 'card-vote';


            img.src = image;
            titleEl.innerText = title;
            overviewEl.innerText = overview;
            voteEl.innerText = vote;

            card.append(img, titleEl, overviewEl, voteEl);

            document.getElementById('mycards').append(card);

 

4. 만들어진 템플릿 html 에 붙여주기

document.getElementById('mycards').innerHTML = templete;

+ Recent posts