美文网首页
浏览器相关内容

浏览器相关内容

作者: 大南瓜鸭 | 来源:发表于2021-07-21 10:53 被阅读0次

    一、浏览器内置对象

    • 什么是浏览器对象模型

    BOM :Browser Object Model(浏览器对象模型),浏览器模型提供了独立于内容的、可以与浏览器窗口进行滑动的对象结构,就是浏览器提供的 API

    其主要对象有:

    1. window 对象——BOM 的核心,是 js 访问浏览器的接口,也是 ES 规定的 Global 对象
    2. location 对象:提供当前窗口中的加载的文档有关的信息和一些导航功能。既是 window 对象属性,也是 document 的对象属性
    3. navigation 对象:获取浏览器的系统信息,navigation 接口表示用户代理的状态和标识,允许脚本查询它和注册自己进行一些活动
    4. screen 对象:用来表示浏览器窗口外部的显示器的信息等
    5. history 对象:保存用户上网的历史信息

    二、浏览器事件模型

    浏览器事件模型中的过程主要分为三个阶段:捕获阶段、目标阶段、冒泡阶段。

    1、事件传播

    • 第三个参数:addEventListener的第三个参数, 如果为true,就是代表在捕获阶段执行。如果为false,就是在冒泡阶段进行,默认为true
    • 阻止后续事件传播:e.stopPropagation();e.stopImmediatePropagation() 阻止事件冒泡并且阻止该元素上同事件类型的监听器被触发
    • 阻止默认行为:e.preventDefault()
    • 兼容性:attachEvent——兼容:IE7、IE8; 不支持第三个参数来控制在哪个阶段发生,默认是绑定在冒泡阶段;addEventListener——兼容:firefox、chrome、IE、safari、opera

    2、实现一个事件委托

    const ul = document.querySelector("ul");
    ul.addEventListener('click', function (e) {
        const target = e.target;
      if (target.tagName.toLowerCase() === "li") {
        const liList = this.querySelectorAll("li");
        index = Array.prototype.indexOf.call(liList, target);
        alert(`内容为${target.innerHTML}, 索引为${index}`);
      }
    })
    

    3、封装一个多浏览器兼容的绑定事件函数

    class BomEvent {
        constructor(element) {
            this.element = element;
        }
    
        addEvent(type, handler) {
            if (this.element.addEventListener) {
                //事件类型、需要执行的函数、是否捕捉
                this.element.addEventListener(type, handler, false);
            } else if (this.element.attachEvent) {
                this.element.attachEvent('on' + type, function () {
                    handler.call(element);
                });
            } else {
                this.element['on' + type] = handler;
            }
        }
    
        removeEvent(type, handler) {
            if (this.element.removeEnentListener) {
                this.element.removeEnentListener(type, handler, false);
            } else if (element.datachEvent) {
                this.element.detachEvent('on' + type, handler);
            } else {
                this.element['on' + type] = null;
            }
        }
    }
    // 阻止事件 (主要是事件冒泡,因为IE不支持事件捕获)
    function stopPropagation(ev) {
        if (ev.stopPropagation) {
            ev.stopPropagation(); // 标准w3c
        } else {
            ev.cancelBubble = true; // IE
        }
    }
    // 取消事件的默认行为
    function preventDefault(event) {
        if (event.preventDefault) {
            event.preventDefault(); // 标准w3c
        } else {
            event.returnValue = false; // IE
        }
    }
    

    三、浏览器请求相关

    1、ajax 及 fetch

    XMLHTTPRequest
    let xhr = new XMLHttpRequest();
    xhr.open('GET', 'http://domain/service');
    
    // request state change event
    xhr.onreadystatechange = function () {
        // request completed?
        if (xhr.readyState !== 4) return;
    
        if (xhr.status === 200) {
            // request successful - show response
            console.log(xhr.responseText);
        } else {
            // request error
            console.log('HTTP error', xhr.status, xhr.statusText);
        }
    };
    
    // xhr.timeout = 3000; // 3 seconds
    // xhr.ontimeout = () => console.log('timeout', xhr.responseURL);
    
    // progress事件可以报告长时间运行的文件上传
    // xhr.upload.onprogress = p => {
    //     console.log(Math.round((p.loaded / p.total) * 100) + '%');
    // }
    
    // start request
    xhr.send();
    
    fetch:
    • 默认不带cookie
    • 错误不会reject
    • 不支持超时设置
    • 需要借用AbortController中止fetch
    fetch(
            'http://domain/service', {
                method: 'GET'
            }
        )
        .then(response => response.json())
        .then(json => console.log(json))
        .catch(error => console.error('error:', error));
    
    // 默认不带cookie
    
    fetch(
        'http://domain/service', {
            method: 'GET',
            credentials: 'same-origin'
        }
    )
    
    // 错误不会reject
    // HTTP错误(例如404 Page Not Found 或 500 Internal Server Error)不会导致Fetch返回的Promise标记为reject;.catch()也不会被执行。
    // 想要精确的判断 fetch是否成功,需要包含 promise resolved 的情况,此时再判断 response.ok是不是为 true
    
    fetch(
            'http://domain/service', {
                method: 'GET'
            }
        )
        .then(response => {
            if (response.ok) {
                return response.json();
            }
            throw new Error('Network response was not ok.');
        })
        .then(json => console.log(json))
        .catch(error => console.error('error:', error));
    
    // 不支持直接设置超时, 可以用promise
    function fetchTimeout(url, init, timeout = 3000) {
        return new Promise((resolve, reject) => {
            fetch(url, init)
                .then(resolve)
                .catch(reject);
            setTimeout(reject, timeout);
        })
    }
    
    // 中止fetch
    const controller = new AbortController();
    
    fetch(
            'http://domain/service', {
                method: 'GET',
                signal: controller.signal
            })
        .then(response => response.json())
        .then(json => console.log(json))
        .catch(error => console.error('Error:', error));
    
    controller.abort();
    

    2、常见的浏览器请求/响应头/错误码

    request header
    • Accept-Charset 用于指定客户端接受的字符集
    • Accept-Encoding 用于指定可接受的内容编码,如Accept-Encoding:gzip.deflate
    • Accept-Language 用于指定一种自然语言,如Accept-Language:zh-cn
    • Host 用于指定被请求资源的Internet主机和端口号,如Host:www.chaojijuhui.com
    • User-Agent 客户端将它的操作系统、浏览器和其他属性告诉服务器l
      Connection 当前连接是否保持,如Connection: Keep-Alive
    response header
    • Server 使用的服务器名称,如Server: Apache/1.3.6 (Unix)
    • Content-Type 用来指明发送给接收者的实体正文的媒体类型,如Content-Type:text/html;charset=GBK
    • Content-Encoding 与请求报头Accept-Encoding对应,告诉浏览器服务端采用的是什么压缩编码-一般写全站压缩的时候需要用到的
    • Content-Language 描述了资源所用的自然语言,与Accept-Language对应
    • Content-Length 指明实体正文的长度,用以字节方式存储的十进制数字来表示
    • Keep-Alive 保持连接的时间,如Keep-Alive: timeout=5, max=120
    status
    • 200 get 成功
    • 201 post 成功
    • 301 永久重定向
    • 302 临时重定向
    • 304 协商缓存 服务器文件未修改
    • 400 客户端请求有语法错误,不能被服务器识别
    • 403 服务器受到请求,但是拒绝提供服务,可能是跨域
    • 404 请求的资源不存在
    • 405 请求的method不允许
    • 500 服务器发生不可预期的错误

    3、封装一个多浏览器兼容的请求函数

     interface IOptions {
        url: string;
        type?: string;
        data: any;
        timeout?: number;
    }
    
    function formatUrl(json) {
        let dataArr = [];
        json.t = Math.random();
        for (let key in json) {
            dataArr.push(`${key}=${encodeURIComponent(json[key])}`)
        }
        return dataArr.join('&');
    }
    
    export function ajax(options: IOptions) {
        return new Promise((resolve, reject) => {
            if (!options.url) return;
    
            options.type = options.type || 'GET';
            options.data = options.data || {};
            options.timeout = options.timeout || 10000;
        
            let dataToUrlstr = formatUrl(options.data);
            let timer;
        
            // 1.创建
            let xhr;
            if ((window as any).XMLHttpRequest) {
                xhr = new XMLHttpRequest();
            } else {
                xhr = new ActiveXObject('Microsoft.XMLHTTP');
            }
        
            if (options.type.toUpperCase() === 'GET') {
                // 2.连接
                xhr.open('get', `${options.url}?${dataToUrlstr}`, true);
                // 3.发送
                xhr.send();
            } else if (options.type.toUpperCase() === 'POST') {
                // 2.连接
                xhr.open('post', options.url, true);
                xhr.setRequestHeader('ContentType', 'application/x-www-form-urlencoded');
                // 3.发送
                xhr.send(options.data);
            }
        
            // 4.接收
            xhr.onreadystatechange = () => {
                if (xhr.readyState === 4) {
                    clearTimeout(timer);
                    if (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304) {
                        resolve(xhr.responseText);
                    } else {
                        reject(xhr.status);
                    }
                }
            }
        
            if (options.timeout) {
                timer = setTimeout(() => {
                    xhr.abort();
                    reject('超时');
                }, options.timeout)
            }
    
            // xhr.timeout = options.timeout;
            // xhr.ontimeout = () => {
            //     reject('超时');
            // }
        });
    }
    

    相关文章

      网友评论

          本文标题:浏览器相关内容

          本文链接:https://www.haomeiwen.com/subject/oyfjmltx.html