9주차 01.25(수) AJAX/Vue.js

하이·2023년 1월 25일
0

수업

목록 보기
16/41
post-custom-banner

JavaScript

ECMA Script 2015(ES6)
clinet-side web API
(
DOM(Document Object Model)
BOM(Browser Object Model)
IndexedDB
localStorage
canvas
... XMLHTTPRequest(AJAX)
)
=> ECMA Script로 제어하는게 쉽지 않음
=> JQuery

JQuery

$() : selector를 이용한 화면처리
method
AJAX
Event

함수의 동작방식

Blocking(동기)

: 순차적으로 발생함 - 대부분 blocking을 이용
: process가 실행한 순서대로 동작하는 개념

장점
: 순차처리에 적합 - 코드의 작성과 프로그램이 쉬움
단점
: 순차처리이기 때문에 비효율적이 될 때가 많음


확인을 눌러야 꺼짐

Non-Blocking(비동기)

: 함수의 동작(역할)이 종료되기 전에(결과가 만들어지기 전에) 함수가 return 됨
: JQeury의 AJAX 함수 -> 함수의 결과를 event방식으로 받음
: process가 실행한 순서와 무관하게 동작

let result = $.ajax({
  	async : true,
    // 동기(false),비동기(true)를 나타냄 - false는 동기로 돌아가고 함수 자체도 blocking됨
  
    url :'',
    type : 'get',
    data : {},
    success : function () {
        // 성공하면 이게 호출됨
    }
});
// ajax 호출을 해서 서버쪽 프로그램이 실행되고 그 결과가
// 우리에게 JSON으로 보내지게 되는데, 당연히 시간이 걸림
// but, 그 시간을 기다리지 않음
// 그래서 ajax()호출은 바로 리턴됨.
// 리턴되는 값은 ajax()의 결과값이 아님
// (결과를 기다리지 않고 return 받음)
// 결과는 event driven방식으로 받음

BoxOffice

https://www.kobis.or.kr/kobisopenapi/homepg/apiservice/searchServiceInfo.do


function searchBtn() {
    // 날짜를 가져와서 AJAX를 호출하면 됨
    $.ajax({
        async : true,
        url : 'http://www.kobis.or.kr/kobisopenapi/webservice/rest/boxoffice/searchDailyBoxOfficeList.json',
        type : 'GET',
        timeout : 3000,  // 천분의 1 단위로 초를 적음
        data : {
            key : '8af68cecd7d222e2af7cafbc370d06d9',
            targetDt : ($('[type=date]').val()).replace(/-/g,''),   // YYYYMMDD 형식, (/-/g,'')g를 찾아서 ''로 바꿈
        },
        dataType : 'json',  // default값이 json이라서 안 써도 됨
        success : function () {
            alert('성공')
        },
        error: function () {
            alert('실패')
        }
    })

    // 지금 클릭한게 <a>.
    // <a>는 default event를 가지고 있기때문에 막아줘야 함
    event.preventDefault();   
}


