常用浏览器API整理

面向对象编程,目前还是主流,个人也比较喜欢细化组件、切割对象.这样看起来比较清晰、每个对象职责单一,不会混淆造成混乱.

前端经?;岷弯榔鞔蚪坏?在处理一些与浏览器相关的逻辑时,就会调用浏览器API,整理日常会用到的API对象.

URL

构造、解析、规范化和编码URL.

创建URL对象

构造参数说明

  • url 如果是绝对URL地址,则忽略第二个参数;如果是相对路径,则以base作为基准URL.

  • base 基准URL,如果第一个参数url是绝对URL时,则不生效.


// 指定绝对ULR地址

const url = new URL('http://www.baidu.com')

// 或者

const url = new URL('','http://www.baidu.com')

// 存在路径时

const url = new URL('http://www.baidu.com/hello')

// 或

const url = new URL('/hello','http://www.baidu.com')

构造完的url实例对象有哪些属性呢 , 可以从图中获取该url地址中所有的数据信息:

origin\searchParams 为只读属性 , 其他的属性则可以通过变量赋值进行设置.

image-20210821141202812.png

修改相关属性:


// 修改协议

url.protocol = "ftp:"        // href: 'ftp://www.baidu.com/hello',

// 修改路径

url.pathname = '/admin'      // href: 'ftp://www.baidu.com/admin',

// 追加hash

url.hash = 'app'            // href: 'ftp://www.baidu.com/admin#app',

实例方法

  • toString() 返回整个URL地址

  • toJSON() , 返回整个URL地址,同url.href

以为有啥不一样的地方,发现都是返现url地址.

还有静态方法,创建一个唯一的资源地址链接:

  • createObjectURL() File、Blog或MediaSource 对象,返回唯一的blog链接.

  • revokeObjectURL() 销毁之前createObjectURL的URL实例对象.


// File 对象,或者blob数据

const dataUrl = URL.createObjectURL('blob:**')

// 销毁创建的实例 , 访问失效

URL.revokeObjectURL(dataUrl)

URLSearchParams 对象

这个应该是我们经?;嵊玫降?用于处理url的查询字符串.

在实例url中,存在searchsearchParams(只读)


// url实例追加一个查询条件

url.search = 'id=45'

// 重新读取时会包含 ? 注意

console.log(url.search)      // ?id=45

// 获取实例URL的查询参数对象

const searchParams = url.searchParams

创建实例
  • 可选的参数 传入会被解析,比如?id=45 \ id=45 会忽略开头的 ?

const searchParams = new URLSearchParams()

// ?id=45

const searchParams = new URLSearchParams("?id=45")    // { 'id' => '45' }

// id=45&name=admin

const searchParams = new URLSearchParams("id=45&name=321")    // { 'id' => '45', 'name' => '321' }

// [['id',45],['name','admin']]

const searchParams = new URLSearchParams([['id',45],['name',"admin"]])

// {'id':45,'name':'admin'}

const searchParams = new URLSearchParams({'id':45,'name':'admin'})

实例化的好处在于可以方便管理,比如添加、删除、查找等,通过实例方法很方便的管理数据.

实例方法
  • append(name,value) - 添加一个数据

  • delete(name) - 删除指定参数名的数据

  • entries() - 迭代遍历键/值对的对象.

  • get(name) - 获取到指定参数名的第一个值.

  • getAll(name) - 返回指定参数名的所有值,数组

  • has(name) - 判断是否存在某个参数.

  • keys() - 所有参数的键的迭代对象.

  • set(name,value) - 设置某个参数的值.

  • sort() - 按键名排序.

  • toString() - 返回查询字符串.

  • values() - 包含所有值的迭代对象.


const searchParams = new URLSearchParams()

// 追加一个参数

searchParams.append("id","sv2341")      // { 'id' => 'sv2341' }

// 判断是否包含某个参数

searchParams.has("name")          // false

// 获取指定参数的值

searchParams.get("id")              // sv2341

