c# - 如何避免在 ASP.NET 代码隐藏中编写困惑的 JavaScript?

标签 c# javascript asp.net webforms code-behind

我想知道在 ASP.NET 中使用 Javascript 的最佳做法是什么。

我不知道这是否是最佳实践,但我在代码隐藏中添加了 javascript 客户端事件。它工作正常,但这是最佳做法吗?

例如,我有一个单选按钮控件,并在 Page_Init 中添加了 Javascript 客户端事件。可以多次调用页面初始化,因此每次调用 Page_It 时都会呈现 Javascript。

此外,调试长 Javascript 字符串也很困难。怎样才能更干净……有什么办法吗?

让我们看一个包含 Javascript 的变量示例:

scripts.Text += "<script type='text/javascript'>function ValidateDdl" + metachamp.ID +
"(sender, args) {  if(" + txtReason.ClientID + ".GetText() != '' ||" +
dynamicControl.ClientID +
".style.display == 'none' || HiddenFieldSaveError.Contains('" + metachamp.ID +
"') ){" + dynamicControl.ClientID + ".className='';HiddenFieldError.Remove(" +
metachamp.ID + ");" + errorImage.ClientID +
".SetClientVisible(false);args.IsValid = true;}else{var comboVal = document.getElementById('" +
Image9.ClientID + "'.substring(0,'" + Image9.ClientID +
"'.length - 6) + 'ddl').value ;if (comboVal != '0' ) {args.IsValid = true;HiddenFieldError.Remove(" +
metachamp.ID + ");" + validImage.ClientID +
".SetClientVisible(false);HiddenField.Remove('Bypass-' + '" +
metachamp.ID.ToString() + "');HiddenFieldSaveError.Remove(" + metachamp.ID +
");" + dynamicControl.ClientID + ".className='';" + errorImage.ClientID +
".SetClientVisible(false);}";

最佳答案

第一步是将 JavaScript 从代码隐藏和值插值中分离出来。与动态构建 JavaScript 不同的是,该方法是使用 给定参数 的 JavaScript 函数。

在第一阶段之后,我们得到了如下内容(请原谅部分翻译,这让我头疼)。注意闭包构建器模式的使用;在实际代码中,我会进一步将其作为一个单独的模块。

function makeValidator(champId, opts) {
    return function (sender, args) {
        // Now this is when it gets harry..
        //
        // Use $get (and $find) inside ASP.NET, especially when
        // dealing with ASP.NET AJAX integration to find a control by ID.
        //
        // HOWEVER, the code uses what appears to be some DevExpress
        // controls and thus must be accessed.. differently, mainly either by
        //   1. `window[clientId]` or
        //   2. `ASPxClientControl.GetControlCollection().GetByName(id);`
        // This is just one of those icky things to deal with; I've shown usage
        // of the former and it may need to be applied to the other controls as well.
        //
        var reasonControl = window[opts.reasonId];        // DX control
        var dynamicControl = $get(opts.dynamicControlId); // normal ASP.NET/DOM
        var errorImage = window[opts.errorImageId];       // DX control
        if(reasonControl.GetText() != '' || dynamicControl.style.display == "none") {
            dynamicControl.className='';
            errorImage.SetClientVisible(false);
            args.IsValid = true;
        }
        // etc.
    }
}

应该清楚的是,JavaScript 代码独立于任何字符串插值。它是一个普通函数,当使用特定参数(由 API 定义)调用时,具有特定行为。虽然有不同的方法来“加载/注入(inject)”此 JavaScript(这在 UpdatePanels 和嵌套/复杂层次结构发挥作用时确实很重要),但我们假设它当前位于 <script> 中。在页面的标记中。

现在,让我们将验证器连接到控件 - 这完全是虚构的,但它显示了数据绑定(bind)的用法以及在代码隐藏中实际创建 JavaScript“调用”,我们稍后会明白为什么. (正确使用数据绑定(bind)实际上很重要,因为它延迟调用 CreateValidator 函数,直到分配了控件的 ClientID。)

<!-- Use of the DataBind Container/Eval may be useful, but ignoring that.. --!>
<control:BlahBlah Id="ImaControl"
                  OnClientValidate="<%# CreateValidator(ImaControl) %>"/>

然后回到代码隐藏:

protected string CreateValidator(Control c) {
    var champId = c.ClientID; // example, not necessarily true

    // Then setup other values to supply to the function. While JSON is not
    // *exactly* like a JS object literal it is close enough so we Just Don't Care.
    // I prefer Json.NET from Newtonsoft, but the standard support is just fine.
    // (The champId could also be serialized here, but I chose to show passing
    //  two arguments, one NOT escaped; we assume champId doesn't contain \s or 's.)
    var opts = new JavaScriptSerializer().Serialize(new {
        reasonId = reasonControl.ClientID,
        dynamicControlId = dynamicControl.ClientID,
        errorImageId = Error9.ClientId
    });

    // The use of parenthesis and actual JavaScript returned depends on if the
    // client-side validation property takes JavaScript to execute (common) or if
    // it takes a function to execute later, as found in DevExpress/some libraries.
    // (Remember from above that makeValidator returns a new function.)

    // For DX/DevExpress:
    return string.Format("makeValidator('{0}', {1})", champId, opts);

    // Normal ASP.NET might look like this:
    return string.Format("return makeValidator('{0}', {1}).apply(this, arguments)",
                    champId, opts);
}

这就是它的要点,包括错误。然而,这种方法有很多变体(包括 ASP.NET AJAX ScriptControl 魔术)和需要考虑的微妙因素;要记住和努力争取的重点是:

分离 JavaScript 代码并使用 API 来传递值

关于c# - 如何避免在 ASP.NET 代码隐藏中编写困惑的 JavaScript?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25816881/

相关文章:

c# - 如何设置按钮悬停并单击前景的样式?

javascript - 无法修复我的 angularjs 应用程序路径中的主题标签

asp.net - 如何在ASP.NET MVC 2中为Html.EditorForModel()方法获取textarea

ASP.Net MVC 和 Comet (WebSync)

c# - 如何将您的 Unity 项目输入更新为 SteamVR 2.0?

c# - 错误仅在发布后出现 : "Unable to connect to any of the specified MySQL hosts."

C# Visual Studio 代码 : Building a Hello World executable

javascript - 如何使用 document.querySelector 从使用 document.querySelector 的节点中选择特定的文本输出?

javascript - Href 与选择框

c# - 从 Master 更新内容页面