function searchBtn() {
    // 날짜를 가져와서 AJAX를 호출하면 됨
    $.ajax({
        async : true,
        url : 'http://www.kobis.or.kr/kobisopenapi/webservice/rest/boxoffice/searchDailyBoxOfficeList.json',
        type : 'GET',
        timeout : 3000,  // 천분의 1 단위로 초를 적음
        data : {
            key : '8af68cecd7d222e2af7cafbc370d06d9',
            targetDt : ($('[type=date]').val()).replace(/-/g,''),   // YYYYMMDD 형식, (/-/g,'')g를 찾아서 ''로 바꿈
        },
        dataType : 'json',  // default값이 json이라서 안 써도 됨
        success : function (data) {
            // alert('성공')
            // 성공하면 당연히 서버는 결과값을 JSON문자열로 전달함
            // 그러면 이 문자열을 받아서 문자열을 분석해서 결과처리를 해야함
            // 이 JSON문자열 처리가 쉽지 않음
            // -> 이걸 객체로 변경해서 우리한테 함수의 인자로 전달해줌
            // 이 JSON을 분석해야 함
            let arr = data.boxOfficeResult.dailyBoxOfficeList;
            // 배열 안의 각 요소에 대해 함수를 호출(callback)함
            $.each(arr, function (idx,item) {
                // idx : 반복할때마다 숫자가 증가하는 index
                // item : 반복할때마다 추출되는 배열 안에 있는 원소
                console.log(item.movieNm);
                // 데이터를 정상적으로 가져올 수 있으면 이제 이걸 가지고 화면처리하면 됨

            })

        },
        error: function () {
            alert('실패')
        }
    });

    // 지금 클릭한게 <a>.
    // <a>는 default event를 가지고 있기때문에 막아줘야 함
    event.preventDefault();

    
}

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>BoxOffice Template</title>
    <!-- jQuery를 사용하기 위한 CDN을 설정. -->    
    <script src="https://code.jquery.com/jquery-3.6.3.min.js" 
            integrity="sha256-pvPw+upLPUjgMXY0G+8O0xUf+/Im1MZjXxxgOcBQBXU=" 
            crossorigin="anonymous">
    </script>

    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css">

    <style>
      .bd-placeholder-img {
        font-size: 1.125rem;
        text-anchor: middle;
        -webkit-user-select: none;
        -moz-user-select: none;
        user-select: none;
      }

      @media (min-width: 768px) {
        .bd-placeholder-img-lg {
          font-size: 3.5rem;
        }
      }

      .b-example-divider {
        height: 3rem;
        background-color: rgba(0, 0, 0, .1);
        border: solid rgba(0, 0, 0, .15);
        border-width: 1px 0;
        box-shadow: inset 0 .5em 1.5em rgba(0, 0, 0, .1), inset 0 .125em .5em rgba(0, 0, 0, .15);
      }

      .b-example-vr {
        flex-shrink: 0;
        width: 1.5rem;
        height: 100vh;
      }

      .bi {
        vertical-align: -.125em;
        fill: currentColor;
      }

      .nav-scroller {
        position: relative;
        z-index: 2;
        height: 2.75rem;
        overflow-y: hidden;
      }

      .nav-scroller .nav {
        display: flex;
        flex-wrap: nowrap;
        padding-bottom: 1rem;
        margin-top: -1px;
        overflow-x: auto;
        text-align: center;
        white-space: nowrap;
        -webkit-overflow-scrolling: touch;
      }
    </style>

    
    <!-- Custom styles for this template -->
    <link href="./css/dashboard.css" rel="stylesheet">
    
    <!-- jQuery를 사용하기 위한 CDN을 설정 -->
    <script src="https://code.jquery.com/jquery-3.6.3.min.js"
    integrity="sha256-pvPw+upLPUjgMXY0G+8O0xUf+/Im1MZjXxxgOcBQBXU="
    crossorigin="anonymous">
    </script>
    
    <script src="./js/230125_BoxOffice.js"></script>
  </head>
  <body>
    
<header class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0 shadow">
  <a class="navbar-brand col-md-3 col-lg-2 me-0 px-3 fs-6" href="#">BoxOffice</a>
  <button class="navbar-toggler position-absolute d-md-none collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#sidebarMenu" aria-controls="sidebarMenu" aria-expanded="false" aria-label="Toggle navigation">
    <span class="navbar-toggler-icon"></span>
  </button>
  <input id="searchDate"
         class="form-control form-control-dark w-100 rounded-0 border-0"
         type="date"
         placeholder="Search"
         aria-label="Search">
  <div class="navbar-nav">
    <div class="nav-item text-nowrap">
      <a class="nav-link px-3" href="#"
         onclick="searchBtn()">Search!!</a>
    </div>
  </div>
</header>

