AJAX学习参考文档:
https://segmentfault.com/a/1190000004322487
题目1: ajax 是什么?有什么作用?
AJAX 全称 Asynchronous JavaScript and XML
AJAX is based on the following open standards:
- Browser-based presentation using HTML and Cascading Style Sheets (CSS).
- Data is stored in XML format and fetched from the server.
- Behind-the-scenes data fetches using XMLHttpRequest objects in the browser.
- JavaScript to make everything happen.
AJAX的技术核心是利用浏览器提供的XMLHttpRequest对象,是这个对象使得浏览器可以发出HTTP请求与接收HTTP响应。
也就是说,AJAX通过XMLHttpRequest往后台发送一个请求。
优点
- 更新数据而不需要刷新页面: 它能在不刷新整个页面的前提下与服务器通信维护数据,由于ajax是按照需求请求数据,避免发送那些没有改变的数据。
- 异步通信: 它与服务器使用异步的方式通信,不会打断用户的操作(卡死页面)。
- 前后端负载平衡: 可以将后端服务器的一些工作转移给客户端,利用客户端限制的能力来处理,减轻了服务器的负担。
- 数据与呈现分离: 利于分工,降低前后耦合。
缺点:
- 浏览器历史记录的遗失: 在使用AJAX对页面进行改变后,由于并没有刷新页面,没有改变页面的访问历史,当用户想要回到上一个状态时,无法使用浏览器提供的后退。
- AJAX的安全问题: AJAX的出现就像建立起了一直通服务器的另一条通道,容易遭受到一些攻击。
题目2 前后端开发联调需要注意哪些事情?后端接口完成前如何 mock 数据?
1.约定数据:约定好页面需要的数据和数据类型
2. 约定接口:
(1)约定接口的名称。
(2)约定请求的参数。
(3)约定响应的的格式,比如:成功后返回什么数据,响应失败返回什么内容。
3.将约定好的东西整理成接口文档和规范
mock数据:参照接口相关文档,使用假数据来验证我们制作的页面响应和接口是否正常。可以搭建php本地服务器用,php写脚本提供临时数据;
也可写js脚本模拟数据,利用server-Mock完成对页面和接口的测试。
题目3:点击按钮,使用 ajax 获取数据,如何在数据到来之前防止重复点击?
方法一
在发送数据请求时,将input的button设置为disabled.
等到数据传输回来了再更改
方法2
设置一个变量为isDataArrive.
var isDataArrive = true
btn.addEventListener('click', function(event){
if(!isDataArrive)
{
return //数据请求还没有结束,这次点击什么也不做
}
//发送请求
ajax(){
send()//发送请求
isDataArrive = false //数据正在传输 上锁
xhr.onreadystatechange = function(){
if(xhr.readyState === 4) //数据传输完成
{
isDataArrive = true //数据传输完成,解锁
}
}
}
})
题目4 封装一个 ajax 函数,能通过如下方式调用
function ajax(opts){
//接收参数并设置默认参数,如果用户没输出参数则可使用默认参数
opts.dataType = 'json'
opts.type = opts.type || 'GET'
opts.data = opts.data || {}
opts.success = opts.success || function(){}
opts.error = opts.error || function(){}
//拼接参数
var query = []
for(attr in opts.data)
{
query.push(key + '=' + opts.data[key])
}
var queryResult = query.join('&')
//创建AJAX对象
var xhr = new XMLHttpRequest()
xhr.onreadystatechange = function(){
if(xhr.readyState === 4)
{
if(xhr.status === 200 || xhr.status === 304)
{
if(opts.dataType.toLowerCase() === 'text')
{
opts.success(xhr.responseText)
}
if(opts.dataType.toLowerCase() === 'json')
{
var result = JSON.parse(xhr.responseText)
opts.success(result)
}
}
}
else
{
opts.error()
}
}
//判断请求方式
if(opts.type.toLowerCase()==='get')
{
xhr.open('GET', opts.url + '?' + queryResult, true)
xhr.send()
}
if(opts.type.toLowerCase()==='post')
{
xhr.open('post', opts.url, true)
xhr.sendRequestHeader('Content-type','application/x-www-form-urlencoded');
xhr.send(queryResult);
}
}
document.querySelector('#btn').addEventListener('click', function(){
ajax({
url: '/login', //接口地址
type: 'get', // 类型, post 或者 get,
data: {
username: 'xiaoming',
password: 'abcd1234'
},
success: function(ret){
console.log(ret); // {status: 0}
},
error: function(){
console.log('出错了')
}
})
});
题目5 实现加载更多的功能,效果范例11,后端在本地使用server-mock来模拟数据
客户端:
var btn = document.querySelector('#load-more')
var ct = document.querySelector('#ct')
var pageIndex = 0
var isLoading = false
btn.addEventListener('click', function(event){
event.preventDefault()//阻止默认事件发生
if(isLoading)
{
return //如果正在请求数据,则这次点击什么也不做
}
//执行到这里说明没有在请求数据,则后买开始发请求
loadData(function(result){
renderPage(result)
})
isLoading = true
})
function loadData(callback)
{
ajax({
type: 'GET',
url: '/loadMore',
data: {
index: pageIndex,
length: 5
},
dataType: 'JSON',
onSuccess: callback,
onError: function(){
console.log('error')
}
})
}
function renderPage(news)
{
var fragment = document.createDocumentFragment()
for(var i = 0; i < news.length; i++)
{
var node = document.createElement('li')
node.innerText = news[i]
fragment.appendChild(node)
}
ct.appendChild(fragment)
}
function ajax(options){
//接收参数与设置默认参数
options.onSuccess = options.onSuccess || function(){}
options.onError = options.onError || function(){}
options.type = options.type || 'GET'
options.dataType = options.dataType || 'JSON'
options.data = options.data || {}
//处理收到的数据,使其成为字符串
var query = '?'
for(key in options.data){
query += key + '=' + options.data[key]+'&'
}
query = query.substr(0, query.length-1)
//创建AJAX对象
var xhr = new XMLHttpRequest()
//开始请求啦
xhr.onreadystatechange = function(){
if(xhr.readyState === 4)
{
isLoading = false
if(xhr.status === 200 || xhr.status === 304)
{
if(options.dataType === 'text')
{
options.onSuccess(xhr.responseText)
}
if(options.dataType.toLowerCase() === 'json')
{
var result = JSON.parse(xhr.responseText)
options.onSuccess(result)
pageIndex = pageIndex + 5
}
}
}
else
{
options.onError()
}
}
xhr.open(options.type, options.url + query, true)
xhr.send()
}
客户端:
app.get('/loadMore',function(req, res){
var index = req.query.index
var len = req.query.length
var data = []
for(var i = 0; i < len; i++)
{
data.push('新闻'+ (parseInt(index)+ i))
}
res.send(data)
})
完整代码