ECMA Script 2015(ES6)
clinet-side web API
(
DOM(Document Object Model)
BOM(Browser Object Model)
IndexedDB
localStorage
canvas
... XMLHTTPRequest(AJAX)
)
=> ECMA Script로 제어하는게 쉽지 않음
=> JQuery
$() : selector를 이용한 화면처리
method
AJAX
Event
: 순차적으로 발생함 - 대부분 blocking을 이용
: process가 실행한 순서대로 동작하는 개념
장점
: 순차처리에 적합 - 코드의 작성과 프로그램이 쉬움
단점
: 순차처리이기 때문에 비효율적이 될 때가 많음
확인을 눌러야 꺼짐
: 함수의 동작(역할)이 종료되기 전에(결과가 만들어지기 전에) 함수가 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방식으로 받음
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();
}
: 웹페이지 화면을 개발하기 위한 Framework
: React와 Angulur의 장점을 추출 (상대적으로 쉬운 난이도)
: 역사가 오래되진 않음(2014~2017)
① core library : 화면에 데이터를 표현
② component 기반 : 화면을 분할해서 구현
③ routing 기능
④ 상태관리
UI 구현 : MVVM 패턴 이용
Model-View-ViewModel
유지보수와 재활용성
Component기반의 Framework
: 화면을 구조화(component)하여 개발
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
: vue로 화면을 개발하기 위해 필수적으로 생성해야하는 기본 단위
new Vue()
: 생성자 함수
: () 안에 설정을 객체로 명시 - 정해져있는 속성 (el, data(변수들), template, methods(함수들), life cycle hook(정해져있음)
: Vue instance는 life cycle을 가지고 있음
: 상태에 따라 Hook method가 호출
: 어디에서 정의하는지, 정확한 호출시점은 언제인지?
: 데이터가 변하면 화면의 연결 데이터도 자동으로 변경됨
<!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의 등록
Vue( ) : 생성자함수 -> 객체 => property를 가짐 -> 이 중 component라는 property가 있는데 => 함수
Vue.component()
② 지역 component의 등록