<div class="container-fluid">
  <div class="row">
    <nav id="sidebarMenu" class="col-md-3 col-lg-2 d-md-block bg-light sidebar collapse">
      <div class="position-sticky pt-3 sidebar-sticky">
        <ul class="nav flex-column">
          <li class="nav-item">
            <a class="nav-link active" aria-current="page" href="#">
              <span data-feather="home" class="align-text-bottom"></span>
              날짜별 BoxOffice 순위
            </a>
          </li>
        </ul>
      </div>
    </nav>

    <main class="col-md-9 ms-sm-auto col-lg-10 px-md-4">

      <h2>영화순위</h2>
      <div class="table-responsive">
        <table class="table table-striped table-sm">
          <thead>
            <tr>
              <th scope="col">순위</th>
              <th scope="col">포스터</th>
              <th scope="col">영화제목</th>
              <th scope="col">관람객수</th>
              <th scope="col">개봉일</th>
              <th scope="col">삭제</th>              
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>1,001</td>
              <td>random</td>
              <td>data</td>
              <td>placeholder</td>
              <td>text</td>
            </tr>
            
          </tbody>
        </table>
      </div>
    </main>
  </div>
</div>

  </body>
</html>

function searchBtn() {
    // 날짜를 가져와서 AJAX를 호출하면 됨
    $.ajax({
        async : true,
        url : 'http://www.kobis.or.kr/kobisopenapi/webservice/rest/boxoffice/searchDailyBoxOfficeList.json',
        type : 'GET',
        timeout : 3000,  // 천분의 1 단위로 초를 적음
        data : {
            key : '8af68cecd7d222e2af7cafbc370d06d9',
            targetDt : ($('[type=date]').val()).replace(/-/g,'')   // YYYYMMDD 형식, (/-/g,'')g를 찾아서 ''로 바꿈
        },
        dataType : 'json',  // default값이 json이라서 안 써도 됨
        success : function (data) {
            $('tbody').empty();
            // alert('성공')
            // 성공하면 당연히 서버는 결과값을 JSON문자열로 전달함
            // 그러면 이 문자열을 받아서 문자열을 분석해서 결과처리를 해야함
            // 이 JSON문자열 처리가 쉽지 않음
            // -> 이걸 객체로 변경해서 우리한테 함수의 인자로 전달해줌
            // 이 JSON을 분석해야 함
            let arr = data.boxOfficeResult.dailyBoxOfficeList;
             // 배열 안의 각 요소에 대해 함수를 호출(callback)함
            $.each(arr, function (idx,item) {
                // idx : 반복할때마다 숫자가 증가하는 index
                // item : 반복할때마다 추출되는 배열 안에 있는 원소
                console.log(item.movieNm);
                // 데이터를 정상적으로 가져올 수 있으면 이제 이걸 가지고 화면처리하면 됨
                
                // 태그를 만들어보자
                // <tr>
                //   <td>1,001</td>
                //   <td><img src="~~~"></td>
                //   <td>data</td>
                //   <td>placeholder</td>
                //   <td>text</td>
                //   <td><button class="btn btn-danger">삭제</buttion></td>  
                // </tr>
                let tr = $("<tr></tr>");
                let ranktd = $("<td></td>").text(item.rank);
                let postertd = $("<td></td>");
                let posterImg = $('<img />');
                postertd.append(posterImg);
                
                // 이미지를 가져오기 위한 AJAX를 호출해야 함
                $.ajax({
                    async: true,
                    url: 'https://dapi.kakao.com/v2/search/image',
                    type:'GET',
                    data : {
                        query : item.movieNm + '포스터'
                    },
                    headers: {
                        Authorization: 'KakaoAK 4d8c40adf5d13ea1c02ade1846d8f0e2'
                    },
                    success : function (data) {
                        // console.log('검색 성공');
                        let imgurl = data.documents[0].thumbnail_url;
                        // 
                        posterImg.attr('src', imgurl);
                    },
                    error : function () {
                        console.log('검색 실패');
                    }
                    
                });


                let titletd = $("<td></td>").text(item.movieNm);
                let audtd = $("<td></td>").text(item.audiCnt);
                let opentd = $("<td></td>").text(item.openDt);
                let deltd = $("<td></td>");
                let delBtn = $("<button></button>").text('삭제').addClass('btn btn-danger');
                deltd.append(delBtn);
                // 삭제버튼에 클릭이벤트에 대한 이벤트 핸들러를 등록해줌
                delBtn.click(function () {
                    // jQuery event 처리방식에서 이벤트 핸들러에 this가 등장하면
                    // 이 this는 event source 문서객체를 지칭함
                    $(this).parent().parent().remove();
                });
                tr.append(ranktd);
                tr.append(postertd);
                tr.append(titletd);
                tr.append(audtd);
                tr.append(opentd);
                tr.append(deltd);
                $('tbody').append(tr);
            })
        },
        error: function () {
            alert('실패')
        }
    });

    // 지금 클릭한게 <a>.
    // <a>는 default event를 가지고 있기때문에 막아줘야 함
    event.preventDefault();
}



