• 第五章-浏览器


    目前的浏览器有以下几种

      IE 6~11: 对W3C支持差, 从IE10开始支持ES6

      Chrome: 谷歌的浏览器, Webkit内核, JS引擎是十分强悍的V8, 保持自动升级的模式

      Safari: 苹果的浏览器, 同样是Webkit内核

      Firefox: Mozilla自己研发的Gecko内核, JS引擎也是自己的OdinMonkey

    1 浏览器对象

      (1) window

      表示全局作用域, 也表示浏览器窗口

        window.innerWidth 显示网页的净宽度

        window.innerHeight 显示网页的净高度

        window.outerWidth 浏览器整个宽度

        window.outerHeight 浏览器整个高度

      (2) navigator

      表示浏览器信息

      

    navigator.appName:浏览器名称;

    navigator.appVersion:浏览器版本;

    navigator.language:浏览器设置的语言;

    navigator.platform:操作系统类型;

    navigator.userAgent:浏览器设定的User-Agent字符串。

      然而navigator的信息很容易就被用户修改, 所以一般不同navigator判断浏览器类型等信息

      一般判断不同的属性要抓住JavaScript对不存在的内容不是报错而是返回undefined

    var width = window.innerWidth || document.body.clientWidth;

      (3) screen  

      表示屏幕信息

      

    screen.width:屏幕宽度,以像素为单位;

    screen.height:屏幕高度,以像素为单位;

    screen.colorDepth:返回颜色位数,如8、16、24。

      (4) location

      表示当前页面的URL信息

      

      (5) document

      表示当前页面, 是整个DOM树的根节点

      

      可以根据document来获取页面的所有标签

      可以通过title来修改页面的title

      

      可以通过getElementById()和getElementsByTagName()等来获取标签对象

      document对象还有一个十分关键的cookie

      Cookie是服务器发送的键值对标识符, 浏览器通过将Cookie发送给服务器, 让服务器认识当前的浏览器, 改善HTTP无状态的情况

      由于一般JavaScript也可以读取Cookie, 这样就十分不安全, 为此可以在服务器中设置httpOnly, 这样cookie就不能被JavaScript读取了

      (6) history

      保存了浏览器的历史记录

      可以使用back()和forward()前进和后退

      但是这种简单粗暴的方式应该杜绝使用了

    2 操作DOM

      HTML文档被浏览器解析之后就是一棵DOM树

      对DOM节点有基本的四个操作: 增删改查

      (1) 常用方法

        document.getElementById() 根据Id, 获得唯一元素

        document.getElementsByTagName() 返回一组元素

        document.getElementsByClassName() CSS选择器, 返回一组元素

      (2) 通过selector选择    

        querySelector() 可以是document调用, 传入选择器参数

        querySelectorAll() 可以是获得的元素对象, 传入的同样是选择器参数

    2.1 更新DOM

      (1) 更改标签内容

        更改标签内容有三个值: innerHTML, innerText, textContent

        innerHTML是获取标签所有内容, 并且可以给其重新赋值, 赋值的内容可以包含有效标签

        

        innerText获取的是元素对象里面的文本信息, 如果给其重新赋值, 会覆盖原有内容, 不会生成有效的标签

        

        textContent与innerText差不多, 只是返回内容的值全部拼接到了一起

        

      (2) 更新标签的属性

        可以直接使用 

    标签对象.属性名 = "修改后的值"

        来直接修改内容, 如果原有内容不符合命名规则, 需要将其转化为驼峰写法

        

        PS: 添加属性使用setAttribute(属性名, 属性值)

    2.2 插入DOM

      使用innerHTML尽管可以添加一些新的标签进去, 但是会替换原有的内容

      插入DOM主要是有两个方法appendChild()insertBefore(新加入节点, 标志节点)  

      可以使用document.createElement(标签名字)来创建一个标签

      通过setAttribute()和直接操作属性, innerHTML等来修改得到标签

      给head添加style标签如下

    var d = document.createElement('style');
    d.setAttribute('type', 'text/css');
    d.innerHTML = 'p { color: red }';
    document.getElementsByTagName('head')[0].appendChild(d);
    

      新添加一个元素到python元素之前

    //原来的HTML
    //<div id="list">
    //  <p id="java">Java</p>
    //  <p id="python">Python</p>
    //  <p id="scheme">Scheme</p>
    //</div>
    
    var
        list = document.getElementById('list'),
        ref = document.getElementById('python'),
        haskell = document.createElement('p');
    haskell.id = 'haskell';
    haskell.innerText = 'Haskell';
    list.insertBefore(haskell, ref);
    
    //新增后的HTML
    //<div id="list">
    //  <p id="java">Java</p>
    //  <p id="haskell">Haskell</p>
    //  <p id="python">Python</p>
    //  <p id="scheme">Scheme</p>
    //</div>
    

    2.3 删除DOM

      删除DOM的办法是, 先获得要删除的节点, 然后获取该节点的父节点, 然后调用父节点的removeChild()删除自身

      删除后会有一个返回值, 这个返回值就是被删除的节点, 这个节点会继续保存在内存当中, 因此可以通过这个返回值可以将它放到另一个地方

      但是这又有一个十分诡异的情况:

      children属性是一个只读属性, 当子节点发生变化的时候会实时更新

      

      也就是说:

    var parent = document.getElementById('parent');
    parent.removeChild(parent.children[0]);
    parent.removeChild(parent.children[1]); // <-- 浏览器报错

      因此在删除多个节点的时候, 要注意children时刻都在变化

    3 操作表单

      表单本身也是一个DOM树, 因此对表单的操作与DOM类似

      HTML的输入控件一般有

     

    • 文本框,对应的<input type="text">,用于输入文本;

    • 口令框,对应的<input type="password">,用于输入口令;

    • 单选框,对应的<input type="radio">,用于选择一项;

    • 复选框,对应的<input type="checkbox">,用于选择多项;

    • 下拉框,对应的<select>,用于选择一项;

    • 隐藏文本,对应的<input type="hidden">,用户不可见,但表单提交时会把隐藏文本发送到服务器。

       

      (1) 一般对表单的操作是设置和获取标签的值, 一般是获得标签之后使用

    标签对象.value;
    标签对象.value = 新设置的值;

      来获取或设置

      但是例如radio这样的, 应该获取checked的值来判断状态, 一般来说勾选为true不勾选为false

      (2) 提交表单

      方法1: 设置一个提交按钮, 写触发的点击事件, 获取表单, 用 表单对象.submit() 来提交表单

    //<form id="test-form">
    //  <input type="text" name="test">
    //  <button type="button" onclick="doSubmitForm()">Submit</button>
    //</form>
    
    function doSubmitForm() {
        var form = document.getElementById('test-form');
        // 可以在此修改form的input...
        // 提交form:
        form.submit();
    }
    

      但是正常情况是使用<button type="submit">或者在某个输入框回车的时候提交表单

      方法2: 在表单中添加onsubmit属性, 里面使用"return 检验函数()", 这样在提交函数内部会有一个返回值, 当返回为true时表单提交, 返回为假时表单不提交

    //<form id="test-form" onsubmit="return checkForm()">
    //  <input type="text" name="test">
    //  <button type="submit">Submit</button>
    //</form>
    
    function checkForm() {
        var form = document.getElementById('test-form');
        // 可以在此修改form的input...
        // 继续下一步:
        return true;
    }
    

      表单注意事项:

        要提交的表单要写好name属性, 没有name属性是不会提交的, 这可以用于不传输明文密码而把原密码加密后给一个hidden的input

    4 操作文件

      唯一可以上传文件的控件是<input type="file">

      当上传文件的时候, 需要将表单的enctype设置为multipart/form-data, methodno必须设置为post

      出于安全性设计, JavaScript是无法获取文件的真实路径的, 也无法赋值, 但是可以使用value来获得假的路径, 文件名是正常的

      一般来说都是对上传的文件作一个类型判断

    var f = document.getElementById('test-file-upload');
    var filename = f.value; // 'C:fakepath	est.png'
    if (!filename || !(filename.endsWith('.jpg') || filename.endsWith('.png') || filename.endsWith('.gif'))) {
        alert('Can only upload image file.');
        return false;
    }
    

      由于JavaScript本身对文件的操作有限, 可以使用File API来获取更多文件信息和一些操作

      HTML5的File API提供了File和FileReader两个主要对象, 可以获得文件信息并读取文件 

      以DataURL的形式读取到的文件是一个字符串, 常用于设置图像, 如果服务器处理, 把字符串base64后面的字符发送给服务器并用Base64解码就可以得到原始文件的二进制内容

      JavaScript有一个十分十分十分重要的特点, 就是单线程执行模式

      也就是说, 浏览器在执行JS代码的时候总是以单线程模式执行, 任何时候JS代码都不可能同时有多余1个线程在执行

      JS处理多任务的方法是使用异步调用, 对于FileReader对象, 就需要先设置一个FileReader对象.onload为一个编写好的回调函数

      这个回调函数在FileReader对象完成文件读取之后才会执行, 这就是JS中比较神奇的异步调用了

      读入一个图片文件并将图片和图片信息显示的实例代码如下:

    var
        fileInput = document.getElementById('test-image-file'),//文件获取input
        info = document.getElementById('test-file-info'),//文件信息展示div
        preview = document.getElementById('test-image-preview');//图片展示div
    // 监听change事件:
    fileInput.addEventListener('change', function () {
        // 清除背景图片:
        preview.style.backgroundImage = '';
        // 检查文件是否选择:
        if (!fileInput.value) {
            info.innerHTML = '没有选择文件';
            return;
        }
        // 获取File引用:
        var file = fileInput.files[0];
        // 获取File信息:
        info.innerHTML = '文件: ' + file.name + '<br>' +
                         '大小: ' + file.size + '<br>' +
                         '修改: ' + file.lastModifiedDate;
        if (file.type !== 'image/jpeg' && file.type !== 'image/png' && file.type !== 'image/gif') {
            alert('不是有效的图片文件!');
            return;
        }
        // 读取文件:
        var reader = new FileReader();
        // 设置回调函数
        reader.onload = function(e) {
            var
                data = e.target.result; // 'data:image/jpeg;base64,/9j/4AAQSk...(base64编码)...'            
            preview.style.backgroundImage = 'url(' + data + ')';
        };
        // 以DataURL的形式读取文件:
        reader.readAsDataURL(file);
    });
    

    5 AJAX

      AJAX(Asynchronous JavaScript and XML) JavaScript执行异步网络请求

      web运行的原理: 一次HTTP请求对应一个页面

      如果需要停留在当前页面中, 并且还发送HTTP请求, 这就需要使用JavaScript来发送这个请求, 就收到数据后, 在用JavaScript更新页面

      现代的AJAX主要是依靠XMLHttpRequest对象, 但是对于低版本的IE, 需要使用ActiveXObjective对象

      但是判断IE版本不要使用navigator不要使用navigator不要使用navigator, 而要抓住JavaScript中的属性不存在的时候返回undefined

      一般地:

        获取到一个请求对象, 然后设置对象.onreadystatechange为一个回调函数, 再使用open()函数设置请求, 使用send()函数发送请求

      其中回调函数一般先判断 对象.readyState==4 表示请求是否完成, 再用status==200判断是否是成功响应

      对于open(), 有三个参数, 分别是发送请求方式(POST/GET), URL地址, 是否使用异步(默认为true)

      特别注意, 如果将是否使用异步设置为false, name浏览器会停止相应等待请求完成, 如果超过10秒, 浏览器就会处于一个假死状态

      具体的兼容版本代码如下:

    function success(text) {
        var textarea = document.getElementById('test-response-text');
        textarea.value = text;
    }
    
    function fail(code) {
        var textarea = document.getElementById('test-response-text');
        textarea.value = 'Error code: ' + code;
    }
    
    // 新建XMLHttpRequest或者Microsoft.XMLHTTP对象
    var request;
    if (window.XMLHttpRequest) {
        request = new XMLHttpRequest();
    } else {
        request = new ActiveXObject('Microsoft.XMLHTTP');
    }
    
    
    request.onreadystatechange = function () { // 状态发生变化时,函数被回调
        if (request.readyState === 4) { // 成功完成
            // 判断响应结果:
            if (request.status === 200) {
                // 成功,通过responseText拿到响应的文本:
                return success(request.responseText);
            } else {
                // 失败,根据响应码判断失败原因:
                return fail(request.status);
            }
        } else {
            // HTTP请求还在继续...
        }
    }
    
    // 发送请求:
    request.open('GET', '/api/categories');
    request.send();
    
    alert('请求已发送,请等待响应...');
    

      关于安全限制

      对于URL设置, 需要设置为当前页面完全一致的域名的URL, 这是浏览器的同源策略

      完全一致包括: 域名相同, 协议相同, 端口相同

      解决同源问题有三种办法:

        1) 通过Flash插件来发送HTTP请求, 但是与Flash交互不是很方便, 当下用得也少

        2) 在同源于域名下, 架设一个代理服务器, 通过该代理服务器来转发请求

    '/proxy?url=http://www.sina.com.cn'

        3) JSONP, 只能使用GET请求, 并且要求返回JavaScript, 实际上是利用浏览器允许跨域引用JavaScript资源来实现的

        具体操作方法为:

          用js添加<script>标签, 里面src就是外部的引用地址, 然后根据该js返回的内容, 设置一个回调函数(一般地, 返回值的数据名部分就是回调函数的名字)

      CORS(Cross-Origin Resource Sharing) 是HTML5规范定义的如何跨域访问资源

      当JavaScript向外域发送请求后, 浏览器会回应请求, 请求中有Access-Control-Allow-Origin字段, 如果该字段中包含了本域(或者为*), 则此次跨域请求成功

      由此可见, 跨域请求是否成功还是取决于请求的服务器是否同意此次跨域, 这也就解释了有的使用使用引用外部的字体的时候, 有可能没有引用成功导致字体设置不正常

      当然对于POST和DELETE等的POST请求, 在发送AJAX请求之前, 浏览器回先发送一个OPTIONS请求到这个URL上, 询问服务器是否接受, 且服务器相应还会给出允许的Method

    6 Promise

      JavaScript的单线程的特性也就意味着JS代码只能是异步执行, 异步执行的话就需要使用回调函数来实现具体功能

      由于在回调中, 会出现成功失败等各种情况的处理结果, 因此需要写各个情况的处理函数, 这样也不方便重用, 现在有一个类似jq中的链式写法

      可以直接在请求之后直接跟上成功和失败的处理函数, 这样就不需要考虑是否成功与失败, 直接自己调用对应的回调函数了

      Promise是封装执行代码和处理结果, 将其分离

      具体实例如下

    // 清除log:
    var logging = document.getElementById('test-promise-log');
    while (logging.children.length > 1) {
        logging.removeChild(logging.children[logging.children.length - 1]);
    }
    
    // 输出log到页面:
    function log(s) {
        var p = document.createElement('p');
        p.innerHTML = s;
        logging.appendChild(p);
    }
    
    new Promise(function (resolve, reject) {
        log('start new Promise...');
        var timeOut = Math.random() * 2;
        log('set timeout to: ' + timeOut + ' seconds.');
        setTimeout(function () {
            if (timeOut < 1) {
                log('call resolve()...');
                resolve('200 OK');
            }
            else {
                log('call reject()...');
                reject('timeout in ' + timeOut + ' seconds.');
            }
        }, timeOut * 1000);
    }).then(function (r) {
        log('Done: ' + r);
    }).catch(function (reason) {
        log('Failed: ' + reason);
    });
    

      利用Promise可以将多个设置多个异步任务, 当执行任务1之后再执行任务2, 任何一个任务失败都不会继续执行 

      另外组合使用Promise, 就可以实现异步任务以并行和串行的方式组合起来执行

    7 Canvas

      Canvas是HTML5新增的组件, 类似于幕布的效果, 可以在Canvas上绘制各种图表, 动画等

      可以在Canvas中定义一些HTML标签, 用于在有的浏览器不支持Canvas的时候显示定义好的这些标签

      Canvas标签含有属性width和height用于定义尺寸大小

      可以通过获得的Canvas对象.getContext()来判断浏览器是不是支持Canvas

      获得绘图2d或者3d对象

    Canvas对象.getContext("2d") 
    Canvas对象.getContext("webgl") 

      Canvas的二维绘图有一个坐标轴, 0点是左上角, 水平向右是x轴, 垂直向下是y轴

      具体在Canvas上绘制一个灰色背景的笑脸图像的具体代码如下

    var canvas = document.getElementById('mycanvas');
    var ctx = canvas.getContext('2d');
    ctx.clearRect(0, 0, 200, 200); // 擦除(0,0)位置大小为200x200的矩形,擦除的意思是把该区域变为透明
    ctx.fillStyle = '#dddddd'; // 设置颜色
    ctx.fillRect(10, 10, 130, 130); // 把(10,10)位置大小为130x130的矩形涂色
    // 利用Path绘制复杂路径:
    var path=new Path2D();
    path.arc(75, 75, 50, 0, Math.PI*2, true);
    path.moveTo(110,75);
    path.arc(75, 75, 35, 0, Math.PI, false);
    path.moveTo(65, 65);
    path.arc(60, 65, 5, 0, Math.PI*2, true);
    path.moveTo(95, 65);
    path.arc(90, 65, 5, 0, Math.PI*2, true);
    ctx.strokeStyle = '#0000ff';
    ctx.stroke(path);
    

      绘制文本  

    ctx.clearRect(0, 0, canvas.width, canvas.height);
    ctx.shadowOffsetX = 2;
    ctx.shadowOffsetY = 2;
    ctx.shadowBlur = 2;
    ctx.shadowColor = '#666666';
    ctx.font = '24px Arial';
    ctx.fillStyle = '#333333';
    ctx.fillText('带阴影的文字', 20, 40);
    

     

  • 相关阅读:
    工作中搜索页面搜索记录功能的封装(存储到本地)
    工作中遇到的git问题
    Git 常用命令
    帮女票做的报表(用到了angular的一些指令)
    HTML和CSS的知识点
    动画制作 手机APP制作以及响应式的实现
    CSS新内容
    JS中的循环嵌套 BOM函数
    fullpage的使用以及less, Sass的属性和JQuery自定义插件的声明和使用
    Javascript的内容
  • 原文地址:https://www.cnblogs.com/weihuchao/p/6924806.html
Copyright © 2020-2023  润新知