【JavaScript高级】Intl.DateTimeFormat、Navigator.sendBeacon埋点等冷门但好用的API方法

前言:随着科技的进步,Web前端技术也是日新月异的发展,虽然因为某些原因有所迟缓,但还是有很多新的技术等待我们去发掘,去探索。而这些东西在我们固有的知识之外,甚至在日常开发中我们都不曾用过。但是如果你沉下心来,细细研究,把他们慢慢融入到你的项目当中,必然会成为一种利器。下面就让我们来看一看JS中一些冷门但好用的API吧。

一、 Intl.DateTimeFormat

Intl.DateTimeFormat 对象能使日期和时间在特定的语言环境下格式化。

创建一个新的 Intl.DateTimeFormat 对象

Intl.DateTimeFormat()

getter 函数,根据此 DateTimeFormat 对象的区域设置和格式化选项格式化日期

Intl.DateTimeFormat.prototype.format()

示例:

// 实例化一个日期对象
const date = new Date()
// 创建一个新的 Intl.DateTimeFormat 对象
let dtf_en = new Intl.DateTimeFormat('en-US').format(date)
// 使用 locales 参数指定美式英语 (US English):month-day-year 格式
console.log(dtf_en) // 5/6/2023
// 使用 locales 参数指定中文 (CH Chinese):month-day-year 格式
let dtf_ch = new Intl.DateTimeFormat('zh-CH').format(date)
console.log(dtf_ch) // 2023/5/6
// 请求参数 (options) 中包含参数星期 (weekday),并且该参数的值为长类型 (long) - 参考语言环境对应输出
 let options = { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' }
let dtf_ch_options = new Intl.DateTimeFormat('zh-CH', options).format(date)
console.log(dtf_ch_options); // 2023年5月6日星期六

API 参考地址:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat

二、Navigator.sendBeacon

2.1 概述

navigator.sendBeacon(url, data) 方法可用于通过 HTTP POST将少量数据 异步传输到 Web 服务器。

  • data 参数是将要发送的 ArrayBufferArrayBufferViewBlobDOMStringFormDataURLSearchParams 类型的数据。

  • 当用户代理成功把数据加入传输队列时,sendBeacon() 方法将会返回 true,否则返回 false

  • 方法主要用于满足统计和诊断代码的需要。在项目中可做"埋点"处理,收集用户的使用习惯和信息数据。

2.2 可以解决传统方式(如下)出现的问题(迫使用户代理延迟卸载文档)

  • 发起一个同步 XMLHttpRequest 来发送数据。
  • 创建一个 img 元素并设置 src,大部分用户代理会延迟卸载(unload)文档以加载图像。

navigator.sendBeacon 优势

  • 相较于img标签,使用navigator.sendBeacon会更规范,数据传输上可传输资源类型会更多。
  • 对于ajax在页面卸载时上报,ajax有可能没上报完,页面就卸载了导致请求中断,因此ajax处理这种情况时必须作为同步操作.
  • sendBeacon是异步的,不会影响当前页到下一个页面的跳转速度,且不受同域限制。这个方法还是异步发出请求,但是请求与当前页面脱离关联,作为浏览器的任务,因此可以保证会把数据发出去,不拖延卸载流程。

2.3 在会话结束时发送统计数据

网站通常希望在用户完成页面浏览后向服务器发送分析或诊断数据,最可靠的方法是在 visibilitychange 事件发生时发送数据

document.addEventListener('visibilitychange', function logData() {
	 if (document.visibilityState === 'hidden') {
	     navigator.sendBeacon('/log', analyticsData);
	 }
});

2.4 基于Navigator.sendBeacon的埋点上报

Navigator.sendBeacon是目前通用的埋点上报方案,Navigator.sendBeacon方法接受两个参数,第一个参数是目标服务器的 URL,第二个参数是所要发送的数据(可选),可以是任意类型(字符串、表单对象、二进制对象等等)。

  • 页面停留时间上报埋点

    绑定点击事件,当点击目标元素时,触发埋点上报。

    function clickButton(url, data) {
        navigator.sendBeacon(url, data)
    }
    
  • 页面停留时间上报埋点

    路由文件中,初始化一个startTime,当页面离开时通过路由守卫计算停留时间。

    let url = ''// 上报地址
    let startTime = Date.now()
    let currentTime = ''
    router.beforeEach((to, from, next) => { 
         if (to) {
             currentTime = Date.now()
             stayTime = parseInt(currentTime - startTime)
             navigator.sendBeacon(url, {time: stayTime})
             startTime = Date.now()
         }
    })
    
  • 内容可见埋点

    通过交叉观察器去监听当前元素是否出现在页面

    // 可见性发生变化后的回调 
    function callback(data) { 
        navigator.sendBeacon(url, { target: data[0].target, text: '内容可见' }) 
    } 
    // 交叉观察器配置项 
    let options = {}; 
    // 生成交叉观察器 
    const observer = new IntersectionObserver(callback); 
    // 获取目标节点 
    let target = document.getElementById("target"); 
    // 监听目标元素 
    observer.observe(target);
    

三、EventSource

EventSource 接口是 web 内容与服务器发送事件通信的接口。

一个 EventSource 实例会对 HTTP 服务器开启一个持久化的连接,以 text/event-stream 格式发送事件,此连接会一直保持开启直到通过调用 EventSource.close() 关闭。

在这里插入图片描述

一旦连接开启,来自服务端传入的消息会以事件的形式分发至你代码中。如果接收消息中有一个 event 字段,触发的事件与 event 字段的值相同。如果不存在 event 字段,则将触发通用的 message 事件。

与 WebSocket 不同的是,服务器发送事件是单向的。数据消息只能从服务端到发送到客户端(如用户的浏览器)。这使其成为不需要从客户端往服务器发送消息的情况下的最佳选择。例如,对于处理如社交媒体状态更新、消息来源(news feed)或将数据传递到客户端存储机制(如 IndexedDB 或 web 存储)之类的,EventSource 无疑是一个有效方案。

  1. 创建一个新的 EventSource,用于从指定的 URL 接收服务器发送事件,可以选择开启凭据模式

    const evtSource = new EventSource("sse.php");
    
  2. 获取页面元素

    const eventList = document.querySelector("ul");
    
  3. 添加 message 事件,会在通过事件源收到数据时触发

    evtSource.onmessage = (e) => {
    	const newElement = document.createElement("li");
    	newElement.textContent = `message: ${e.data}`;
    	eventList.appendChild(newElement);
    }
    

四、Proxy API

Proxy API 可以用于创建代理对象,可以拦截对象属性的读取、赋值等操作。这个功能可以用于实现元编程、数据劫持等功能。

const myObject = {
  name: "John",
  age: 30,
};

const myProxy = new Proxy(myObject, {
  get(target, property) {
    console.log(`Getting property ${property}`);
    return target[property];
  },
  set(target, property, value) {
    console.log(`Setting property ${property} to ${value}`);
    target[property] = value;
  },
});

console.log(myProxy.name); // "John"

myProxy.age = 31; // Setting property age to 31

五、IntersectionObserver

IntersectionObserver 可以用于检测元素是否进入视口,可以用于实现无限滚动、懒加载等功能。

const myObserver = new IntersectionObserver((entries, observer) => {
  entries.forEach((entry) => {
    if (entry.isIntersecting) {
      console.log(`${entry.target.id} is now visible`);
      observer.unobserve(entry.target);
    }
  });
});

const myElement = document.getElementById("myElement");
myObserver.observe(myElement);

使用场景:在Web应用中,可能需要实现无限滚动、懒加载等功能,使用IntersectionObserver可以方便地实现这些功能。

六、AudioContext

AudioContext 可以用于处理音频,可以用于实现音频播放、音效处理等功能。

const audioContext = new AudioContext();

fetch("https://example.com/audio.mp3")
  .then((response) => response.arrayBuffer())
  .then((arrayBuffer) => audioContext.decodeAudioData(arrayBuffer))
  .then((audioBuffer) => {
    const source = audioContext.createBufferSource();
    source.buffer = audioBuffer;
    source.connect(audioContext.destination);
    source.start();
  });

使用场景:在Web应用中,可能需要实现音频播放、音效处理等功能,使用AudioContext可以方便地实现这些功能。

============================ 注意:以下为了解内容 ================================================

七、服务器和HTTP(了解)

7.1 服务器

简单来说就是可提供服务的机器(响应)

这个服务器可以租、可以买、可以下载一些模拟软件

我们选择自己搭建的Nodejs

如果想要使用Nodejs,需要下载应用程序

官网:https://nodejs.org/zh-cn/

​ http://nodejs.cn/

平时我们查看的地址栏:

​ file://……

有了服务器之后的地址栏:

[ http:// ](http://localhost:3000/05 服务器.html)……

本机ip地址: localhost 或者 127.0.0.1

如果有网络:可以使用网络ip 192.168.0.105

7.2 HTTP

http: 是超文本传输协议,里面规定了前端如何发送请求到后端,后端如何返回数据,前端如何接收的规定

当有了服务器之后,我们可以发送http请求,来请求服务器中的资源

在很久之前,浏览器的目的只是为了渲染静态页面,此时,面临一个问题,前端发送请求,后端如何接收,

后端返回数据,前端如何解析?

于是,HTTP就出现了

例如:前端想要请求一张图片到服务器端,此时,要按照HTTP协议中的规定去发送请求,后端接收请求并返回数据的时候要按照HTTP协议中的规定按照正确的格式返回数据

还有一个问题,服务器可连接的数量是有限的,比如一个服务器的连接数量是10, 此时,前端发送过来一个请求,并且还是有状态的(持久连接),服务器的连接数量最多只有10个,但是在当时浏览器只是为了渲染静态页面,所以没有必要是有状态的(持久连接),所以特意给HTTP设置为无状态(没有持久连接)

连接过程:

  • 浏览器端发送HTTP请求,请求服务器中的资源,服务器得到响应,返回数据,断开连接
  • 由于断开了连接,所以服务器可连接的数量远大于有状态的连接
  • 浏览器接收数据,并渲染页面

服务器最大的作用是可以提供服务器环境

在前端很多时候要用到服务器环境。比如:事件推送,多线程,ajax、canvas相关功能都需要使用 服务器环境

八、WebSql

WebSql 是一个浏览器端的数据库,但是后面删除了,因为前端页面数据库意义不大。

浏览器中的位置:

在这里插入图片描述

5.1 打开或创建一个数据对象

openDatabase 是一个全局函数,window对象下

在这里插入图片描述

在这里插入图片描述

openDatabase(name, version, descrip,size) 函数用于打开或创建一个数据对象

  • name 数据库名称
  • version 数据库版本号
  • descrip 数据库版本描述
  • size 数据库大小
//创建一个数数据库对象
var db = openDatabase('stu',1.0,"这是某某中学学生数据库信息",1024 * 1024);

在这里插入图片描述

此时,数据库中 db 中没有数据:

在这里插入图片描述

5.2 开启事务

通过数据库对象 db 中的方法 transaction 开启事务:

//数据库对象中有一个方法 transaction 用于开启事务   
//这个方法中有一个参数 是回调函数  回调函数默认是有一个参数的。处理事务的对象 SQLTransaction
db.transaction(function(ts){
    // console.log(arguments);
    console.log(ts);
})

在这里插入图片描述

处理事务的对象 SQLTransaction 它的原型中 有一个 executeSql 函数,用于操作数据库数据:

executeSql(sql,[],successback,failedback)

​ sql 操作数据库的命令

​ [] 替换数组

​ successback 命令操作成功的回调

​ ,failedback 命令操作失败的回调

5.3 创建一个table

//创建一个数数据库对象
var db = openDatabase('stu',1.0,"这是某某中学学生数据库信息",1024 * 1024);

//数据库对象中有一个方法 transaction 用于开启事务   
//这个方法中有一个参数 是回调函数  回调函数默认是有一个参数的。处理事务的对象 SQLTransaction
db.transaction(function(ts){
    // console.log(arguments);
    // console.log(ts);

    //ts 对象原型中  executeSql 函数,用于操作数据库数据
    // 创建一个表格
    ts.executeSql("create table stu(name varchar(10), age int(10))",[],function(){
        console.log("table stu create success....")
    },function(){
        console.log("table stu create failed....")
    })
})

在这里插入图片描述

注意:不能重复创建同名的table

5.4 向table中插入数据

//创建一个数数据库对象
var db = openDatabase('stu',1.0,"这是某某中学学生数据库信息",1024 * 1024);

//数据库对象中有一个方法 transaction 用于开启事务   
//这个方法中有一个参数 是回调函数  回调函数默认是有一个参数的。处理事务的对象 SQLTransaction
db.transaction(function(ts){
    //插入数据
    ts.executeSql("insert into stu values('Jack',23)",[],function(){
        console.log("insert success....")
    },function(){
        console.log("insert failed....")
    })
})

在这里插入图片描述

六、SVG

SVG(Scalable Vector Graphics)是一种用于描述二维矢量图形的图形格式。它基于 XML 格式,通过描述形状、路径、颜色等属性来实现对图形的描述。与位图不同,SVG 是一种矢量图形格式,可以保证图形的无损缩放和平滑展示,适用于在不同分辨率和设备上显示。

SVG 的优势主要体现在以下几个方面:

  1. 矢量图形:SVG 使用数学公式来描述图形,因此图形被保存为对象而不是一系列像素点。这意味着无论缩放比例多大,图形都能保持高质量和清晰度。相比之下,位图在不同缩放级别下会导致图像失真。

  2. 小文件大小:由于 SVG 使用 XML 格式进行保存,文件大小通常较小,可以减少网络加载时间和带宽使用。这使得 SVG 成为 Web 动画和交互设计的理想选择。

  3. 可编辑性:SVG 图像可以被编辑和修改,而不会失去其原有质量。这使得设计师在开发阶段可以灵活地进行修改和调整。

下面是一个简单的 SVG 代码示例,绘制了一个红色圆形:

<svg width="200" height="200">
  <circle cx="100" cy="100" r="50" fill="red" />
</svg>

在上面的代码中,svg 标签定义了一个 SVG 画布,通过 widthheight 属性设置了画布的大小。circle 标签定义了一个圆形,通过 cxcy 属性设置了圆心的坐标,r 属性定义了圆的半径,fill 属性定义了填充颜色。

除了基本的形状绘制,SVG 还支持路径绘制、渐变填充、滤镜效果、动画等高级特性。以下是一个稍复杂一点的 SVG 代码示例,绘制了一个渐变圆环和一个动画效果:


<svg width="200" height="200">
  <defs>
    <linearGradient id="gradient">
      <stop offset="0%" stop-color="green" />
      <stop offset="100%" stop-color="yellow" />
    </linearGradient>
  </defs>
  
  <circle cx="100" cy="100" r="70" fill="none" stroke="url(#gradient)" stroke-width="15">
    <animate attributeName="r" from="70" to="50" dur="1s" repeatCount="indefinite" />
    <animate attributeName="stroke-width" from="15" to="5" dur="1s" repeatCount="indefinite" />
  </circle>
</svg>

上面的代码中,defs 标签定义了一个线性渐变,通过两个 stop 子标签定义了渐变的起始和终止颜色。circle 标签绘制了一个填充为空、描边为渐变颜色的圆环。animate 标签定义了两个动画效果,分别改变了圆环的半径和描边的宽度,通过设置不同的属性名称、起始值、结束值、持续时间和重复次数来实现动画效果。

总结来说,SVG 作为一种矢量图形格式,具有高质量、小文件大小、可编辑性等优势。通过使用简单的 SVG 代码,我们可以轻松绘制各种形状,并结合高级特性实现复杂的效果和动画。在 Web 开发和图形设计领域,SVG 是一种非常强大和实用的技术。

七、Fetch 封装

const $http = async (url = '', data = {}, type = 'GET') => {
  const baseUrl = "" // 基础路径
  type = type.toUpperCase(); // 请求方式小写转换成大写
  url = baseUrl + url; // 请求地址的拼接
  let token = ''

  if(sessionStorage.getItem('token')) {
    token = sessionStorage.getItem('token')
  }

  if (type == 'GET') {
    let dataStr = ''; //数据拼接字符串
    Object.keys(data).forEach(key => {
      dataStr += key + '=' + data[key] + '&';
    })
    if (dataStr !== '') {
      dataStr = dataStr.slice(0, dataStr.lastIndexOf('&'));
      url = url + '?' + dataStr;
    }
  }
  
  let requestConfig = {
    credentials: 'same-origin',
    method: type,
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/json',
      // 获取 token
      'Authorization': token
    },
    mode: "cors", // 用来决定是否允许跨域请求  值有 三个 same-origin,no-cors(默认)以及 cores;
    cache: "force-cache" // 是否缓存请求资源 可选值有 default 、 no-store 、 reload 、 no-cache 、 force-cache 或者 only-if-cached 。
  }

  if (type == 'POST') {
    Object.defineProperty(requestConfig, 'body', {
      value: JSON.stringify(data)
    })
  }
  try {
    const response = await fetch(url, requestConfig);
    const responseJson = await response.json();
    return responseJson
  } catch (error) {
    throw new Error(error)
  }
}

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MagnumHou

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值