现代浏览器高级API

随着技术的不断革新,现代浏览器提供了很多高级的功能用来满足开发者的需要。这些新的API在程序员的”红宝书“里未必能见到它们的身影,不过仍需要提前了解以备不时之需。

Beacon API

Beacon API可以向服务器发送少量的数据以实现统计等目的。同时它的性能比我们平常使用Ajax发送请求更好。当你需要发送数据但不要求有返回值的时候,都可以使用这个API。所有的数据都是在空闲时间发送的。

比如下面这个例子:

const beaconURL = "https://example.com"

function sendEvent(strEvent) {
// 由于这个API还处于实验阶段,为了照顾低版本浏览器需要进行功能检测处理。
  if (navigator.sendBeacon) {
    navigator.sendBeacon();
  }
}

window.addEventListener('load', function (e) {
  sendEvent("loadEvent");

  document.getElementById("btn1").addEventListener("click", function () {
    sendEvent("Button 1 click");
  });
});

可以通过在事件监听函数中触发发送请求事件达到统计的目的。

IntersectionObserver API

IntersectionObserver API是用来监视某个元素是否进入了浏览器的可视区域。因此,可以利用这个特性达到延迟加载的目的:

window.addEventListener("load", function () {
  const observer = new IntersectionObserver(function (entries) {
    console.log(entries);
  }, {
    "threshold": [0, 0.5, 1.0]
  });
});

其中threshold表示触发回调函数的临界值。比如0.5表示在可视区域内能看到一半元素的时候触发一次。因此上面的例子中[0, 0.5, 1.0]总共会在元素刚进入可视区域、进入一半和完全进入这三个阶段都触发一次回调函数。

浏览器通知

你可能经常在使用某个网页的时候在浏览器上看到提示框,现在利用Notification接口我们自己也能够实现这样的功能。

主要分为两步:

  1. 检测权限
window.addEventListener("load", () => {
  document.getElementById("btnRequest").addEventListener("click", () => {
    Notification.requestPermission().then(() => {
        if (Notification.permission === “granted”) {
            // 发送通知
            sendNotifaction("hello world")
        }
    })
  })
})
  1. 发送通知
function sendNotification(text) {
    let notification = new Notification('Page Title', {
      icon: ‘../image.png’,
      body: text,
    });
    
    notification.onclick = function() {
      parent.focus();
      window.focus(); //just in case, older browsers
      evt.target.close();
      // do somthing
    };
    setTimeout(notification.close.bind(notification), 5000);
}

使用Cache API进行缓存数据

CacheStorage 接口表示 Cache 对象的存储。它提供了一个 ServiceWorker 、其它类型worker或者 window 范围内可以访问到的所有命名cache的主目录(它并不是一定要和service workers一起使用,即使它是在service workers规范中定义的),并维护一份字符串名称到相应 Cache 对象的映射。

这个API使用起来也比较简单:

function getJSONData(url) {
  if ('cache' in window) {
    window.caches.open('my-data-cache').then(function (cache) {
      if (result === undefined) {
        fetch(url).then(function (result) {
          let clonedresp = result.clone();
         // 将数据存储到浏览器中去:
          cache.put(url, result);
          result.text().then(function(data) {
            console.log(data);
          });
        });
      }
    })
  }
}

数据持久化

IndexedDB是异步的,可以让web保持响应,而不是像localStorage一样阻塞页面。同时它还可以存储多种类型数据,很容易分为多个独立的实例进行存储。

const instance1, instance2;
document.getElementById("btnMulti").addEventListener("click", function () {
  instance1 = localforage.createInstance({
    "name": "instance1"
  });
  instance2 = localforage.createInstance({
    "name": "instance2"
  });
});

document.getElementById("btnStore").addEventListener("click", function () {
  instance1.setItem("key1", "value1");
  instance2.setItem("key1", "value2");
});

不过使用IndexedDB是复杂的,可以借助第三方库localForage来简化代码操作:

npm install localforage

安装完成后,可以在代码里这样应用:

localforage.getItem("test").then(value => {
    console.log(value);
}).catch(err => {
    console.log(err)
});

localforage.setItem("test", "some value").then(value => {
    console.log(value);
}).catch(err => {
    console.log(err);
});

浏览器存储状态检测

检测浏览器内存的功能可能不太常用,但如果你是开发移动端页面,对于内存比较小的设备来说,检测功能有时候就能够派上用场:

