11.3 OnReady 触发问题

11.3.1 基本原理

在页面中, 硕正控件的创建过程是异步的, 所谓异步, 就是你无法预知、要求控件什么时候创建好, 但是当硕正控件被成功创建后，它是会触发 OnReady 事件的，用程序的角度看，相当于硕正控件反向调用了页面的 OnReady 函数。控件通过调用 OnReady 函数通知页面：我已经被创建了，您可以在该事件中书写初始语句了，比如打开报表模板、加载数据等等。
硕正控件必须触发过 OnReady 事件后才是可用的。如果您在控件触发该事件前调用函数如 AF.func("print", ""), 控件是没有反应的, 不会有任何动作.
一种想当然的错误 js 脚本如下：

     insertReport('AF', 'rebar=none');
     AF.func("build", "../test/myreport.xml");
     ...

insertReport( )执行完后，不等于控件已经创建好, 下面的 AF.func( ) 函数偶尔可能会执行成功, 但极有可能是执行失败的.

11.3.2 多个控件的触发机制

如果页面中包含了多个硕正插件, 那么每个插件都会触发一遍 OnReady, 例如下面的html片段，就表示包含了2个紧挨着的控件，其 id 分别为 AF1、AF2:

    <div style="position:relative;width:96%;height:400px">
        <script>insertReport('AF1', '')</script>
    </div>
    <div style="position:relative;width:96%;height:400px">
        <script>insertReport('AF2', '')</script>
    </div>

AF1、AF2将先后被页面创建，并将分别触发 OnReady 事件, 也就是说页面中的 OnReady(id) 函数将一共被执行 2 遍。

注意: 控件未必是按照从上到下的次序创建的，也就是说你无法预测 OnReady( id ) 函数中 id 参数是先出现 AF1 还是 AF2！

您的 OnReady 函数中，应该增加 id 的条件判断语句，按类似如下的格式书写:

    function OnReady(id)
    {
     if(id == 'AF1')
      AF1.func("build", "../xml/report1.xml");
     else if(id == 'AF2')
      AF2.func("build", "../xmlres/genrpt.aspx?n=133");
    }

如下写法是错误的，有严重的逻辑问题，初学者很容易犯这个错误:

    function OnReady(id)
    {
      AF1.func("build", "../xml/report1.xml");
      AF2.func("build", "../xmlres/genrpt.aspx?n=133");
    }

11.3.3 IE 的触发机制

在不同的浏览器下，控件的创建时机是不一样的，在 IE 浏览器下，控件的创建时机是：控件首次出现在可视区域时。举个例子，假如您的页面很长，控件隐藏在页面的下方，需要拖拽右侧滚动条才能让控件显示：
控件一开始是不被创建的，直到您拖拽滚动条，让控件出现在浏览器窗口的可视区域的一瞬间，它才被创建、并触发 OnReady 事件的！

仅 IE 浏览器是这样的，Chrome、Firefox 浏览器不存在这个问题，不管控件是不是在可视区域，都将被快速创建.

11.3.4 Firefox的触发机制

考察一下这段典型的 OnReady( ) 事件代码:

    function OnReady(id) {
     AF.func("Build", "../test/myreport.xml");
    }

控件反向调用(即触发)这段代码时, 必须要具备一个前提:
AF 作为 js 对象, 它本身已经被页面注册了, 或者已经被浏览器解析到页面的 DOM 树中了.
一般情况下, 这个条件都是具备的, 即 AF 这个 js 对象已经存在。然而, 我们发现，在Firefox 在 30 版及后续的版本中，经常会发生这样的现象：当OnReady( )触发时, 页面 DOM 中尚未包含这个名为 "AF" 的 js 对象!
并且, 页面越复杂、网速越慢, 这种意外出现得越频繁.
为了解决这个问题, 页面的 OnReady 机制必须加以修正, 例如可以写成这样:

    var countFF = 0;  //计数器
    function cooper()
    {
     countFF++;
     if(countFF != 2) return;
     AF.func("Build", "../test/myreport.xml");
    }
    function OnReady(id)
    {
     cooper();
    }
    $(document).ready( )
    {
     cooper();
    }

您看懂了吗? jquery 的 $(document).ready( ) 事件是发生在 DOM 对象全部注册成功时的, 这样就能保证前面提到的前提能满足.
如果您没有使用 jquery, 那么可以试试用 <body onload="cooper()"> 代替之.
如果您的页面中有多个控件, 那就要修改计数器的控制了, 假如页面中有 2 个硕正控件, cooper( )函数应该写成这样：

    function cooper()
    {
     countFF++;
     if(countFF != 3) return;  //注: cooper( )一共会被调用 3 次
     AF1.func("Build", "../test/myreport1.xml");
     AF2.func("Build", "../test/myreport2.xml");
    }

这种写法能兼容其它浏览器。