在這個系列的最後,要利用六角學院的 API 製作訂房網站。要使用 API 必須要註冊,並取得自己的 token 。基於安全考量,我的 token 就不放上來了,但下面會記錄寫法,希望對你有所幫助。
概念是這樣,我想要做兩個畫面,一個是主頁,列出所有房型;另一個是房型頁,看我在主頁點擊哪個房型,就跳出哪個房型的詳細資料。
畫面如下:
可想而知我至少會需要四個檔案: index.html / index.js / room.html / room.js
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>製作訂房網站</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">
</head>
<body>
<div class = "wrap">
<ul class = "room"></ul>
</div>
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js" integrity="sha384-B4gt1jrGC7Jh4AgTPSdUtOBvfO8shuf57BaghqFfPlYxofvL8/KUEfYiJOMMV+rV" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script src="index.js"></script>
</body>
</html>
這裡應該沒有問題,帶入一些該載入的 js ,並且額外載入了 boostrap 的 css 和 js 設定檔,規劃一下等等從 API 那抓到的東西要放在哪裡。
const api = 'https://challenge.thef2e.com/api/thef2e2019/stage6/rooms';
const room = document.querySelector('.room');
let data = [];
axios.defaults.headers.common["Authorization"] = `Bearer 把註冊得到的token放在這裡`
axios.get(api).then((res) =>{
this.data = res.data.items;
render(data);
});
function render(){
let str = "";
this.data.forEach((item) =>{
str +=`
<div class="col-md-4 col-sm-6 mb-3">
<div class="card rounded h-100">
<h2 class="card-header text-center" >${item.name}</h2>
<div style="height: 250px; background-size: cover; background-position: center; background-image: url(${item.imageUrl}"></div>
<p>平日價格: ${item.normalDayPrice} 元</p>
<p>假日價格: ${item.holidayPrice} 元</p>
<a href="room.html?id=${item.id}" data-id="${item.id}" class="detail btn btn-outline-primary btn-block">詳細資料</a>
</div>
</div>
`;
});
room.innerHTML = str;
運用之前學到的 axios.get ,取出抓到的 API 裡需要的資料,分別放進該放的位置。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>製作訂房網站</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">
</head>
<body>
<div class="container mt-5">
<div class="roomDetail">
<div id="carouselControls" class="carousel slide" data-ride="carousel"></div>
<div class="carousel-inner"></div>
<a class="carousel-control-prev" href="#carouselControls" role="button" data-slide="prev">
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
<span class="sr-only">Previous</span>
</a>
<a class="carousel-control-next" href="#carouselControls" role="button" data-slide="next">
<span class="carousel-control-next-icon" aria-hidden="true"></span>
<span class="sr-only">Next</span>
</a>
</div>
<div class="roomInfo"></div> <!--放從別的網站抓到的房型細節-->
<div class="amenitiesInfo row bg-light mb-5"></div> <!--放房間設備圖示-->
</div>
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js" integrity="sha384-B4gt1jrGC7Jh4AgTPSdUtOBvfO8shuf57BaghqFfPlYxofvL8/KUEfYiJOMMV+rV" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script src="room.js"></script>
</body>
</html>
同上 index.html ,也是規畫該把東西放哪並載入該載的檔案。
const id = location.search.split("=")[1];
const imgCarousel = document.querySelector(".carousel-inner");
const roomInfo = document.querySelector(".roomInfo");
const amenitiesInfo = document.querySelector(".amenitiesInfo");
const api = `https://challenge.thef2e.com/api/thef2e2019/stage6/room/${id}`;
let roomData = [];
axios.defaults.headers.common["Authorization"] = `Bearer 把註冊得到的token放在這裡`
axios.get(api).then((res) =>{
roomData = res.data.room[0];
imageCard(roomData); //照片切換功能
infoCard(roomData); //內容介紹
amenitiesCard(roomData); //設備介紹
});
function imageCard() { //照片切換功能
const image = roomData.imageUrl;
imgCarousel.innerHTML = `
<div class="carousel-item active">
<img class="d-block w-100" src="${image[0]}" alt="First slide"
style="height: 500px; object-fit: cover;">
</div>
<div class="carousel-item">
<img class="d-block w-100" src="${image[1]}" alt="Second slide"
style="height: 500px; object-fit: cover;">
</div>
<div class="carousel-item">
<img class="d-block w-100" src="${image[2]}" alt="Third slide"
style="height: 500px; object-fit: cover;">
</div>
`;
}
function infoCard() { //內容介紹
roomInfo.innerHTML = `
<h3>${roomData.name}</h3>
<p>${roomData.description}</p>
<ul>
<li>人數限制: ${roomData.descriptionShort.GuestMin} ~ ${roomData.descriptionShort.GuestMax}</li>
<li>床型: ${roomData.descriptionShort.Bed[0]}</li>
<li>衛浴: ${roomData.descriptionShort["Private-Bath"]} 間 </li>
<li>房間大小: ${roomData.descriptionShort.Footage} 平方公尺 </li>
</ul>
<p>Check In: ${roomData.checkInAndOut.checkInEarly} ~ ${roomData.checkInAndOut.checkInLate}</p>
<p>Check Out: ${roomData.checkInAndOut.checkOut}</p>
<p>平日(一~四)價格: ${(roomData.normalDayPrice)}</p>
<p>假日(五~日)價格: ${(roomData.holidayPrice)}</p>
`;
}
function amenitiesCard() { //設備介紹
amenitiesInfo.innerHTML = `
<div class="col-lg-4 ${
!roomData.amenities["Wi-Fi"] ? "text-muted" : "text-success"
}">
<i class="fas fa-wifi"></i>
<span class="pl-2">Wi-Fi</span>
</div>
<div class="col-lg-4 ${
!roomData.amenities["Air-Conditioner"] ? "text-muted" : "text-success"
}">
<i class="fas fa-wind"></i>
<span class="pl-2">空調</span>
</div>
<div class="col-lg-4 ${
!roomData.amenities["Breakfast"] ? "text-muted" : "text-success"
}">
<i class="fas fa-utensils"></i>
<span class="pl-2">含早餐</span>
</div>
<div class="col-lg-4 ${
!roomData.amenities["Child-Friendly"] ? "text-muted" : "text-success"
}">
<i class="fas fa-baby"></i>
<span class="pl-2">小孩友善</span>
</div>
<div class="col-lg-4 ${
!roomData.amenities["Pet-Friendly"] ? "text-muted" : "text-success"
}">
<i class="fas fa-paw"></i>
<span class="pl-2">寵物友善</span>
</div>
<div class="col-lg-4 ${
!roomData.amenities["Great-View"] ? "text-muted" : "text-success"
}">
<i class="fas fa-mountain"></i>
<span class="pl-2">漂亮視野</span>
</div>
<div class="col-lg-4 ${
!roomData.amenities["Mini-Bar"] ? "text-muted" : "text-success"
}">
<i class="fas fa-glass-cheers"></i>
<span class="pl-2">Mini Bar</span>
</div>
<div class="col-lg-4 ${
!roomData.amenities["Refrigerator"] ? "text-muted" : "text-success"
}">
<i class="fas fa-ice-cream"></i>
<span class="pl-2">含冰箱</span>
</div>
<div class="col-lg-4 ${
!roomData.amenities["Room-Service"] ? "text-muted" : "text-success"
}">
<i class="fas fa-concierge-bell"></i>
<span class="pl-2">客房服務</span>
</div>
<div class="col-lg-4 ${
!roomData.amenities["Smoke-Free"] ? "text-muted" : "text-success"
}">
<i class="fas fa-smoking"></i>
<span class="pl-2">煙友友善</span>
</div>
<div class="col-lg-4 ${
!roomData.amenities["Sofa"] ? "text-muted" : "text-success"
}">
<i class="fas fa-couch"></i>
<span class="pl-2">含沙發</span>
</div>
<div class="col-lg-4 ${
!roomData.amenities["Television"] ? "text-muted" : "text-success"
}">
<i class="fas fa-tv"></i>
<span class="pl-2">含電視</span>
</div>
`;
}
這是四個檔案裡最複雜的。首先利用 spilt() 把等號作為斷點,分離左右兩邊,藉此取得等號右邊的 id ,才去用各自房型的 id 代出我要他帶出的單一產品資料。然後一樣使用 axios.get 抓資料,分別跑下面三個函式:照片切換、內容介紹、設備介紹,接著當然就是分別把資料帶入三個區塊了。
剩下的功能,就讓我們明天繼續...
JS 學徒特訓班教學影片及練習題 49-52 關