// 获取所有参数的值

[...searchParams.values()]        // ['sv2341']

//

searchParams.toString();        //.

处理URL地址参数

不需要自己再去分隔字符串处理查询参数了,通过searchParams对象优雅处理查询参数,方便多了.


// 获取实例URL的查询字符串对象

const searchParams = url.searchParams

// 追加一个name查询参数

searchParams.append('name','admin')        // href: 'ftp://www.baidu.com/admin?id=45&name=admin#app',

如果是实例化的新的URLSearchParams , 则复制给url对象属性search


const url = new URL('http://www.baidu.com/hello')

// 新实例化的对象

const searchParams = new URLSearchParams()

searchParams.append("id","sv2341")

searchParams.append("name","test")

// 设置查询参数

url.search = searchParams            // href: 'http://www.baidu.com/hello?id=sv2341&name=test',

无法处理hash与pathname的位置顺序

让人头疼的是hashpathname 的位置,hash设置总是在pathname \ search 后面


const url = new URL('http://www.baidu.com')

// 赋值hash

url.hash = '/'

// 赋值路径

url.pathname = '/app'

// 赋值查询条件

url.search = 'id=45'

结果展示为http://www.baidu.com/app?id=45#/ 怎么调试也没能改变, 我想要的结果是http://www.baidu.com/#/app?id=45

不然重新打开一个新的tab页时,会导航到初始主路由 :cry:

所以只能去重新拼接一下URL地址:


const url = new URL('http://www.baidu.com/#/app')

const searchParams = new URLSearchParams()

searchParams.append("id","sv2341")

searchParams.append("name","test")

// 打开新的tab页面

window.open(url.toString()+"?"+searchParams.toString()) // http://www.baidu.com/#/app?id=sv2341&name=test

File

处理文件相关的信息.访问文件中的数据. UTF8编码

构造实例

参数定义:

  • bits 定义的文件内容,包含ArrayBuffer\ArrayBufferView\Blob\DOMString[]等类型

  • name 文件名称,可以追加路径.

  • options 可选的配置项

    • type - 文件MIME类型 ,默认‘’

    • lastModified 文件修改的时间


const file = new File(bits,name,options)

可访问的属性,都为只读属性:

  • lastModified - 文件最后的修改时间

  • name - 文件名称

  • size - 文件大小

  • type - 文件类型

实例方法

自身没有定义方法,继承自Blob接口,可选的参数定义:

  • slice(start,end,contentType) - 返回一个新的Blob对象,原始的一段数据.

// 自定义文本内容

const file = new File(['hello world','luck for you'],'test.txt')

FileReader

上述只是定义个一个文件对象,我们要读取到文件的内容,则需要FileReader 对象读取数据.

构造实例

const fileReader = new FileReader();

可访问的属性:

  • error - 读取文件时发生的错误

  • readyState - 取值状态, 0-未加载任何数据; 1-数据正在加载; 2-已读取完成.

  • result - 读取到的文件内容.

实例方法

定义实例,则可以用来读取文件,文件的读取是一个异步过程. 那么异步就会存在异步流程,对应着不同的事件.

先看一下实例定义的方法:

  • abort() 中止读取操作

  • readAsArrayBuffer() 读取内容以ArrayBuffer格式保存数据.

  • readAsDataURL() 读取内容,返回格式为data:base64数据

  • readAsText() 读取内容,返回的内容为字符串.

可以继续之前的文件数据读取;


// 定义文件对象

const file = new File(['hello world','luck for you'],'test.txt')

// 定义文件读取的实例对象

const fileReader = new FileReader()

// 通过onload事件回调获取到文件内容

fileReader.onload = function(event){

    console.log(event.target.result)        // hello worldluck for you

}

// 读取文件为字符串

fileReader.readAsText(file)

这里是所有的事件:

  • onabort 中断读取时触发.

  • onerror 读取操作发生错误触发.

  • onload 读取完成时触发.

  • onloadstart 读取开始时触发

  • onloadend 读取结束触发,成功或者失败

  • onprogress 读取Blob对象时触发

