浏览器事件

83 阅读3分钟

浏览器事件模型&请求

DOM事件

  1. DOM0:click事件,对每个事件只支持一个事件处理程序
  2. DOM1:无实际定义事件
  3. 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

特点:在页面中发送请求,进行局部状态的更新,无需重载整个页面

基础知识储备:

  1. onreadystatechange:监听异步对象请求状态码readyState的改变,每当readyState改变时,就会触发onreadystatechange事件;

  2. readyState:请求状态码,表示异步对象目前的状态,状态码从0到4:

    0: 表示请求未初始化,还没有调用 open()

    1: 服务器连接已建立,但是还没有调用 send()

    2: 请求已接收,正在处理中(通常现在可以从响应中获取内容头);

    3: 请求处理中,通常响应中已有部分数据可用了,没有全部完成;

    4: 当readyState状态码为4时,表示请求已完成;此阶段确认全部数据都已经解析完毕,可以通过异步对象的属性获取对应数据;

  3. status:http状态码,表示成功的http状态码有:xmlHttp.status >= 200 && xmlHttp.status < 300 || xmlHttp.status == 304

  4. responseText:后台返回的字符串形式的响应数据;

  5. 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);
  },
});
  1. 创建异步请求的api对象(使用XMHLHttpRequest)

  2. 设置发送请求的方式和地址

  3. 发送请求

  4. 监听请求状态

  5. 处理返回值

参考如下:

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(...)