Vue.js

: 웹페이지 화면을 개발하기 위한 Framework
: React와 Angulur의 장점을 추출 (상대적으로 쉬운 난이도)
: 역사가 오래되진 않음(2014~2017)

① core library : 화면에 데이터를 표현
② component 기반 : 화면을 분할해서 구현
③ routing 기능
④ 상태관리

  • UI 구현 : MVVM 패턴 이용
    Model-View-ViewModel
    유지보수와 재활용성

  • Component기반의 Framework
    : 화면을 구조화(component)하여 개발

CDN

<script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>

Vue instance

: vue로 화면을 개발하기 위해 필수적으로 생성해야하는 기본 단위
new Vue()
: 생성자 함수
: () 안에 설정을 객체로 명시 - 정해져있는 속성 (el, data(변수들), template, methods(함수들), life cycle hook(정해져있음)
: Vue instance는 life cycle을 가지고 있음

vue instance의 life cycle

: 상태에 따라 Hook method가 호출
: 어디에서 정의하는지, 정확한 호출시점은 언제인지?

Vue의 반응성

: 데이터가 변하면 화면의 연결 데이터도 자동으로 변경됨

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <!-- Vue.js를 이용해보아요! CDN을 포함시켜요 -->
    <script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>

</head>
<body>
    <div id="app">
        {{ message }}
        <div id="myDiv"></div>
    </div>
    <script>
        // Vue instance(인스턴스)를 생성
        // 만들어진 Vue instance가 내가 원하는 일을 하는 객체여야 함
        // 생성자 함수
        new Vue({
            // el, data 등을 property라고 함 key : value
            el:'#app',      // el 속성
            data: {         // data 속성
                message : '아우성!'
            },
            methods: {
                myFunc: function(){
                    console.log('myFunc가 호출');
                }
            },
            beforeCreate: function(){
                // beforeCreate Hook method
                // instance가 생성되고 가장 처음에 실행되는 life cycle 단계
                // 이 상태가 되면 자동으로 메소드가 호출됨
                console.log('beforeCreate가 호출');
                // 이 시점에는 아직 data속성과 methods 속성이 정의되지 않은 시점
                // 그리고 또한 화면에 부착되지도 않은 시점
                console.log(this.message);  // undefined
            },
            created: function(){
                // created Hook method
                // 이 시점에는 data속성과 method속성을 사용할 수 있음
                console.log('created가 호출');
                console.log(this.message);  // 아우성
                this.myFunc();              // 여기는 myFunc
            },
            beforeMount: function(){
                    console.log('beforeMount가 호출');
                    // 아직 화면에 붙지 않았기 때문에 화면제어를 할 수 없음
            },
            mounted: function(){
                console.log('mounted가 호출');
                // 화면에 Vue instance가 붙은 직후에 호출되기 때문에
                // 화면제어를 할 수 있음
                // $('#myDiv').text('하이하이');   // JQuery 코드
                // const myDiv = document.getElementById('myDiv')  // 이 두줄이 JS코드
                // myDiv.innerText = '하이하이'                      // 이 두줄이 JS코드
            }
        }); 
                   
    </script>
</body>
</html>


버튼을 클릭하면 메세지가 바뀜

component -> javascript 객체 {~~~}
: 화면의 일정부분을 구현

component의 2가지 동작방식

  • Global component(전역 component) : 여러 instance에서 공통적으로 사용이 가능
  • Local component(지역 component) : 특정 instance 내에서만 유효한 component

① 전역 component의 등록
Vue( ) : 생성자함수 -> 객체 => property를 가짐 -> 이 중 component라는 property가 있는데 => 함수
Vue.component()

② 지역 component의 등록

profile
기록의 즐거움 😆💻
post-custom-banner

0개의 댓글