昨天我們以 axios 的方式做切入,只有粗略提到一點 Ajax 。今天要把主角換成 Ajax ,深入底層的觀念。
Ajax 主要有五個步驟:
換成語法的話就會是下面這樣:
let xhr = new XMLHttpRequest();
xhr.open('post or get','api網址',true或false);
xhr.onload = function(要執行的事){};
xhr.setRequestHeader('Content-type','application/x-www-form-urlencoded');
xhr.send('要傳送的資料');
用昨天的 API 來寫的話則是這樣:
let xhr = new XMLHttpRequest();
xhr.open('get','https://api.kcg.gov.tw/api/service/Get/b4dd9c40-9027-4125-8666-06bef1756092',true);
xhr.onload = function(){
console.log(xhr.responseText);
};
xhr.send();
application/x-www-form-urlencoded 是種在 post api 時常見的格式,這個位置會根據後端要求要用哪種格式傳送而改變。其他常見的格式還有: multipart/form-data 、 application/json 和 text/xml 。用不同的格式傳送,可能導致下面要把內容放到網站畫面,須把格式轉換成 JSON 格式,或把物件轉成字串。
例如使用 JSON.parse() 可把資料轉成 JSON 格式,用 JSON.stringfy() 則可把物件轉成字串。
send 括弧裡要傳送的資料如果不只一筆,中間可以用 & 來連接。例如:
xhr.send('email=abc@gmail.com&password=123');
在上面 xhr.open 的第三格可以設定同步與非同步,這是什麼意思,又要如何設定呢?昨天在寫 axios 時,應該會發現有時候資料還沒 load 完,就跑下面的程式,非常困擾吧!但同樣的,如果今天要傳的資料很多,網頁一直卡在那不能處理其他的事情,導致使用者不知道現在是什麼狀況而直接按叉叉,也很母湯。
所以這裡就出現是否要同步的選擇題了。
但不管你想怎麼決定,讓我們繞回來談一下設定。跟直觀想的不同, true 在這裡代表非同步,也就是不等資料傳回來就讓程式碼繼續往下跑,等到回傳才自動回傳。 false 在這裡代表的是同步,也就是等資料回傳才繼續跑下面。
此外,你也可以透過 network 面板確認是否所有東西都有運作中,以及後端回傳那些物件資料。開啟方式和 console 一樣,在網頁上按 f12 ,選 network。從 status 可以判斷每個檔案跑的狀況。
點選 xhr 的檔案,會秀出細部資料,可以在 header 裡看到是用哪種方式(get/post)取得資料的, status 是什麼,在 preview 則能看到回傳的資料。實際螢幕畫面如下:
在上面的 xhr.open 後面,不只可以設定 post ,設成 get 也一樣能夠取得資料。例如上面的例子中,我們使用的 method 就是 get 而不是 post 。那這兩種的差別是什麼呢?
使用 get 傳送資料時,資料會被放在 header 傳送,傳送過程會被放在網址上,因此不適合傳密碼等較隱密的資料。此外, get 的請求會被 cache 紀錄、受限 QueryString 長度限制,並且是運用 PHP 的 $GET['xxx']
變數接受傳值。
post 則不同,是把資料放在訊息主體內傳送,不會被 cache 紀錄、資料長度無限制,並且是運用 PHP 的 $_POST['xxx']
接受傳值。也是因為 get 和 post 把資料放在不同的地方,剛剛提到的 Content-type ,只有會把資料放在主體的 post 需要設定。
我們可以利用上面學到的,用這個 API 製作一個簡易註冊登入面板,並加入兩個小功能,讓系統能確認帳號密碼不為空,以及送出後清空欄位。
<div class= "wrap">
<div class = "submit">
<form action = "index.html">
<h4>E-Mail:</h4>
<input type = "text" name = "emailSubmit" class = "emailSubmit" placeholder = "example@gmail.com">
<h4>Password:</h4>
<input type = "text" name = "passwordSubmit" class = "passwordSubmit" placeholder = "請輸入密碼">
<input type = "submit" value = "註冊" class = "sendSubmit">
</form>
</div>
<div class = "login">
<form action = "index.html">
<h4>E-Mail:</h4>
<input type = "text" name = "emailLogin" class = "emailLogin" placeholder = "example@gmail.com">
<h4>Password:</h4>
<input type = "text" name = "passwordLogin" class = "passwordLogin" placeholder = "請輸入密碼">
<input type = "submit" value = "登入" class = "sendLogin">
</form>
</div>
</div>
h4{
margin-left: 15px;
}
.wrap{
width: 600px;
display: flex;
margin: 0 auto;
}
input{
margin: 15px;
}
.submit, .login{
width: 500px;
justify-content: space-evently;
padding: 20px;
margin-top: 40px;
}
.submit{
background: #0077b6;
color: #90e0ef;
}
.login{
background: #90e0ef;
color: #0077b6;
}
.sendLogin{
background: #0077b6;
color: #90e0ef;
border: 0px;
width: 200px;
}
.sendLogin:hover, .sendSubmit:hover{
background: #e5989b;
color: #6d6875;
}
.sendSubmit{
background: #90e0ef;
color: #0077b6;
border: 0px;
width: 200px;
}
//註冊
let sendSubmit = document.querySelector('.sendSubmit');
sendSubmit.addEventListener("click",runSubmit);
function runSubmit(e){
e.preventDefault();
let mailSubmit = document.querySelector('.emailSubmit').value;
let passSubmit = document.querySelector('.passwordSubmit').value;
if(mailSubmit == ''||passSubmit == ''){ //帳號密碼不可為空
alert('請輸入帳號密碼');
}else{
let xhrSubmit = new XMLHttpRequest();
xhrSubmit.open("post","https://hexschool-tutorial.herokuapp.com/api/signup",true);
xhrSubmit.setRequestHeader("content-type","application/x-www-form-urlencoded");
xhrSubmit.send("email="+mailSubmit+"&password="+passSubmit);
xhrSubmit.onload=function (){
if(xhrSubmit.value == ""){ //帳號密碼不可為空
outmail.innerhtml = "請輸入帳號密碼"
};
let strSubmit= JSON.parse(xhrSubmit.responseText).message;
alert(strSubmit);
}
}
reset(); //送出後,欄位進行清空
}
//登入
let sendLogin = document.querySelector('.sendLogin');
sendLogin.addEventListener("click",runLogin);
function runLogin(e){
e.preventDefault();
let mailLogin = document.querySelector('.emailLogin').value;
let passLogin = document.querySelector('.passwordLogin').value;
if(mailLogin == ''||passLogin == ''){ //帳號密碼不可為空
alert('請輸入帳號密碼');
}else{
let xhrLogin = new XMLHttpRequest();
xhrLogin.open("post","https://hexschool-tutorial.herokuapp.com/api/signup",true);
xhrLogin.setRequestHeader("content-type","application/x-www-form-urlencoded");
xhrLogin.send("email="+mailLogin+"&password="+passLogin);
xhrLogin.onload=function (){
let strLogin = JSON.parse(xhrLogin.responseText).message;
alert(strLogin);
}
}
reset(); //送出後,欄位進行清空
}
function reset(){ //送出後,欄位進行清空
document.querySelector('.emailSubmit').value = "";
document.querySelector('.passwordSubmit').value = "";
document.querySelector('.emailLogin').value = "";
document.querySelector('.passwordLogin').value = "";
}
JS 學徒特訓班教學影片及練習題 47-48 關
什麼是 Ajax? 搞懂非同步請求 (Asynchronous request)概念: https://tw.alphacamp.co/blog/ajax-asynchronous-request
[鐵人賽Day2] GET/POST 的差異與配合PHP用法: https://ithelp.ithome.com.tw/articles/10155801
【POST】請求頭 Content-type: https://medium.com/@des75421/post-%E8%AB%8B%E6%B1%82%E9%A0%AD-content-type-82b93f9230f7