1.ajax 是什么谍倦?有什么作用?
Asynchronous JavaScript and XML(異步的 JavaScript 和 XML 通過在后臺與服務(wù)器進行少量數(shù)據(jù)交換叹誉,AJAX 可以使網(wǎng)頁實現(xiàn)異步更新沉馆。這意味著可以在不重新加載整個網(wǎng)頁的情況下,對網(wǎng)頁的某部分進行更新呕诉。
作用:
- 更新數(shù)據(jù)而不需要刷新頁面: 它能在不刷新整個頁面的前提下與服務(wù)器通信維護數(shù)據(jù)覆劈,由于ajax是按照需求請求數(shù)據(jù)保礼,避免發(fā)送那些沒有改變的數(shù)據(jù)。
- 異步通信: 它與服務(wù)器使用異步的方式通信责语,不會打斷用戶的操作(卡死頁面)炮障。
- 前后端負載平衡: 可以將后端服務(wù)器的一些工作轉(zhuǎn)移給客戶端,利用客戶端限制的能力來處理坤候,減輕了服務(wù)器的負擔(dān)胁赢。
- 數(shù)據(jù)與呈現(xiàn)分離: 利于分工,降低前后耦合白筹。
缺點 - 瀏覽器歷史記錄的遺失: 在使用AJAX對頁面進行改變后智末,由于并沒有刷新頁面谅摄,沒有改變頁面的訪問歷史,當(dāng)用戶想要回到上一個狀態(tài)時系馆,無法使用瀏覽器提供的后退送漠。
- AJAX的安全問題: AJAX的出現(xiàn)就像建立起了一直通服務(wù)器的另一條通道,容易遭受到一些攻擊
2.前后端開發(fā)聯(lián)調(diào)需要注意哪些事情由蘑?后端接口完成前如何 mock 數(shù)據(jù)闽寡?
注意事項:
約定數(shù)據(jù):有哪些需要傳輸?shù)臄?shù)據(jù),數(shù)據(jù)類型是什么尼酿;
約定接口:確定接口名稱及請求和響應(yīng)的格式爷狈,請求的參數(shù)名稱、響應(yīng)的數(shù)據(jù)格式裳擎;
根據(jù)這些約定整理成接口文檔
如何mock數(shù)據(jù):
1.自己模擬數(shù)據(jù)來進行MOCK涎永;
2.使用server-mock或mock.js搭建模擬服務(wù)器,進行模擬測試鹿响;
3.使用XAMPP等工具羡微,編寫PHP文件來進行測試。
3.點擊按鈕抢野,使用 ajax 獲取數(shù)據(jù),如何在數(shù)據(jù)到來之前防止重復(fù)點擊?
1.初始化數(shù)據(jù)是已經(jīng)響應(yīng)成功 var isDataArrive = true
2.當(dāng)剛剛發(fā)送請求時各墨,立即將再次發(fā)送封鎖指孤,防止用戶多次點擊
xhr.open(type,url ,true);
xhr.send();
isDataArrive = false
btn.addEventListener("click",function(){
if(!isDataArrive){
return;
}
...
}
3.當(dāng)服務(wù)器響應(yīng)完成,返回數(shù)據(jù)后贬堵,立即設(shè)置 isDataArrive = true
恃轩,這樣用戶再次點擊就可以重新發(fā)送請求了
var isDataArrive = true;//1
btn.addEventListener("click",function(){
if(!isDataArrive){
return;
} //3
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
if(xhr.readyState === 4){
if(xhr.status ===200 || xhr.status ===304){
//do something
}else{
//do something
}
isDataArrive = true //4
}
};
xhr.open(type,url ,true);
xhr.send();
isDataArrive = false; //2
})
4.封裝一個 ajax 函數(shù),能通過如下方式調(diào)用黎做。后端在本地使用server-mock來 mock 數(shù)據(jù)
function ajax(opts){
opts.success = opts.success || function(){};
opts.error = opts.error || function(){};
opts.type = opts.type || 'get';
opts.dataType = opts.dataType || 'json';
opts.data = opts.data || {};
var dataStr = '';
for(var key in opts.data){
dataStr += key+ '='+opts.data[key] + '&';
}
dataStr = dataStr.substr(0,dataStr.length-1);
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
if(xhr.readyState === 4 ){
if(xhr.status === 200 || xhr.status ===304){
if(opts.dataType === 'text'){
opts.success(xhr.responseText)
}
if(opts.dataType === 'json'){
var json =JSON.parse(xhr.responseText);
opts.success(json)
}
}else{
opts.error()
}
}
};
if(opts.type.toLowerCase() === 'get'){
xhr.open(opts.type,opts.url+'?'+dataStr,true);
xhr.send();
}
if(opts.type.toLowerCase() === 'post'){
xhr.open(opts.type,opts.url,true);
xhr.setRequestHeader("content-type","application/x-www-form-urlencoded");
xhr.send(dataStr)
}
}
5.實現(xiàn)加載更多的功能叉跛,效果范例,后端在本地使用server-mock來模擬數(shù)據(jù)
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>加載更多</title>
<style>
.container {
list-style: none;
margin: 0;
padding: 0;
}
.container li {
border: 1px solid #cccccc;
padding: 10px;
margin-bottom: 10px;
}
.container li:hover{
background: green;
color: #ffffff;
}
#btn{
text-align: center;
text-decoration: none;
color: #e27272;
border: 1px solid #e27272;
border-radius: 3px;
display: block;
margin: 0 auto;
width: 80px;
height: 40px;
line-height: 40px;
}
#btn img{
width: 40px;
height: 40px;
}
</style>
</head>
<body>
<ul class="container">
<li>內(nèi)容1</li>
<li>內(nèi)容2</li>
</ul>
<a href="#" id="btn">加載更多</a>
<script>
var btn = document.getElementById("btn");
var ct = document.querySelector(".container");
var idx = 3;
var isDataArr = true;
btn.addEventListener("click",function(e){
e.preventDefault();
if(isDataArr===false){
return;
}
btn.innerHTML = "![](loading.jpg)";
ajax({
url: "/loadMore",
type: "get",
data: {
index: idx,
length: 5
},
success: function(data){
var fragment = document.createDocumentFragment();
for(var i = 0; i < data.length; i++){
var node = document.createElement("li");
node.innerText = data[i];
fragment.appendChild(node);
}
ct.appendChild(fragment);
btn.innerHTML = "加載更多";
idx += 5;
},
error: function(){
console.log("加載失敗")
}
});
});
function ajax(opts){
opts.success = opts.success || function(){};
opts.error = opts.error || function(){};
opts.type = opts.type || 'get';
opts.dataType = opts.dataType || 'json';
opts.data = opts.data || {};
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
if(xhr.readyState === 4 ){
if(xhr.status === 200 || xhr.status ===304){
if(opts.dataType === 'text'){
opts.success(xhr.responseText)
}
if(opts.dataType === 'json'){
var json =JSON.parse(xhr.responseText);
opts.success(json)
}
}else{
opts.error()
}
}
isDataArr = true;
};
var dataStr = '';
for(var key in opts.data){
dataStr += key+ '='+opts.data[key] + '&';
}
dataStr = dataStr.substr(0,dataStr.length-1);
if(opts.type.toLowerCase() === 'get'){
xhr.open(opts.type,opts.url+'?'+dataStr,true);
xhr.send();
}
if(opts.type.toLowerCase() === 'post'){
xhr.open(opts.type,opts.url,true);
xhr.setRequestHeader("content-type","application/x-www-form-urlencoded");
xhr.send(dataStr)
}
isDataArr = false;
}
</script>
</body>
</html>
后臺代碼
app.get('/loadMore', function(req, res){
var curIdx = req.query.index;
var len = req.query.length;
var data = [];
for(var i=0;i<len;i++){
data.push("內(nèi)容"+(parseInt(curIdx)+i))
}
setTimeout(function(){
res.send(data)
},1000)
});