1.ajax 是什么?有什么作用副砍?
Ajax是Asynchronous JavaScript and XML的縮寫衔肢,這一技術(shù)能夠向服務(wù)器請求額外的數(shù)據(jù)而無需卸載整個(gè)頁面,會帶來良好的用戶體驗(yàn)豁翎。傳統(tǒng)的HTTP請求流程大概是這樣的:
- 瀏覽器向服務(wù)器發(fā)送請求
- 服務(wù)器根據(jù)瀏覽器傳來數(shù)據(jù)生成response
- 服務(wù)器把response返回給瀏覽器
- 瀏覽器刷新整個(gè)頁面顯示最新數(shù)據(jù)
- 這個(gè)過程是同步的角骤,順序執(zhí)行
異步數(shù)據(jù)傳輸(HTTP 請求)從服務(wù)器獲取數(shù)據(jù)
無需重新加載頁面
通過DOM操作網(wǎng)頁部分更新
網(wǎng)頁沒有緩存
有安全問題
2.
- 前后端開發(fā)聯(lián)調(diào)需要注意哪些事情?
1:get/post; //請求類型
2./loadMore; //接口位置
3.{
index: 3, //請求的數(shù)組的序號和長度
length: 5
};
4.['new1', 'news2'...'news5']; //需要的數(shù)據(jù)心剥,JSON格式的數(shù)組
- 后端接口完成前如何 mock 數(shù)據(jù)邦尊?
1.自己模擬數(shù)據(jù)來進(jìn)行MOCK;
2.使用server-mock或mock.js搭建模擬服務(wù)器优烧,進(jìn)行模擬測試蝉揍;
3.使用XAMPP等工具,編寫PHP文件來進(jìn)行測試畦娄。
xhr.open('get', '/loadmore?index='+pageIndex+'&length=5', true)
/*生成請求
*將接口和數(shù)據(jù)的要求
*通過字符串拼接出來
*/
xhr.send() /*發(fā)送
3.點(diǎn)擊按鈕又沾,使用 ajax 獲取數(shù)據(jù),如何在數(shù)據(jù)到來之前防止重復(fù)點(diǎn)擊?
/*
var isDataArrive = true * 添加一個(gè)變量來記錄數(shù)據(jù)到來狀態(tài)
* 初始狀態(tài)為true
*/
btn.addEventListener('click', function(){
if(!isDataArrive){
return;
}
xhr.onreadystatechange = function(){
...
if(xhr.readyState === 4){
... /*
isDateArrive = true * 在onreadystatechange事件變?yōu)?之后
} * 表示請求的數(shù)據(jù)正常生成
} */
xhr.open()
xhr.send() /*
* 到達(dá)這里表示數(shù)據(jù)已正常到來
isDateArrive = false * 狀態(tài)改變--->false
* 之后重復(fù)點(diǎn)擊不會再生成請求發(fā)送
*/
})
4.封裝一個(gè) ajax 函數(shù)熙卡,能通過如下方式調(diào)用杖刷。后端在本地使用server-mock來 mock 數(shù)據(jù)
//ajax封裝
function ajax(opts){
opts.success = opts.success || function(){}; //該項(xiàng)內(nèi)容用戶沒有輸入則設(shè)置默認(rèn)
opts.error = opts.error || function(){};
opts.dataType = opts.dataType || 'json';
opts.data = opts.data || {};
var dataStr = '';
for (var key in opts.data){
dataStr += key + '=' + opts.data[key] + '&'
}
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function(){
if (xmlhttp.readyState == 4) {
if(xmlhttp.status == 200 || xmlhttp.status ==304) {
if(opts.dataType === 'text'){
opts.success(xmlhttp.responseText);
}
if(opts.dataType === 'json'){
var json = JSON.parse(xmlhttp.responseText);
opts.success(json)
}
}else{
opts.error()
}
}
}
dataStr = dataStr.substr(0,dataStr.length-1);
if (opts.type.toLowerCase() === 'post') {
xmlhttp.open(opts.type, opts.url,true);
xmlhttp.setRequestHeader('content-type', 'application/x-www-form-urlencoded')
xmlhttp.send();
}
}
document.querySelector('#btn').addEventListener('click', function(){
ajax({
url: '/login', //接口地址
type: 'get', // 類型get
data: {
username: 'xiaoming',
password: 'abcd1234'
},
success: function(ret){
console.log(ret); // {status: 0}
},
error: function(){
console.log('出錯了')
}
})
});
5.
加載更多
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<style type="text/css">
ul,li{
margin: 0;
padding: 0;
}
li:hover{
background-color: #6ff;
color: #fff;
}
.btn{
display:block;
margin: 10px auto;
text-decoration: none;
color: #fff;
background: #6ea;
width: 100px;
padding: 10px;
line-height: 30px;
font-size: 18px;
text-align: center;
}
#ct>li{
padding: 10px;
margin: 10px 0;
border: 1px solid #ccc;
}
</style>
<body>
<ul id="ct">
<li>內(nèi)容1</li>
<li>內(nèi)容2</li>
</ul>
<a href="#" id="load-more" class="btn">加載更多</a>
<script type="text/javascript">
var btn = document.querySelector(".btn")
var ct = document.querySelector("#ct")
var pageIndex = 3
var isDataArrive = true
btn.addEventListener('click',function(e){
e.preventDefault()
if(!isDataArrive){
return;
}
var xhr = new XMLHttpRequest()
xhr.onreadystatechange = function(){
if(xhr.readyState === 4){
if(xhr.status === 200 || xhr.status === 304){
var results = JSON.parse(xhr.responseText)
console.log(results)
var fragment = document.createDocumentFragment()
for (var i = 0;i<results.length;i++){
var node = document.createElement('li')
node.innerText = results[i]
fragment.appendChild(node)
}
ct.appendChild(fragment)
pageIndex = pageIndex + 5
}else{
console.log('出錯了')
}
isDataArrive = true
}
}
xhr.open('get','/loadMore?index='+pageIndex+'&length=5',true)
xhr.send()
isDataArrive = false
})
</script>
</body>
</html>
//router.js
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);
},5000)
// res.send(data);
});
//完整的ajax封裝
<script>
var btn = document.querySelector(".btn")
var ct = document.querySelector("#ct")
var pageIndex = 3
var isDataArrive = true //上鎖
btn.addEventListener('click',function(e){
e.preventDefault()
if(!isDataArrive) return;
load(function(e){
renderPage(e)
pageIndex = pageIndex + 5
isDataArrive = true //解鎖
})
isDataArrive = false //加鎖
})
function load(callback){
ajax({
url:'/loadMore',
type: 'get',
dataType: 'json',
data: {
index: pageIndex,
length: 5
},
success: callback, //callback 是一個(gè)函數(shù),得到的參數(shù)傳給e
error: function(){
console.log('error');
}
})
}
function renderPage(text){
var fragment = document.createDocumentFragment()
for (var i = 0;i<text.length;i++){
var node = document.createElement('li')
node.innerText = text[i]
fragment.appendChild(node)
}
ct.appendChild(fragment)
}
function ajax(opts){
opts.success = opts.success || function(){}; //該項(xiàng)內(nèi)容用戶沒有輸入則設(shè)置默認(rèn)的匿名函數(shù)
opts.error = opts.error || function(){};
opts.dataType = opts.dataType || 'json';
opts.data = opts.data || {};
var dataStr = '';
for (var key in opts.data){
dataStr += key + '=' + opts.data[key] + '&'
}
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function(){
if (xmlhttp.readyState == 4) {
if(xmlhttp.status == 200 || xmlhttp.status ==304) {
if(opts.dataType === 'text'){
opts.success(xmlhttp.responseText);
}
if(opts.dataType === 'json'){
var json = JSON.parse(xmlhttp.responseText);
opts.success(json)
}
}else{
opts.error()
}
}
}
dataStr = dataStr.substr(0,dataStr.length-1);
if (opts.type.toLowerCase() === 'post') {
xmlhttp.open(opts.type, opts.url,true);
xmlhttp.setRequestHeader('contengt-type', 'application/x-www-form-urlencoded')
xmlhttp.send(dataStr); //post的傳遞請求方式
}
if (opts.type.toLowerCase() === 'get') {
xmlhttp.open(opts.type, opts.url+'?'+dataStr,true);
xmlhttp.send();
}
}
</script>