Asp.Net ScriptManager 导致 jQuery Widget 出现问题

Posted

技术标签:

【中文标题】Asp.Net ScriptManager 导致 jQuery Widget 出现问题【英文标题】:Asp.Net ScriptManager causing issues with jQuery Widget 【发布时间】:2018-03-14 13:13:38 【问题描述】:

多年来,我一直在网站上同时使用 ScriptManager 和 jQuery 滑块小部件,但我最近遇到了一个问题,导致小部件无法正常工作。我设法解决了这个问题,但这更多的是运气而不是专业知识。我希望有人可以提供该问题背后的原因,并且该修复程序可能对遇到相同问题的其他人有用。

我使用了一个脚本聚合器,它将我的脚本组合在一起 - 这是它包含的内容 - 所有代码 sn-ps 都已配对为简洁起见:

vendor/Modernizr.min.js
vendor/jQuery.3.0.0.min.js
vendor/jQuery-UI.1.12.1.min.js
vendor/jQuery-UI.TouchPunch.min.js
propriertary/LoanSelector.js
DefaultInit.js

这是 DefaultInit.js 的内容:

$(document).ready(function () 
    loanSelector.init();
);

这是 LoanSelector.js 的基本内容

var loanSelector = function () 

    var pub = , $ctl = $("#loan-selector"),
        $sliderAmount = $ctl.find(".slider-amount:first"),
        $widgetAmount = $sliderAmount.find(".widget:first");

    function initControl() 
        initWidgetAmount(100, 2000, 100, $("#hfStartAmount").val());
    

    function initWidgetAmount(min, max, step, initialVal) 
        $widgetAmount.slider(
        );
    

    pub.init = function () 
        initControl();
    ;

    return pub;
 ();

现在这可以工作了 - 但只有页面上没有 ScriptManager。

添加脚本管理器后,滑块小部件不会加载 - 没有错误 - 没有。

缓存的元素是页面上的永久固定装置 - 因此这不是元素在某个时间点不存在的情况。

这是 ScriptManager 代码:

    <asp:ScriptManager ID="SM" runat="server"
        EnableCdn="true"
        LoadScriptsBeforeUI="false"
        EnablePageMethods="true">
    </asp:ScriptManager>

如果我进行更改,我可以使用页面上的 ScriptManager 加载小部件 - 这是另一个有效的 LoanSelector.js 版本:

var loanSelector = function () 

    var pub = , $ctl, $sliderAmount, $widgetAmount;

    function cacheElements() 
        $ctl = $("#loan-selector"),
        $sliderAmount = $ctl.find(".slider-amount:first"),
        $widgetAmount = $sliderAmount.find(".widget:first");
    

    function initControl() 
        // This is new
        cacheElements();

        initWidgetAmount(100, 2000, 100, $("#hfStartAmount").val());
    

    function initWidgetAmount(min, max, step, initialVal) 
        $widgetAmount.slider(
        );
    

    pub.init = function () 
        initControl();
    ;

    return pub;
 ();

那么,任何人都可以解释一下为什么它可能不起作用以及修复为什么起作用?

【问题讨论】:

几个问题,控制台有错误吗?你试过放调试器吗?进入你的函数的各个部分,看看命中了什么? LoanSelector 的 init() 函数是什么?我在pub对象上看到了,但是你调用了loanSelector.init(),你只需要调用loanSelector()吗? 我认为可能 ScriptManager 必须改变脚本的加载方式,如果您的脚本在加载 html 之前加载,那么它找不到元素。检查这一点的最简单方法是在调用 initWidgetAmount 方法之前立即为每个工作和非工作解决方案添加“conslole.log($ctl.length)。如果长度为 0,在非工作示例中,表示未加载 HTML 内容当方法被调用时。 @andrewf - 我在 Chrome 中检查了页面,看不到任何明显的错误 - pub 是公共接口 - 我在 document.ready 中调用 init。 你几乎可以看到模块模式了。检查 $(document).ready(function () if(typeof(loanSelector) === "undefined") loanSelector.init(); );如果这是真的,你的脚本管理器需要被取出来。 会不会和scriptmanager的部分页面渲染有关?所以 document.ready() 没有被触发? 【参考方案1】:

第一个方法在执行时填充变量:

var pub = , $ctl = $("#loan-selector"),
    $sliderAmount = $ctl.find(".slider-amount:first"),
    $widgetAmount = $sliderAmount.find(".widget:first");

所以#loan-selector.slider-amount:first.widget:first 需要在调用它之前在页面的 DOM 中呈现。

第二个变体在调用loanSelector.init() 时填充,并且通过代码中调用它的位置加载 DOM。

&lt;asp:ScriptManager&gt; 为您提供了一个服务器端脚本集合,控件可以轻松添加到其中,但它呈现为&lt;script&gt; 标签列表,并且顺序可能很重要 - 页面中的另一个控件可能意味着您的 DOM代码运行时依赖尚未加载。脚本按顺序运行,但不等待 DOM 渲染完成。

jQuery 有它自己的组件结构,你可以使用它,以及一个你可以依赖的 DOM 就绪方法 - 你已经在 DefaultInit.js 中使用它,这就是为什么 loanSelector.init() 可以访问 DOM 而直接执行的代码不会。

你已经有了一个修复,你的第二个脚本是更好的做法,因为它不依赖于执行时间。

另一种选择是在$(document).ready 中调用您的loanSelector 函数:

$(function()
    // In this DOM ready function your elements should be ready to find
    var loanSelector = ...
    ...

    // And you may not need this, as you can init in the actual function
    loanSelector.init();
);

【讨论】:

以上是关于Asp.Net ScriptManager 导致 jQuery Widget 出现问题的主要内容,如果未能解决你的问题,请参考以下文章

如何从用 asp.net 中的 scriptmanager.registerclientscript 编写的 javascript 确认框返回值?

ASP.Net ScriptManager 在 Machine.Config 中全局设置 ScriptMode

ASP.NET使用UpdatePanel实现AJAX

同一个ASP.NET页面放置多个UpdatePanel分别刷新的解决办法。.

ASP.NET AJAX扩展控件

ASP.NET 页面上的倒数计时器