window.addEventListener("load", () => {
  if (navigator.storage && navigator.storage.estimate) {
      navigator.storage.estimate().then(estimate => {
      console.log("The remaining space: " + estimate.quota);
      console.log("Space used:" + estimate.usage);
    });
  }
  
  // 检测应用数据是否是持久化的
  if (navigator.storage && navigator.storage.persisted) {
    navigator.storage.persisted().then(persisted => {
      console.log("Storage persistence: " + persisted);
    });
  }
  
  if (navigator.deviceMemory) {
    console.log("The device memory is: " + navigator.deviceMemory);
  }
})

最终执行结果如下:

The device memory is: 8
Storage persistence: false
VM72:3 The remaining space: 244355911680
VM72:4 Space used:0

识别网络状态和质量

有时候我们要根据网络状态来采取不同的业务处理,如离线加载等,这就需要能够检测到浏览器中网络连接情况。要实现这个需求,可以借助window.navigator对象:

const isOnline = window.navigator.onLine;

if (window.navigator.conneciton) {
    const connection = navigator.connection;
    console.log(connection);
}

这是个只读对象,其中提供了很多很浏览器特性相关的属性,利用connection这个属性就可以检测到浏览器连接状态。

downlink: 1.05
effectiveType: "3g"
onchange: null
rtt: 300
saveData: false

而借助onLine属性我们就可以知道此时网络是否可用。

全屏显示页面

开发视频页面的时候,经常需要和全屏事件打交道,此时你可以借助浏览器自身的这个特性对其操作:

function enterFullscreen(ele) {
  if (ele.requestFullscreen) {
    ele.requestFullscreen();
  }
  
  if (ele.webkitRequestFullscreen) {
    ele.webkitRequestFullscreen();
  }
  
  if (ele.mozRequestFullscreen) {
    ele.mozRequestFullscreen();
  }
  
  if (ele.msRequestFullscreen) {
    ele.msRequestFullscreen();
  }
} 

function exitFullscreen(ele) {
  if (ele.requestFullscreen) {
    ele.exitFullscreen();
  }
  
  if (ele.webkitExitFullscreen) {
    ele.webkitExitFullscreen();
  }
  
  if (ele.mozCancelFullscreen) {
    ele.mozCancelFullscreen();
  }
  
  if (ele.msExitFullscreen) {
    ele.msExitFullscreen();
  }
} 

样式方面,和操作滚动条样式类似,对应的浏览器也提供了:full-screen这样的伪元素选择器:

:full-screen button {
  background: red;
}

:-webkit-full-screen button {
  background: red;
}

:-moz-full-screen button {
  background: red;
}

:-ms-fullscreen button {
  backgorund: red;
}

自定义CSS

CSS Houdini是现代CSS提供的一个高级API,由于开放了底层接口,我们借助它实现一些更加高级的特性。

比如接下来这个例子,我将实现一个自定义的属性samplepainter

新建一个叫做csspaint_start.js的文件:

if (typeof registerPaint !== "undefined") {
  class SampleCSSPaint {
    static get inputProperties() {
      return ['--cross-thickness', '--cross-color']
    }
    
    paint(ctx, size, props) {
      let width = props.get('--cross-thickness');
      let color = props.get('--cross-color').toString();
      
      ctx.lineWidth = width;
      ctx.strokeStyle = color;
       
      ctx.beginPath();
      ctx.moveTo(0,0);
      ctx.lineTo(size.width, size.height);
      ctx.stroke();

      ctx.beginPath();

      ctx.stroke();
    }
  }
    
  registerPaint('samplepainter', SampleCSSPaint);
}

然后将我们刚才写好的模块注册到启动脚本main.js中去:

window.addEventListener("load", function () {
  // 检测浏览器是否支持paintWorklet
  if ('paintWorklet' in CSS) {
    console.log("paintWorklet supported")
    
    CSS.paintWorklet.addModule("csspaint_start.js");
  } else {
    console.log("paintWorklet not supported")
  }
});

接着我们就可以在css中使用自定义的属性进行操作了:

#demo {
  background-image: paint(samplepainter);
  --cross-thickness: 2;
  --cross-color: red;
}

——--转载请注明出处--———

微信扫描二维码,关注我的公众号.jpg

最后,欢迎大家关注我的公众号,一起学习交流。

参考资料

https://www.lynda.com/JavaScript-tutorials/JavaScript-Modern-Browser-APIs/784304-2.html
https://developer.mozilla.org/en-US/docs/Web/API/notification
https://hackernoon.com/why-and-how-to-implement-web-notification-api-4eb795c5b05d
https://developer.mozilla.org/en-US/docs/Web/API/CacheStorage

https://www.w3.org/TR/beacon
https://putsreq.com

https://css-tricks.com/the-css-paint-api/

Https:/storage.spec.whatwg.org

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

推荐阅读更多精彩内容