Sys.Application.add_load()与$(文档).ready()与pageLoad()的对比

时间:2010-09-02 19:07:12

标签: asp.net-ajax

我的页面有一些需要在页面加载时运行的javascript。所述javascript需要找到ServerControl的客户端组件,它与$ find()一起使用。

当然,如果我直接将代码发送到页面上,它会在页面被读取时执行,并且因为它所依赖的任何内容尚未初始化而失败。

如果我将我的代码放在pageLoad()函数中,它运行得很好,因为asp.net会自动为任何名为pageLoad()的函数连接onload处理程序。问题是我真的不喜欢pageLoad()解决方案 - 主要是因为它是一个单一的全局名称。如果我使用pageLoad()提交一些代码,我只知道其他一些程序员将要复制该方法,在某个地方不合适,我们最终会得到一个包含两个或更多不同pageLoad()函数的页面,并且结果将是一堆神秘的错误,需要永远追查。

所以,我把我的代码放在一个传递给jquery的$(document).ready()的匿名函数中。这失败了,因为它在ServerControl的客户端组件存在之前运行。

因此,我将我的代码放在Sys.Application.add_load()传递给的匿名函数中。这也失败了,因为系统未定义。

所以我最终决定将我的代码放在Sys.Application.add_load()中,然后将它放在$(document).ready()调用的函数中。这样可行,但它几乎与pageLoad()一样令人心痛。

<script type="text/javascript">
    $(document).ready(function(){
        Sys.Application.add_load(function(){
            var component = $find(<clientid>);
            if (component) { <do something> }
        });
    });
</script>

必须有更好的方法来解决这个问题。

有什么想法吗?

4 个答案:

答案 0 :(得分:19)

如果您可以控制代码隐藏,则可以通过以下方式注册要在启动时运行的JavaScript:

this.Page.ClientScript.RegisterStartupScript(
    this.GetType(), 
    "StartupScript", 
    "Sys.Application.add_load(function() { functioncall(); });", 
    true);

只要您的组件已通过Sys.Application.add_init()加载,您应该没问题......

答案 1 :(得分:5)

我想为那些试图构建外部库并尝试在.NET中尽可能遵循不引人注目的javascript思维方式的人提供替代方案。

pageLoad是一种自动连接AJAX事件的绝佳方法,这些事件应该在每个页面加载时触发(无论该加载来自此页面的后退按钮导航,页面的前进按钮导航,AJAX回调,标准页面加载,等等,因为您不必担心等待ScriptManager存在于DOM中,并且它以一种有意义的方式命名,在大多数情况下(pageLoad vs. body.onload有点令人困惑)对于非.NET编码器,但对于.NET人员来说,有意义的是pageLoad会在每次页面加载时触发,包括在回调之后,因为服务器端Page_Load的行为是相同的。话虽如此,您的关注点很好 - 您不希望在给定页面上有两个pageLoad实例,因为它会中断。这是一个直接的javascript解决方案,对于所有开发人员来说都是安全的,允许使用pageLoad,不会担心存在的DOM,确保没有代码冲突,并且对我们来说非常有效。

在主javascript库中,定义pageLoad以及辅助函数:

if (!pageLoad) { var pageLoad = function (sender, args) {}; };
if (!mylibrarynamespace) {var mylibrarynamespace = {};};
if (!mylibrarynamespace.registerStartupScript) mylibrarynamespace.registerStartupScript = function (fn) {
    /* create local pointer for added function */
    var f = fn;

    /* create pointer to existing pageLoad function */
    var pLoad = pageLoad;

    /* add new function pointer to pageLoad by creating new anonymous function (search Google for "javascript enclosures" for why pl and f will persist with this newly defined anonymous function) */
    pageLoad = function (sender, args) {
    pLoad(sender,args);
    f(sender, args);
    }
}

然后,要在客户端代码中的任何位置使用它,只需执行以下操作:

mylibrarynamespace.registerStartupScript(
    function (sender, args){ 
        /* do my AJAX always enabled startup code logic here*/
    }
);

为了更容易地更改功能,我建议传入的匿名函数调用该页面中的函数或控件的库子集,这样您只需要更改库的函数声明(在文件中或在运行时动态) )更改网站特定部分的pageLoad的工作方式。

答案 2 :(得分:3)

我相信如果你在脚本块上面添加(或移动)ScriptManager控件,你就不需要将它包装在jQuery的$(document).ready()函数中。通过这样做,Sys显然可以作为ScriptManager:

  

注入了大量的JavaScript   确切的位置   ScriptManager控件位于   在页面中。 [http://encosia.com/2007/08/16/updated-your-webconfig-but-sys-is-still-undefined/]

然而,这个解决方案仍然可能让你感到胃灼热,因为对于任何毫无戒心的开发人员来说,ScriptManager实际上在这里提供的内容肯定不是很明显。

在ScriptManager中添加脚本引用的另一种方法(参见上面链接文章中讨论的“更好的方法”)并不适合我,因为我不是整个ScriptManager方法的忠实粉丝。 / p>

答案 3 :(得分:0)

尝试使用ScriptManager注册客户端脚本块,但为每个附加函数调用提供唯一标题,特别是如果它使用相同的函数但具有不同的参数值,则具有唯一参数。如果您使用add_load技术,则只应在页面加载不是回发时使用,即仅在页面刷新或页面加载后调用一次而不回发。

试试这个:     ScriptManager.RegisterClientScriptBlock(this,GetType(),&#34;唯一标题&#34;,&#34; alert(&#39; quick test&#39;);&#34;,true);