H5中的桌面通知Notification

H5中的桌面通知Notification

前言:?对于一个前段开发者,逛网页总会留意一些新奇的功能,对于上班总会用到Teambition的我,总是能收到Notification…所以今天就来研究下这个H5功能…


  1. 实例一个Notification

复制代码

let n = new Notification(
  “这是一个通知消息”, //这是必选Title 一定会显示的通知标题
  {
   icon: “xxx.png”, // 这个icon是用来显示通知中的左边图片
   body: “你好啊,我是xxx”,   // 通知中的内容字符
    dir: auto,             // 文字的方向 值包含: auto(自动), ltr(从左到右), rtl(从右向左)
    tag: “gxlself”          // 给与这个通知消息一个ID, 用来对这个通知消息进行 刷新.移除.替换 等操作
    // long: “en-US”               //lang字段 需要参考https://tools.ietf.org/html/bcp47 并不是必须 没看出啥作用…
    // …            // 其余可选属性见下实例属性
  }
)
访问对应的实例属性:
n.actions // 一个只读的NotificationAction对象数组。每一个对象描述用户可以在一个通知中选择的单个操作。
n.image // 通知的一部分显示的图像的URL
n.badge // 当没有足够的空间显示通知本身时,用于表示通知的图像的URL。
n.permission // 有三个值 granted, denied, 或default 当状态值为granted时可以发送通知消息 default默认用户没处理 denied 用户拒绝 n.renotify // 布尔值。新通知出现的时候是否替换之前的。如果设为true,则表示替换,表示当前标记的通知只会出现一个。注意这里的“当前标记”没?没错,true参数要想起作用,tag必须需要设置属性值。 n.requireInteraction // 布尔值, 指的是通知是否保持活动直到用户点击或取消通知 而不是自动关闭.. n.silent // 布尔值。通知出现的时候,是否要有声音。默认false, 表示无声。 n.timestamp //通知创建或者可以使用的时间。 n.data // 任意类型和通知相关联的数据。 n.vibrate // 通知显示时候,设备震动硬件需要的震动模式。所谓振动模式,指的是一个描述交替时间的数组,分别表示振动和不振动的毫秒数,一直交替下去。例如[200, 100, 200]表示设备振动200毫秒,然后停止100毫秒,再振动200毫秒。 (移动端) n.sound // 字符串。音频地址。表示通知出现要播放的声音资源。 n.sticky // 通知吸附不容易被清除… (移动端) n.noscreen // 布尔值。是否不再屏幕上显示通知信息。默认false, 表示要在屏幕上显示通知内容。(移动端) n. 此时实例 n 有四个事件处理: 1> onclick 用户对通知信息的点击事件 2> onshow 通知消息展示之后触发的事件 3> onerror 遇到错误会触发的事件 4> onclose close事件的处理

复制代码

2. Notification对象会有什么属性/方法呢?利用控制台中的window对象输出点开查看就可以看到: 值得注意的是: requestPermission()方法仅在Notification对象有效,实例对象无效!!!这个方法是用来向用户申请显示通知的权限,只能被用户主动去调用(在页面onload中可以调用,可以向用户申请,之后再去发送…)   实例对象拥有的方法有: (1). close()? 用于关闭通知消息 –> 也可以在onshow方法加延迟调用,提高用户体验感… (2). addEventListener() 监听事件(这个通用方法) (3). removeEventListener 卸载监听事件(通用,同上) (4). dispatchEvent 分派事件(同上)   接下来,写一个js测试, 如果使用的是谷歌浏览器,建议在设置中显示通知将本地服务地址加入允许通知 但是,http的域名在谷歌浏览器被默认关闭,还不允许更改,查看谷歌浏览器控制台有警告信息—> index.js:78 [Deprecation] The Notification API may no longer be used from insecure origins. You should consider switching your application to a secure origin, such as HTTPS. See https://goo.gl/rStTGz for more details. 嗯,好吧,让加https证书,真的是有毒…虽然在自己的主页中添加该功能也只能在火狐浏览器爽一爽…. (腾讯云有免费一年的ssl证书,可自己进行安装…)

复制代码

// index.js
window.onload = function(){
  let gxlself = new Gxlself()
  gxlself.requestPermission()
  setTimeout(()=>{
    gxlself.showNotification()
  },3000)
}

class Gxlself{
   constructor(){
    this.isNotificationSupported = “Notification” in window;
   }
isPermissionGranted(){
return Notification.permission === ‘granted’;
}
requestPermission(){
if(!this.isNotificationSupported){
return;
}
Notification.requestPermission(status=>{
let permission = Notification.permission;
})
}
showNotification(){
if (!this.isNotificationSupported) {
return;
}
if (!this.isPermissionGranted()) {
return;
}
var n = new Notification(“gxlself对您发来问候”, {
icon : ‘gxlself.png’,
body : ‘欢迎来访,鄙人万分感激! 点击即可跳转至我的博客页面~’
});
n.onshow = function () {
console.log(‘gxlself已经发送通知信息’);
setTimeout(function() {
n.close();
}, 5000);
}
n.onclick = function () {
location.href = ‘http://gxlself.com/blog
n.close()
}
n.onerror = function (err) {
console.log(err)
}
n.onclose = function () {
console.log(‘gxlself消息窗口关闭’)
}
}
}

复制代码