定义文件下载

通常前端会处理一些简单的文件下载,比如文本、图片之类的. 会使用a标签进行下载处理


// 完成简单的自定义.txt文件下载

const file = new File(['hello world'],'test.txt')

// 定义读取文件对象

const fileReader = new FileReader()

// 读取文件

fileReader.onload = function(event){

    // 定义a标签,追加到body中,点击进行下载

    let a = document.createElement('a')

    a.download = 'hello.txt'

    a.href = event.target.result

    a.textContent = '下载'

    document.body.append(a)

}

// a标签下载接受的格式blob:或者data:

// 定义读取base64 格式的数据

fileReader.readAsDataURL(file)

可以读取远程的URL地址文件信息,在前端实现下载.

通常自定义实现的下载,不需要去点击,启动触发下载事件


// 通过click方法模拟点击事件,触发下载

a.click()

// 定义a标签不可见

a.style.display = 'none'

通过URL.createObjectURL定义文件下载

上述可以通过FileReader来读取文件内容,也可以通过URL静态方法创建blob:格式的URL对象,指向源内容.


// 创建文件内容ULR

const dataUrl = URL.createObjectURL(file)

// 构建下载

let a = document.createElement('a')

a.download = 'hello.txt'

a.href = dataUrl

a.textContent = '下载'

a.style.display = 'none'

document.body.append(a)

a.click();

准备写一下文件的上传、下载;主要是断点续传、分片上传等;先立个flag吧,不知道啥时候写完. :dog:

Image

常用的展示形式-图片,不可或缺. 通常的网站并不会处理图片,拿到ULR地址,直接做展示就好.如果是一个专门处理图片的工程的话, 就会对图片各方面处理要求的多. 通常先获取到图片的大小,初始画布等.

构造实例

实例同等于html元素img, 接受参数

  • width 宽度

  • height 高度


const img = new Image()

// 等同于

img = document.createElement('img')

可访问属性:

  • alt 描述内容

  • complete 表示加载正常,没有发生错误.

  • crossOrigin 跨域设置

  • currentSrc 表示正在加载图像的URL.

  • decoding 图片的加载后的解码设置

  • height css渲染的高度

  • width css渲染的宽度

  • isMap 是否是某一图片映射的一部分

  • naturalHeight图片固有高度;不同于实际展示大小可能会受CSS影响.

  • naturalWidth 图片固有宽度;不同于实际展示大小可能会受CSS影响.

  • referrerPolicy 定时告诉用户如何获取图片资源

  • src 图像完整的URL

  • useMap 定义引用map 元素#开头

  • srcset 候选图像列表,逗号分隔; w表示图像宽度,x 表示图像密度

  • sizes 定义图像特定现实的大小;


// 定义实例

const img = new Image(150,160)

img.src = './test.png'

// 定义了宽度、高度,则可以直接获取到属性 img.width img.height

img.onload = function(){

  // 要获取实际的图片的大小,则必须等待图片加载完成

  // img.naturalWidth,img.naturalHeight

}

// 可以像普通的img标签添加到页面中

document.body.appendChild(img)

实例方法

基本没什么主要的方法提供调用,

  • decode() 用于解码加载图片的帧,安全的加载到DOM中。返回一个promise

继承自HTMLELement接口,拥有常规DOM的事件

  • onload 加载完成

  • onerror 加载错误时,触发调用。


// 主要是onload 加载完成获取到实际图片的大小信息

img.onload = function(){

  // 要获取实际的图片的大小,则必须等待图片加载完成

  // img.naturalWidth,img.naturalHeight

}

创建实例时,没有指定大小,img.widht/img.hegiht即是图片的真实大小。

响应式图片大小

现在的电子设备越来越多,屏幕大小、分隔各不相同,设计网站展示想达到完美的展示效果,则必须创建适合各个大小屏幕分隔的图片进行展示.

