如果在页面底部呈现捆绑脚本,如何使用动态JQuery脚本定义部分视图?

时间:2014-02-01 22:29:19

标签: c# jquery asp.net-mvc razor asp.net-mvc-partialview

我有一个使用MVC4和Razor视图的Web应用程序,它们使用了大量的JQuery和其他插件脚本。

为了加快视图的渲染速度,我相信一般情况下,最好将脚本渲染到正文的底部,因此布局(大大合并)如下所示:

<body>
    @RenderBody()

    @Scripts.Render("~/bundles/jquery")
    @Scripts.Render("~/bundles/other")

    @RenderSection( "Scripts", false )
</body>

Scripts部分允许特定视图添加其他JQuery函数,并且保证它们在JQuery库之后呈现。到目前为止,非常好。

现在考虑视图中的以下代码段,该代码段为集合中的每个项目呈现部分:

@foreach (var item in Model.Items)
{
    Html.RenderPartial("_MyPartial", item);
}

此部分(_MyPartial)需要根据集合项详细信息(例如以下代码段)为控件呈现JQuery:

$(function () {
    $("#@(Model.Id)").click(function () {
        // do something when control on partial with id Model.Id is clicked
        alert("I've been clicked!");
    });
});

部分视图JQuery函数未执行,因为在每个集合项的_MyPartial脚本之前未加载JQuery库。在chrome调试器中运行显示$ not defined,这证实了这一点。

我可以做一些非常丑陋的事情,例如在脚本部分复制每个foreach语句,用于调用partial的所有视图,然后让父视图生成脚本。但是,这实际上会破坏局部视图的可重用性。

有没有办法让Razor部分视图脚本延迟渲染(例如在父脚本部分中),或者是针对此问题的不同方法?

2 个答案:

答案 0 :(得分:6)

不幸的是,部分视图中不支持部分。一种可能性就是编写自定义帮助程序,如本文所述:https://stackoverflow.com/a/9663249/29407

这将允许您在文档末尾调用占位符助手,该助手将呈现已在partials中注册的所有脚本。

这就是说,将部分需要的客户端功能作为jQuery插件公开通常是个更好的主意。然后在一些DOM元素上调用这个插件非常容易:

$('.someElement').somePlugin();

这样您就不再需要在部分中执行任何$("#@(Model.Id)")。部分内容通常不应包含任何脚本。

答案 1 :(得分:0)

作为参考,我使用了Darin的解决方案,并且还扩展了我需要注册不在文件中的原始脚本的情况。其他方法是:

public static class HtmlExtensions
{
    public static IHtmlString RegisteredRawScripts(this HtmlHelper htmlHelper)
    {
        var ctx = htmlHelper.ViewContext.HttpContext;
        var registeredScripts = ctx.Items["_rawscripts_"] as Stack<string>;
        if (registeredScripts == null || registeredScripts.Count < 1)
        {
            return null;
        }
        var sb = new StringBuilder();
        foreach (var script in registeredScripts)
        {
            sb.AppendLine("\r\n" + script);
        }
        return new HtmlString(sb.ToString());
    }

    public static void RegisterRawScript(this HtmlHelper htmlHelper, string script)
    {
        var ctx = htmlHelper.ViewContext.HttpContext;
        var registeredScripts = ctx.Items["_rawscripts_"] as Stack<string>;
        if (registeredScripts == null)
        {
            registeredScripts = new Stack<string>();
            ctx.Items["_rawscripts_"] = registeredScripts;
        }
        if (!registeredScripts.Contains(script))
        {
            registeredScripts.Push(script);
        }
    }
}

在您的部分内容中,您可以执行以下操作:

@Html.RegisterRawScript(script);  // where script is your raw script as a string

在您的布局中,您注册了原始脚本:

@Html.RegisteredRawScripts()
相关问题