这是火狐浏览器执行后的效果展示:   再来看看谷歌本地跑的效果:(域名已经被默认拦截关闭,上面已经说明,不再重复) 谷歌的效果其实挺好看的,嗯…只是一个https把我给屏蔽了? ?哎… ——-? 桌面版应用 ———– 当你要在开放 web 应用中使用通知时,请确保将?desktop-notification?权限添加到你的 manifest 文件中。通知可以被用于任何权限级别,hosted 或更高。

1
2
3
  "permissions": {
   "desktop-notification":{}
  }

  这个Notification比较好玩,也是未来发送消息的一个重要的一块,留此记录…

原型笔记

  • 1. Object.getOwnPropertyNames()

在学习使用该方法的时候,查阅了《JavaScript高级程序设计》与 MDN 来综合学习。

先来看看MDN对其的表述:

参数

obj:

  一个对象,其自身的可枚举和不可枚举属性的名称被返回。

返回值

      在给定对象上找到的属性对应的字符串数组。

描述

Object.getOwnPropertyNames() 返回一个数组,该数组对元素是 obj自身拥有的枚举或不可枚举属性名称字符串。 数组中枚举属性的顺序与通过 for...in 循环(或 Object.keys)迭代该对象属性时一致。数组中不可枚举属性的顺序未定义。

同时,举出了几个例子来表显示,例如:

var arr = [“a”, “b”, “c”];
console.log(Object.getOwnPropertyNames(arr).sort()); // [“0”, “1”, “2”, “length”] // 类数组对象
var obj = { 0: “a”, 1: “b”, 2: “c”};
console.log(Object.getOwnPropertyNames(obj).sort()); // [“0”, “1”, “2”] // 使用Array.forEach输出属性名和属性值
Object.getOwnPropertyNames(obj).forEach(function(val, idx, array) {
console.log(val + “ -> “ + obj[val]);
}); // 输出 // 0 -> a // 1 -> b // 2 -> c //不可枚举属性
var my_obj = Object.create({}, {
getFoo: {
value: function() { return this.foo; },
enumerable: false }
});
my_obj.foo = 1;

console.log(Object.getOwnPropertyNames(my_obj).sort()); // [“foo”, “getFoo”]

  正如:MDN上所述,该方法返回的是对象自身的可枚举与不可枚举属性,即返回的是一个数组。并且在查阅《JavaScript高级程序设计》这本书籍的时候,却发现了一个问题。

function Person(){

}

Person.prototype.name = ‘asfd’
Person.prototype.age = 15
Person.prototype.sayName = function () {
console.log(this.name)
}

var keys = Object.getOwnPropertyNames(Person.prototype) console.log(keys)
// 书籍中表述keys返回的是 [‘constructor’, ‘name’, ‘age’, ‘sayName’]

// 但是当将Person.property设置一个以对象字面量形式创建的对象时,就不再返回constructor. 书籍中已经解释此时的constructor不再指向Person // 于是,我真的操作了一遍才发现,真的如此
// 实例如下:
function Person(){ }
Person.prototype = {
name: ‘zwj’,
age: 21,
say: function () {
console.log(‘say’)
}
}
var keys = Object.getOwnPropertyNames(Person.property)
console.log(keys)
// 此时返回的 [‘name’,’age’,’sayName’]

  我根据书中理解如下:设置一个以对象字面量形式创建的对象,虽然结果相同,但是constructor不再指向Person,这就涉及到原型链了

  首先,每个构造函数被创建的时候,同时就创建了一个构造函数对应的原型对象,即: 构造函数.prototype 

  这个对象就会自动获得一个constructor属性,这个属性就是该对象指向构造函数的指针,你也可以试试输出: Person.prototype    Person.prototype.constructor     Person.prototype.constructor.prototype 等等,就会发现形成了一个闭环…

  这里我们使用的语法去接收属性值,本质上默写了prototype对象,这时候,改写的对象默认的constructor指向为Object构造函数,毕竟函数也是对象,在JS中一切皆为对象…

  所以如果我们通常为了在原型上进行大量的属性写入,就必须对这部分操作进行注意,需要在使用设置对象字面量方式之后手动为其添加constructor属性的指向,这样做的目的就是为了确保通过该属性能够访问到适当的值…

  当然你会觉得这样设置并不是完美,毕竟对于constructor这个属性,他应该是不可枚举的,此时,却是可枚举的,这是就需要我们使用Object.defineProperty()进行相应的设置.相应的代码如下:

function Person(){
} // 此时重写了prototype对象 constructor指向Object
Person.prototype = {
name: ‘Nick’,
age: 15,
sayName: function(){
consolelog(this.name)
}
} // 对constructor进行设置修改
Object.defineProperty(Person.prototype, ‘constructor’, {
enumerable: false, // 设置是否可枚举 false为不可枚举
value: Person // 设置值为Person
}) //可以通过definePrototype进行更改数据属性的共有6个,其余4个分别为: // configurable ———-> 表示是否可以通过delete进行删除 默认为true // writable ———-> 表示是否可以修改属性的值 默认为true
// get ———-> 一个给属性提供 getter 的方法,如果没有 getter 则为 undefined。该方法返回值被用作属性值。默认为 undefined。
// set ——–> 一个给属性提供 setter 的方法,如果没有 setter 则为 undefined。该方法将接受唯一参数,并将该参数的新值分配给该属性。默认为 undefined。

  总结: 在进行创建构造函数的时候,以前习惯只是将constructor直接写在重写的prototype对象中,但是却忽略了其中最重要的一条信息,那就是constructor属性本身是不可枚举的属性,还需要更深一层的操作去设置constructor.看问题不能只看表面,更应该注重于内在…