zoukankan      html  css  js  c++  java
  • JavaScript:原生JS实现Facebook实时消息抓捕

    基础知识准备:

    HTML5给我们提供了一个新的对象叫作:MutationObserver。为了兼容,还有WebKitMutationObserver、MozMutationObserver,挂靠在window下。


    这个对象是干嘛的呢?
    mutation:变化、变动、突变;
    observer:观察者;
    顾名思义,在DOM中,MutationObserver就是监听DOM变化的意思。


    那么这个对象能够监听DOM的哪些变化呢?

    1. 子节点变化; ——–> childList
    2. 自身属性变化; ——–> attributes
    3. 自身的文本变化; ——–> characterData

    以上三点呢是三大基本点。


    至于这个对象怎么使用呢?很简单!

    var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;
    
    var observer = new MutationObserver(function(mutations) {});
    • 1
    • 2
    • 3

    上面的代码中,就是new了一个对象,里面传个callback回调函数而已,就这么简单,这个回调函数干嘛的?该回调函数会在指定的DOM节点(目标节点)发生变化时被调用. 该回调函数有一个参数mutations,这个参数是个数组,数组里每个元素是对象(包含了若干个MutationRecord对象的数组)。


    该对象有几个方法要知道:

    observe( Node target, optional MutationObserverInit options );
    ovserve(要观察的目标节点, 你要观察目标节点的哪些东西-对象);
    //举个例子,给你个人(目标节点),你想观察这个人的哪些指标变动:体重、身高、小孩等等
    
    disconnect();//不再观察

    好了,直接上个例子吧:

    <!DOCTYPE html>
    <html>
    <head>
        <title></title>
    </head>
    <body>
        <divid="guoyu"></div>
    
        <scripttype="text/javascript">var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver
            // 选择目标节点var target = document.querySelector('#guoyu');
            // 创建观察者对象,一旦目标节点发送变化,该回调立马执行var observer = new MutationObserver(function(mutations) {
              mutations.forEach(function(mutation) {
                console.log(mutation.type);
              });
              console.log(mutations);//看看callback参数到底是什么
            });
    
            // 配置观察选项:你想观察目标节点哪些项var config = {
                attributes: true,
                childList: true,
                characterData: true
            }
    
            // 传入目标节点和观察选项
            observer.observe(target, config);
    
        </script>
    
    </body>
    </html>

    我们在id为”guoyu”的节点中添加一个节点,那么回调函数立马就会被触发执行:
    这里写图片描述


    看到了吧,我们在节点中插入一个子节点,立马触发了回调函数,并打印了我们想要的结果,而且改变的是childList。


    再看一下,我这次把id给改了,看看有什么不同:

    这里写图片描述


    看到了吗,这次修改id属于属性的修改,打印出来的是attributes。


    注: childList, attributes, 或者characterData三个属性中必须至少有一个为true.否则,会抛出异常”An invalid or illegal string was specified”.


    下面呢,就着重介绍一下各个属性到底是啥意思!首先我们看看回调函数里的那个参数,这个参数上面说了是个数组,每个元素是个对象,具体名字参见上面截图。


    这里写图片描述


    我们在观察目标节点的时候,需要配置一个json对象,告诉浏览器我们要监听目标节点的哪些指标,比如:属性、子节点、文本、所有子孙节点等等。那么具体有哪些呢?

    这里写图片描述


    再举个例子吧,比如,我们既改变文本值,记录characterDataOldValue;又改变属性id的值,记录attributeOldValue。

    <!DOCTYPE html>
    <html>
    <head>
        <title></title>
    </head>
    <body>
        <divid="old_guoyu">I'am old</div>
    
        <scripttype="text/javascript">var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver
    
            var target = document.querySelector('#old_guoyu');
    
            var observer = new MutationObserver(function(mutations) {
              mutations.forEach(function(mutation) {
                console.log(mutation.type);
              });
              console.log(mutations); 
            });
    
            var config = {
                attributes: true,
                childList: true,
                characterData: true,
                characterDataOldValue: true,//监听老的文本值
                attributeOldValue: true,//记录老的属性值
                subtree: true
            };
    
            observer.observe(target, config);
    
        </script>
    
    </body>
    </html>

    这里写图片描述


    看到没,此次我同时改变了文本值和属性值,回调函数执行了两次,一次是文本改变执行的,另一次是属性id改变执行的。说明MutationObserver准确的监听了所有的变化,并作出反应。


    监听Facebook消息

    有了上面的基础,我们就可以做很多有趣的东西。我们知道,每当有新的消息的时候,facebook会给你立即推送,但这是有前提的,你的软件必须和Facebook有合作,或者花钱买Facebook的服务消息推送。比如UC浏览器的海外版,UC浏览器就可以实时帮你推送Facebook的消息,因为UC和Facebook达成了合作,才会给你推送。


    我们的突破口在Facebook首页的tab上,每当有新的消息,该主页上的tab会显示一个数字,只要我们实时监听到这个数字变化,就可以实时监听Facebook的消息,让你不用花钱也能实时获取消息提醒,这对于没有和Facebook达成合作协议的浏览器厂商十分有用。


    这里写图片描述


    前端可以使用原生JS实现对消息的实时监听,并把消息发送给浏览器客户端,浏览器客户端进行提醒,下面是一点跑除复杂业务需求的基本代码:

    var MutationObserverMRN = window.MutationObserver || window.WebKitMutationObserver;
    var observerM, targetM;
    var observerR, targetR;
    var observerN, targetN;
    var configGYFBUI = {
        'characterData' : true,
        'characterDataOldValue' : true,
        'childList': true,
        'subtree' : true
    };
    functionobserverMessages(nodeId, type) {
        var idDiv = document.getElementById(nodeId);
        var parentM = (idDiv.childNodes[0].nodeName == 'A') ? idDiv.childNodes[0] : idDiv;
        targetM = parentM.querySelectorAll('span')[1];
        if (!observerM) {
            observerM = new MutationObserverMRN(function(mutations) {
                var strCount = (targetM.innerText == 'undefined') ? '0' : targetM.innerText;
                if (parseInt(strCount) > 0) {
                    var url = 'https://m.facebook.com' + parentM.getAttribute('href');
                    var href = window.location.href;
                    var reg = /messages/;
                    if (!reg.test(href)) {
                        JSInterfaceManager.receiveFbNoti(type, url, strCount);
                    }
                }
            });
        }
        observerM.observe(targetM, configGYFBUI);
    }
    functionobserverRequests(nodeId, type) {
        var idDiv = document.getElementById(nodeId);
        var parentR = (idDiv.childNodes[0].nodeName == 'A') ? idDiv.childNodes[0] : idDiv;
        targetR = parentR.querySelectorAll('span')[1];
        if (!observerR) {
            observerR = new MutationObserverMRN(function(mutations) {
                var strCount = (targetR.innerText == 'undefined') ? '0' : targetR.innerText;
                if (parseInt(strCount) > 0) {
                    var url = 'https://m.facebook.com' + parentR.getAttribute('href');
                    JSInterfaceManager.receiveFbNoti(type, url, strCount);
                }
            });
        }
        observerR.observe(targetR, configGYFBUI);
    }
    functionobserverNotifications(nodeId, type) {
        var idDiv = document.getElementById(nodeId);
        var parentN = (idDiv.childNodes[0].nodeName == 'A') ? idDiv.childNodes[0] : idDiv;
        targetN = parentN.querySelectorAll('span')[1];
        if (!observerN) {
            observerN = new MutationObserverMRN(function(mutations) {
                var strCount = (targetN.innerText == 'undefined') ? '0' : targetN.innerText;
                if (parseInt(strCount) > 0) {
                    var url = 'https://m.facebook.com' + parentN.getAttribute('href');
                    JSInterfaceManager.receiveFbNoti(type, url, strCount);
                }
            });
        }
        observerN.observe(targetN, configGYFBUI);
    }
    observerMessages('messages_jewel', 'messages');
    observerRequests('requests_jewel', 'requests');
    observerNotifications('notifications_jewel', 'notifications');

    这里写图片描述

  • 相关阅读:
    Code Forces Gym 100886J Sockets(二分)
    CSU 1092 Barricade
    CodeChef Mahesh and his lost array
    CodeChef Gcd Queries
    CodeChef GCD2
    CodeChef Sereja and LCM(矩阵快速幂)
    CodeChef Sereja and GCD
    CodeChef Little Elephant and Balance
    CodeChef Count Substrings
    hdu 4001 To Miss Our Children Time( sort + DP )
  • 原文地址:https://www.cnblogs.com/7qin/p/9602118.html
Copyright © 2011-2022 走看看