浏览器事件模型&请求
DOM事件
- DOM0:click事件,对每个事件只支持一个事件处理程序
- DOM1:无实际定义事件
- DOM2:
addEventListener()和removeEventListener(),
element.addEventListener(event, function, useCapture)
useCapture: true - 事件句柄在捕获阶段执行
false- 默认。事件句柄在冒泡阶段执行
举例事件捕获模式:
<div id="btn1" style="height: 150px;width: 150px;background: red;color: #fff"> btn1
<div id="btn2" style="height: 100px;width: 100px;background: green;color: #fff"> btn2 <div id="btn3" style="height: 50px;width: 50px;background: blue;color: #fff"> btn3 </div>
</div>
</div>
<script>
let btn1 = document.getElementById('btn1')
let btn2 = document.getElementById('btn2')
let btn3 = document.getElementById('btn3')
btn1.addEventListener('click',function (){ alert('btn1') },true) btn2.addEventListener('click',function (){ alert('btn2') },true) btn3.addEventListener('click',function (){ alert('btn3') },true)
</script>
//上述结果为:先弹出btn1 btn2 btn3
举例事件冒泡模式:将上述最后一个参数改为fasle即可
结果变成:btn3 btn2 btn
//如何组织? stopPropagation
通过DOM2添加的匿名函数无法移除
事件流:页面中接收事件的顺序
IE 的事件流是事件冒泡流,
Netscape Communicator的事件流是事件捕获流
DOM2级事件规定的事件流包括三个阶段:
- 事件捕获阶段;
- 处于目标阶段;
- 事件冒泡阶段;
事件委托
作用:解决事件绑定过多的一些问题
概念:将事件委托给dom树中最小的公共父节点
原理:利用事件冒泡,将事件传递给自己父元素,请父元素代为执行
浏览器请求
ajax
特点:在页面中发送请求,进行局部状态的更新,无需重载整个页面
基础知识储备:
-
onreadystatechange:监听异步对象请求状态码readyState的改变,每当readyState改变时,就会触发onreadystatechange事件; -
readyState:请求状态码,表示异步对象目前的状态,状态码从0到4:0: 表示请求未初始化,还没有调用
open();1: 服务器连接已建立,但是还没有调用
send();2: 请求已接收,正在处理中(通常现在可以从响应中获取内容头);
3: 请求处理中,通常响应中已有部分数据可用了,没有全部完成;
4: 当
readyState状态码为4时,表示请求已完成;此阶段确认全部数据都已经解析完毕,可以通过异步对象的属性获取对应数据; -
status:http状态码,表示成功的http状态码有:
xmlHttp.status >= 200 && xmlHttp.status < 300 || xmlHttp.status == 304 -
responseText:后台返回的字符串形式的响应数据;
-
responseXML:后台返回的XML形式的响应数据;
手写思路:
具体实现参考下方调用:
ajax({
type: 'GET',
url: 'http://localhost:3000/posts',
timeout: 1000,
data:{
a:1
}
success: data => {
console.log('success', data);
},
error: err => {
console.log('error', err);
},
});
-
创建异步请求的api对象(使用XMHLHttpRequest)
-
设置发送请求的方式和地址
-
发送请求
-
监听请求状态
-
处理返回值
参考如下:
const ajax = function (options) {
//处理参数
const objToString = (data) => {
data.t = new Date().getTime();
let res = [];
for (let key in data) {
//需要将key和value转成非中文的形式,因为url不能有中文。使用encodeURIComponent();
res.push(encodeURIComponent(key) + ' = ' + encodeURIComponent(data[key]));
}
return res.join('&');
};
let str = objToString(options.data || {});
//创建ajax对象
let xmlHttp;
let timer
if (window.XMLHttpRequest) {
xmlHttp = new XMLHttpRequest();
} else {
//准对低版本的ie浏览器做兼容处理
xmlHttp = new ActiveXObject('');
}
//设置请求的方式和地址
//有一个知识点:get请求相同的url,ie浏览器会存在缓存问题,会认为是相同的请求,无法拿到实时的数据
//如何解决:url中拼接时间戳
//xmlHttp.open('GET','ajax-urls'+ Math.random(),true)
if (options.type === 'GET') {
//get请求,query参数以key=value的形式拼接在url后面
xmlHttp.open('GET', options.url + '?t=' + str, true);
xmlHttp.send();
} else {
xmlHttp.open('POST', options.url, true);
xmlHttp.send(str);
xmlHttp.setRequestHeader(
'Content-type',
'application/x-www-form-urlencoded'
);
}
//监听返回值变化
xmlHttp.onreadystatechange = () => {
if (xmlHttp.readyState === 4) {
clearInterval(timer)
if ((xmlHttp.status >= 200 && xmlHttp.status < 300) ||xmlHttp.status == 304) {
//成功处理
options.success(xmlHttp.responseText);
} else {
//失败处理
options.error(xmlHttp.responseText);
}
}
};
if (options.time) {
timer = setInterval(()=>{
xmlHttp.abort(); //中断请求
clearInterval(timer);
},options.time)
}
};
fetch
概念:Fetch 是在 ES6 出现的,它使用了 ES6 提出的 Promise 对象。它是 XMLHttpRequest 的替代品。
用法示例:
fetch(url)
.then(...)
.catch(...)