使用图片的srcset \ sizes定义图片资源


<img srcset="1.png 500w,

            2.png 800w,

            3.png 1200w"

    sizes="(max-width:520px) 500px,

            (max-width:820px) 800px,

            1200px"

    alt="图像"

  />

检测设备宽度, 检查符合条件的sizes列表媒体查询;获取到定义的展示图片的大小,从srcset加载到最符合size大小的图像进行展示.

可以通过定义srcset x 不同的分辨率;

MutationObserver

提供了监视对DOM树所做更改的能力 ,

这个是在vue指令滚动加载的时候看到源码里写的,之后就业务功能中也会使用它做一些加载的优化处理.

构造实例

  • 参数为回调 , 即指定的节点或子节点发生dom变动时别调用.

    • 回调第一个参数为变动的MutationRecord 对象数组.

    • 实例对象observer


// 实例化observer对象

const observer = new MutationObserver(handlerChange)

// 配置监听的dom,以及监听哪些属性的变动配置

const options = {

  childList:true, // 观察子节点的变化,添加或删除

  attributes:true, // 观察属性变动

  subtree:true, // 观察子孙节点

}

// 监听

observe.observe(document.querySelector("#app"),options)

// 回调事件

const handlerChange = function(mutationList,observer){

  // 触发变动的节点、属性

}

实例方法

  • observe(dom,options) - 配置监听的DOM给定选项更改时,调用回调函数

    
    const options = {
    
      attributeFiter:[], // 设置监听指定属性,比如width、height等.不设置则监听所有属性.
    
      attributeOldValue:true, // 观察节点属性变更时,记录旧值
    
      attributes:true, // 观察节点属性的变更
    
      characterData:true, // 监听文本节点文本的变化
    
      characterDataOldValue:true, // 监听文本节点,记录文本节点旧值
    
      childList:true, // 观察子孙节点的添加、删除更改
    
      subtree:true, // 观察子孙节点、属性等所有的变化
    
    }
    
    

    多次调用监听方法,会移除现有的观察目标的监听; 如果没有指定DOM,则保留现有的观察目标,并添加新的观察者.

  • disconnect() - 停止监听DOM,回调不会在调用

  • takeRecords() - 删除所有待处理的变更通知.

滚动加载时加载初始数据

之前看到element的滚动加载的指令v-infinite-scroll , 在初始加载数据时,使用API监听子节点的变化,从而加载让数据内容去出现滚动条为止. 我们的滚动加载必须要有滚动条才能出发滚动事件.

(当然我们可以通过递归回调的方式判定数据区的offsetHeight/clientHeight 对比是否出现滚动条,进而追加数据)

但自动触发处理逻辑岂不更好 :smile:


let id = 0

// 加载数据的方法

function loadChild(){

    id++;

    let p = document.createElement('p')

    p.textContent = `数据id${id}`

    //

    dom.appendChild(p)

}

// 实例化observer对象

const observer = new MutationObserver(function(){

    // 触发之后,添加子节点

    loadChild()

    // 判断是否出现了滚动条,

    // 有滚动条了则不需要监听DOM 了

    if(dom.scrollHeight > dom.clientHeight){

        // 存在滚动条

        if(observer){

            observer.disconnect();

            observer = null;

        }

    }

})

// 配置监听的dom,以及监听哪些属性的变动配置

const options = {

    childList: true, // 观察子节点的变化,添加或删除

    attributes: false, // 观察属性变动

    subtree: false, // 观察子孙节点

}

// 监听

let dom = document.querySelector(".list-box");

observer.observe(dom, options)

// 初始调用一次

loadChild();

// 然后是正常的scroll 事件监听

dom.addEventListener('scroll',function(){

    // 滚动距离+可视高度 <= 内容区高度-20 追加数据

    let scrollBottom = dom.scrollTop + dom.clientHeight

    if(dom.scrollHeight - scrollBottom <= 20){

        loadChild();

    }

})

