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

Joh*_*ara 13 javascript asp.net jquery webforms

我多年来一直在网站上使用ScriptManager和jQuery滑块小部件,但我最近遇到了一个阻止小部件工作的问题.我设法解决了这个问题,但这比运气专业更不幸运.我希望有人可以提供问题背后的推理,并且该解决方案可能对具有相同问题的其他人有用.

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

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
Run Code Online (Sandbox Code Playgroud)

这是DefaultInit.js的内容:

$(document).ready(function () {
    loanSelector.init();
});
Run Code Online (Sandbox Code Playgroud)

这是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;
} ();
Run Code Online (Sandbox Code Playgroud)

现在这个工作 - 但只在页面上没有ScriptManager.

添加脚本管理器时,滑块小部件不会加载 - 没有错误 - 什么都没有.

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

这是ScriptManager代码:

    <asp:ScriptManager ID="SM" runat="server"
        EnableCdn="true"
        LoadScriptsBeforeUI="false"
        EnablePageMethods="true">
    </asp:ScriptManager>
Run Code Online (Sandbox Code Playgroud)

如果我进行更改,我可以在页面上使用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;
} ();
Run Code Online (Sandbox Code Playgroud)

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

Kei*_*ith 1

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

var pub = {}, $ctl = $("#loan-selector"),
    $sliderAmount = $ctl.find(".slider-amount:first"),
    $widgetAmount = $sliderAmount.find(".widget:first");
Run Code Online (Sandbox Code Playgroud)

因此#loan-selector,.slider-amount:first.widget:first需要在调用之前在页面的 DOM 中渲染。

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

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

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

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

另一种选择是loanSelector在以下位置调用您的函数$(document).ready

$(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();
});
Run Code Online (Sandbox Code Playgroud)