资讯专栏INFORMATION COLUMN

页面可见与不可见的事件——visibilitychange

libxd / 608人阅读

摘要:需求背景在最近的项目中,使用了和定时器实现了随机走动物体的功能,走动的物体还会有的动画。上述代码中,维护了两个数组,分别代表页面进入可见状态时需要执行的回调列表和进入不可见状态时需要执行的回调列表。

需求背景

在最近的项目中,使用了transition和定时器实现了随机走动物体的功能,走动的物体还会有animation的动画。我发现在手机中,按home键或者切换应用,使页面不在屏幕中,也就是页面不可见,过一段时间切回来,会出现物体移动但是没有播放animaiton的动画的情况。

我就想到了visibilitychange。

结合react使用,添加类似onShow/onHide生命周期 额外生命周期

浏览器document有个visibilitychange的事件,由于存在兼容性问题,所以代码里也做了兼容处理。该事件会在document.visibilityState发生变化时触发,visibilityState有两个状态值——visible和hidden,表示页面是否在屏幕当中。

let changeState;
let visibilityChange;

if (typeof document.hidden !== "undefined") {
    visibilityChange = "visibilitychange";
    changeState = "visibilityState";
} else if (typeof document.mozHidden !== "undefined") {
    visibilityChange = "mozvisibilitychange";
    changeState = "mozVisibilityState";
} else if (typeof document.msHidden !== "undefined") {
    visibilityChange = "msvisibilitychange";
    changeState = "msVisibilityState";
} else if (typeof document.webkitHidden !== "undefined") {
    visibilityChange = "webkitvisibilitychange";
    changeState = "webkitVisibilityState";
}

知道了当前浏览器的状态属性和事件名称后,就可以添加时间监听了。

const visibleCallbackList = [];
const hiddenCallbackList = [];

document.addEventListener(
    visibilityChange,
    () => {
        if (document[changeState] === "visible") {
            for (let i = 0; i < visibleCallbackList.length; i++) {
                if (typeof visibleCallbackList[i] === "function") {
                    visibleCallbackList[i]();
                }
            }
        } else if (document[changeState] === "hidden") {
            for (let i = 0; i < hiddenCallbackList.length; i++) {
                if (typeof hiddenCallbackList[i] === "function") {
                    hiddenCallbackList[i]();
                }
            }
        }
    },
    false
);

上述代码中,维护了两个数组,分别代表页面进入可见状态时需要执行的回调列表和进入不可见状态时需要执行的回调列表。这两个列表在下面会讲到。

因为我们是使用react开发,所以想在组件级别做到该组件是否能使用该功能,所以想到让组件具有类似小程序的onShow和onHide的生命周期,在这个生命周期中执行组件内部的逻辑。

export const h5OnShow = callback => {
    visibleCallbackList.push(callback);
};

export const h5OnHide = callback => {
    hiddenCallbackList.push(callback);
};

/**
 *
 * @param {Object}
 *   {Function} h5OnShowCallback h5需要注销的显示回调
 *   {Function} h5OnHideCallback h5需要注销的隐藏回调
 */
export const h5ExtraLifecycleWillUnmount = ({ h5OnShowCallback, h5OnHideCallback }) => {
    if (h5OnShowCallback) {
        visibleCallbackList.splice(visibleCallbackList.indexOf(h5OnShowCallback), 1);
    }
    if (h5OnHideCallback) {
        hiddenCallbackList.splice(hiddenCallbackList.indexOf(h5OnHideCallback), 1);
    }

};

如上述代码中,h5OnShow方法中将传入的callback push至visibleCallbackList数组,h5OnHide方法将callback push到hiddenCallbackList。
h5ExtraLifecycleWillUnmount是在组件即将要卸载的时候调用,将回调列表里的方法删除。

额外生命周期的使用
    componentDidMount() {
        h5OnShow(this.pageShow);
        h5OnHide(this.pageHide);
    }
    componentWillUnmount() {
        h5ExtraLifecycleWillUnmount({
            h5OnShowCallback: this.pageShow,
            h5OnHideCallback: this.pageHide
        });
    }
    pageShow = () => {
        // 开启随机走动定时器
    }
    pageHide = () => {
        // 关闭随机走动定时器
    }

在组件里,注册onSHow和onHide,在页面显示时开启定时器,在页面隐藏时关闭定时器并把transition设置为none,这样在页面不可见时不会做无用的逻辑处理,这也是符合用户的预期,因为页面隐藏时并不关心在这期间做了生命动画变更。

可优化点:
1.visibleCallbackList和hiddenCallbackList使用WeakSet更好,保证了不会出现内存泄漏。
2.如果组件实例化多次,pageShow和pageHide使用箭头函数并不友好,可使用修饰器模式改变原型上的方法的this指向。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/105640.html

相关文章

  • PageVisibilityAPI简单易学教程演示

      一、简介  要知道用户何时离开,有常用的方法是监听下面三个事件。  pagehide  beforeunload  unload  可上述三种方法有一个bug就是,这些事件在手机上可能不会触发,页面就直接关闭了。因为手机系统可以将一个进程直接转入后台,然后杀死。  用户点击了一条系统通知,切换到另一个 App。  用户进入任务切换窗口,切换到另一个 App。  用户点击了 Home 按钮,切换...

    3403771864 评论0 收藏0
  • HTML 5页面可视性API

    摘要:原文译文的页面可视性译者在早期,浏览器并没有提供选项卡,但是现在基本所有浏览器都提供了这个功能。在这个中,将基于页面的可视性状态弹出文档的标题。对于常见的手风情效果,当页面不可见时,可以限制其移动。 原文:HTML5 Page Visibility API 译文:HTML 5的页面可视性API 译者:dwqs showImg(https://segmentfault.com/im...

    voidking 评论0 收藏0
  • 移动端倒计时切到后台切回来不继续执行问题

    摘要:问题描述这个倒计时按钮,如果页面在移动端切到后台和切回来,倒计时停止运行。相关代码为了兼容,切换到后台继续运行 问题描述 showImg(https://segmentfault.com/img/bVbiVSh);这个倒计时按钮,如果页面在移动端切到后台和切回来,倒计时停止运行。但是在pc端没有这个问题。倒计时代码如下 let downCount = () => { ...

    Aomine 评论0 收藏0
  • 页面可见性用途

    摘要:页面可见性有哪些用途页面可见性对于用户来说,可见性的意思就是能不能看到,显示的页面,就是我们正在看的页面,隐藏的页面,就是我们没有看的页面。 页面可见性有哪些用途? 页面可见性:对于用户来说,可见性的意思就是能不能看到,显示的页面,就是我们正在看的页面,隐藏的页面,就是我们没有看的页面。因为我们一次要打开好多标签页面来回切换着,始终只有一个页面在我们眼前,其它页面都是隐藏的。使用方式:...

    ispring 评论0 收藏0

发表评论

0条评论

libxd

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<