为了初始触发目标节点的变动,需要手动调用一次数据加载函数loadChild() , 当添加第一条数据后,DOM监听回调开始执行 ;一直到出现滚动条(可视高度不等于内容区域高度时)停止检测.

正常的scroll事件被监听,滚动到底部距离小于20(阀值)时,触发数据加载函数;

数据加载完成时,可以在loadChild函数中增加取消滚动事件,停止滚动加载时间触发.

MutationRecord

监听DOM 变更后回调第一个参数.

  • type - 变更的类型, 属性-attributes;节点文本变化 - characterData; 子节点变化 - childList

  • target - 变更的目标节点

  • addedNodes - 被添加的节点NodeList

  • removedNodes - 被移除的节点NodeList

  • oladValue - 变更前的旧值记录,需要配置属性才会有;

  • ...

FormData

提供处理form表单数据的功能,form表单处理在日??⒅写Υ杉O衷诘那岸丝蚣馨镂液芎玫拇砹苏庖晃侍?,必要的学习了解还是必须的。

构造实例

  • 参数为 form标签dom对象,非必选。

//

const form = new FormData()

当我们传入form 参数时,每个form元素都需要name属性,这是必须的?;嶙远淼ブ敌蛄谢?/p>


// 指定form元素,同步获取到表单里的表单属性、值。

const form = new FormData(document.querySelector('#form'))

实例方法

  • append() key/value 新增键值对,如果存在key,则新增一个值

  • delete() 删除指定键

  • entries() 所有键值对的迭代对象

  • get() 获取到指定键的第一个值

  • getAll() 返回指定键的包含所有值的数组

  • has() 是否包含某个键

  • keys() 所有属性键的迭代对象

  • set() 设置属性值,覆盖原有的值

  • valuse() 返回包含所有属性值得迭代对象


<form id="form">

    <div class="form-item">

        <label>姓名</label>

        <input type="text" name="name" value="admin" placeholder="输入姓名" />

    </div>

    <div class="form-item">

        <label>年龄</label>

        <input type="number" min="0" name="age" value="23" max="200" step="1" />

    </div>

    <div class="form-item">

        <label>性别</label>

        <input type="radio" name="gender" value="1" checked>男

        <input type="radio" name="gender" value="2">女

    </div>

</form>

定义的form表单,创建FormData实例后,操作表单元素,并可增加新的属性。


// 所有属性 ,按照表单元素的name属性序列化

form.keys()        // [...keys] - result:["name", "age", "gender"]

// 查找某个值

form.has('id')          // false

// 添加一个值,重复的name属性

form.append('name','test')       

form.get('name')              // 返回第一个符合的值, 为 admin

form.getAll('name')              // 返回所有的值得数组, ['admin','test']

XMLHttpRequest发送数据

创建一个ajax实例,发送请求。


// 直接发送数据

const xhr = new XMLHttpRequest()

xhr.open('post','/addUserInfo')

xhr.send(form)

使用File 创建文件,上传文件。


// 创建文件对象

const file = new File(['hello world'],'test.txt')

// 定义文件读取的实例对象

const fileReader = new FileReader()

// 定义请求实例

const xhr = new XMLHttpRequest()

// 通过onload事件回调获取到文件内容

fileReader.onload = function(event){

    // 读取到文件blob数据

    form.append('file',event.target.result)

    xhr.open('post','/addUserInfo')

    xhr.send(form)

}

// 读取文件为字符串

fileReader.readAsDataURL(file)

作为URLSearchParams 构造参数解析

可直接传入URLSearchParams解析,然后追加到URL上。


//

const params = new URLSearchParams(form)

// 可获取使用实例的方法

params.toString()                  // name=admin&age=23&gender=1&name=test

?著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,992评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,212评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事?!?“怎么了?”我有些...
    开封第一讲书人阅读 159,535评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,197评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,310评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,383评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,409评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,191评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,621评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,910评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,084评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,763评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,403评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,083评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,318评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,946评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,967评论 2 351

推荐阅读更多精彩内容