// PageWatch.js
// 绑定激活和离开的方法
export default class PageWatch {
success = undefined // 切换一次的回调函数
status = undefined // 当前的状态
visibleNum = undefined // 离开的次数
hiddenNum = undefined // 归来的次数
_prefix = undefined // 前缀
_eventName = undefined // 浏览器监听事件的事件名,可能需要加前缀
_attributeName = undefined // 浏览器获取当前状态的事件名,可能需要加前缀
_nowEvent = undefined // 当前绑定的归来或离开的事件们
constructor(objData, success) {
this.status = undefined
this.visibleNum = undefined
this.hiddenNum = undefined
this._prefix = undefined
this._eventName = undefined
this._attributeName = undefined
this._nowEvent = undefined
this.init(objData)
this.success = success
}
init(eventObj) {
this.status = undefined
this.visibleNum = 0
this.hiddenNum = 0
this._nowEvent = {}
// 判断浏览器是否支持
this._prefix = null // 前缀
if ('hidden' in document) this._prefix = '';
else {
let prefixes = ['webkit', 'moz', 'ms', 'o'];
for (let i = 0; i < prefixes.length; i++) {
if ((prefixes[i] + 'Hidden') in document)
this._prefix = prefixes[i]
break
}
}
let obj = { // 记录浏览器支持情况
reload: true,
visible: true,
hidden: true
}
if (this._prefix === null) {
obj.visible = false
obj.hidden = false
}
this._eventName = (this._prefix ? this._prefix + 'Hidden' : 'hidden').replace(/[H|h]idden/, '') + 'visibilitychange';
this._attributeName = this._prefix ? this._prefix + 'VisibilityState' : 'visibilityState';
// 如果初始化时传入了事件对象
if (typeof (eventObj) === 'object' && Array.isArray(eventObj) === false) this.add(eventObj)
this.eventChange.updataEvent(obj) // 监听事件,一直监听
this.success && this.success(obj)
}
// 移除事件监听
removeEvent() {
this.eventChange.removeEvent()
}
add(eventObj) {
if (!(typeof (eventObj) === 'object' && Array.isArray(eventObj) === false)) return new Error(eventObj, ' 不是对象')
// 更新要绑定的事件
for (let key in eventObj) {
if (key === 'visible' || key === 'hidden' || key === 'reload') {
this._nowEvent[key] = eventObj[key]
}
}
}
// this.remove 需要的字符串判断和处理函数
_remove_handle(string) {
if (string === 'visible' || string === 'hidden' || string === 'reload') {
delete this._nowEvent[string]
}
}
remove(eventNames) {
if (typeof (eventNames) !== 'string' && Array.isArray(eventNames) !== true) return new Error(eventNames, ' 不是 string 且不是 array')
// 更新要绑定的事件
if (typeof (eventNames) === 'string') this._remove_handle(eventNames)
else if (Array.isArray(eventNames)) {
for (let i = 0; i < eventNames.length; i++) {
this._remove_handle(eventNames[i])
}
}
}
// 内部更新事件
eventChange = ((__this) => {
// console.log(_this)
const _this = __this || {}
const inside_event = {
hidden() {
this.hiddenNum++ // 更新离开的次数
this.status = 'hidden'
_this._nowEvent.hidden && _this._nowEvent.hidden(_this)
},
visible() {
_this.visibleNum++ // 更新归来的次数
_this.status = 'visible'
_this._nowEvent.visible && _this._nowEvent.visible(_this)
},
reload: function (e) {
if (!_this._nowEvent.reload) return false
let needTip = {} // 用于判断是否需要浏览器弹窗提醒
_this._nowEvent.reload && _this._nowEvent.reload(_this, needTip)
// 判断是否需要浏览器弹窗提醒
if (typeof(needTip) === 'object') {
let bool = false
for (let key in needTip) {
if (needTip[key]) {
bool = true
break
}
}
// 需要阻止
if (bool) {
// eslint-disable-next-line
let confirmationMessage = "\o/";
(e || window.event).returnValue = confirmationMessage; // Gecko and Trident
return confirmationMessage;
}
}
}
}
// 监听到页面前后台切换发生了变化
let insideFn_show = () => {
inside_event[document[_this._attributeName]]()
}
// 监听到页面更新了
let insideFn_reload = () => {
inside_event['reload']()
}
return {
updataEvent(obj) {
obj.visible && document.addEventListener(_this._eventName, insideFn_show, false)
window.addEventListener('beforeunload', insideFn_reload, false)
},
removeEvent() {
document.removeEventListener(_this._eventName, insideFn_show, false)
window.removeEventListener('beforeunload', insideFn_reload, false)
}
}
})(this)
}