当前位置:   article > 正文

浏览器相关 | 事件模型 | ajax和fetch API详解

浏览器相关 | 事件模型 | ajax和fetch API详解

1.什么是浏览器对象模型

BOM :Browser Object Model(浏览器对象模型),浏览器模型提供了独⽴于内容的、可以与浏览器

窗⼝进⾏滑动的对象结构,就是浏览器提供的 API

其主要对象有:

  1. window 对象——BOM 的核⼼,是 js 访问浏览器的接⼝,也是 ES 规定的 Global 对象

  2. location 对象:提供当前窗⼝中的加载的⽂档有关的信息和⼀些导航功能。既是 window 对象属

性,也是 document 的对象属性

  1. navigation 对象:获取浏览器的系统信息

  2. screen 对象:⽤来表⽰浏览器窗⼝外部的显⽰器的信息等

  3. history 对象:保存⽤⼾上⽹的历史信息

2.浏览器事件

浏览器事件模型中过程分为三个阶段:捕获阶段、目标阶段、冒泡阶段,事件的流转顺序为捕获阶段 -> 目标阶段 ->冒泡阶段,捕获阶段为从外向内捕获,冒泡阶段为从内向外冒泡

通常有以下几种方式触发事件

<button onclick="buttonClick()">按钮</button>
  • 1
<button id="button">按钮</button>
<script>
    var btn = document.getElementById('button');
    btn.onclick = function(){
    	//TODO 一些事情
    };
</script>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
<button id="button">按钮</button>
<script>
    const btn = document.getElementById('button');
    btn.addEventListener('click',function(e){
        //TODO 一些事情
    },false)
</script>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

第三种就是事件监听,也就是我们所说的事件模型的捕获阶段,冒泡阶段,其中第三个参数true表示捕获阶段,false表示冒泡阶段,默认不传为false,下面来看个例子。

<div id="parent" class="flex-center">
    parent
    <p id="child" class="flex-center">
        child
        <span id='son' class="flex-center">
            son
        </span>
    </p>
</div>
<script>
const parent = document.getElementById("parent");
const child = document.getElementById("child");
const son = document.getElementById("son");
window.addEventListener("click", function (e) {
    // e.target.nodeName 指当前点击的元素, e.currentTarget.nodeName绑定监听事件的元素
    console.log("window 捕获", e.target.nodeName, e.currentTarget.nodeName);
}, true);

parent.addEventListener("click", function (e) {
    // e.stopPropagation();

    // e.target.nodeName 指当前点击的元素, e.currentTarget.nodeName绑定监听事件的元素
    console.log("parent 捕获", e.target.nodeName, e.currentTarget.nodeName);
}, true);

child.addEventListener("click", function (e) {
    console.log("child 捕获", e.target.nodeName, e.currentTarget.nodeName);
}, true);

son.addEventListener("click", function (e) {
    console.log("son 捕获", e.target.nodeName, e.currentTarget.nodeName);
}, true);

window.addEventListener("click", function (e) {
    // e.target.nodeName 指当前点击的元素, e.currentTarget.nodeName绑定监听事件的元素
    console.log("window 冒泡", e.target.nodeName, e.currentTarget.nodeName);
}, false);

parent.addEventListener("click", function (e) {
    console.log("parent 冒泡", e.target.nodeName, e.currentTarget.nodeName);
}, false);

child.addEventListener("click", function (e) {
    console.log("child 冒泡", e.target.nodeName, e.currentTarget.nodeName);
}, false);

son.addEventListener("click", function (e) {
    console.log("son 冒泡", e.target.nodeName, e.currentTarget.nodeName);
}, false);
</script>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50

当我点击son时候,上述的输出顺序依次为

window 捕获 SPAN undefined
parent 捕获 SPAN DIV
child 捕获 SPAN P
son 捕获 SPAN SPAN
son 冒泡 SPAN SPAN
child 冒泡 SPAN P
parent 冒泡 SPAN DIV
window 冒泡 SPAN undefined

target与currentTarget如备注描述,为什么要讲这两个,因为涉及到接下来的事件委托

运用事件模型的流转来写一个事件委托

<ul id="ul">
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
    <li>6</li>
    <li>7</li>
    <li>8</li>
</ul>
<script>
    const ul = document.querySelector('ul');
    ul.addEventListener('click',function(e){
        const target = e.target;
        if(target.tagName.toLowerCase() === "li") {
            const liList = document.querySelectorAll('li');
            const index = Array.prototype.indexOf.call(liList,target);
            alert(`内容为${target.innerHTML},索引为${index}`);
        }
    })
</script>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

3.ajax 及 fetch API 详解

ajax底层使用的是XMLHttpRequest,fetchXMLHttpRequest 非常类似,都是用来做网络请求。但是同复杂的XMLHttpRequest的API相比,fetch使用了Promise,这让它使用起来更加简洁,从而避免陷入”回调地狱”。

1.使用XMLHttpRequest实现一个请求

let xhr = new XMLHttpRequest();
xhr.open('GET', 'http://localhost:3000/test');

xhr.onreadystatechange = function () {
    if(xhr.status !== 4) return;

    if(xhr.status === 200 || xhr.status === 304){
        console.log(xhr.responseText);
    }else{
        console.log('HTTP Request Error',xhr.status,xhr.statusText);
    }
}

xhr.timeout = 3000;
xhr.ontimeout = function() {
    console.log('request timeout',xhr.responseURL);
}
xhr.send();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

2.使用fetch实现一个请求

(1).fetch没有超时时间

(2).默认不带cookie

(3).错误不会reject

(4).需要借用AbortController中止fetch

fetch('http://localhost:3000/test',{method:'GET'})
	.then(response=>response.json())
	.then(json=>console.log(json))
	.catch(error=>console.error('报错信息:',error));
  • 1
  • 2
  • 3
  • 4

3.为fetch设置超时设置,超时后中止请求

const fetchAbsortTimeout = (url,options,timeout=3000) => {
    const controller = new AbortController();
    options.signal = controller.signal;
    return new Promise((resolve,reject)=>{
        fetch(url,options)
            .then(response=>response.json)
            .then(resolve)
            .catch(reject)
        setTimeout(()=>{
            controller.abort();
            reject('超时!')
        },timeout)
    })
}

const requestOptions = {method:'GET'};
fetchAbsortTimeout('http://localhost:3000/test',requestOptions,3000)
    .then(json=>{console.log(json)})
    .catch(reason=>{console.log('报错信息:',reason)})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

△4.衍生一下,写一个通用的异步函数超时处理

const asyncTimeout = (asyncFn,timeout = 3000) =>{
    return new Promise((resolve,reject) => {
        try{
            asyncFn().then(res=>{resolve(res)})
        } catch (e) {
            throw e;
        }
        setTimeout(()=>{reject()},timeout);
    })
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/148417
推荐阅读
相关标签
  

闽ICP备14008679号