我在我的_Layout.cshtml中定义了这个部分

@RenderSection("Scripts", false)

我可以很容易地从视图中使用它:

@section Scripts { 
    @*Stuff comes here*@
}

我正在努力解决的问题是如何从局部视图将一些内容注入到这个部分中。

让我们假设这是我的视图页面:

@section Scripts { 

    <script>
        //code comes here
    </script>
}

<div>
    poo bar poo
</div>

<div>
  @Html.Partial("_myPartial")
</div>

我需要在脚本部分中从_myPartial partial视图中注入一些内容。

我该怎么做呢?


当前回答

我能想到的第一个解决方案是使用ViewBag来存储必须呈现的值。

我从来没有试过,如果这个工作从一个局部的观点,但它应该在我看来。

其他回答

我今天遇到了这个问题。我将添加一个工作区,使用<脚本延迟>,因为我没有看到其他答案提到它。

//on a JS file somewhere (i.e partial-view-caller.js)
(() => <your partial view script>)();

//in your Partial View
<script src="~/partial-view-caller.js" defer></script>

//you can actually just straight call your partial view script living in an external file - I just prefer having an initialization method :)

上面的代码摘自我关于这个问题的一篇文章。

使用Mvc Core,你可以创建一个整洁的TagHelper脚本,如下所示。这可以很容易地转换成一个节标记,在这里您也可以给它一个名称(或者名称取自派生类型)。注意,需要为IHttpContextAccessor设置依赖注入。

当添加脚本时(例如在部分中)

<scripts>
    <script type="text/javascript">
        //anything here
    </script>
</scripts>

当输出脚本时(例如在一个布局文件中)

<scripts render="true"></scripts>

Code

public class ScriptsTagHelper : TagHelper
    {
        private static readonly object ITEMSKEY = new Object();

        private IDictionary<object, object> _items => _httpContextAccessor?.HttpContext?.Items;

        private IHttpContextAccessor _httpContextAccessor;

        public ScriptsTagHelper(IHttpContextAccessor httpContextAccessor)
        {
            _httpContextAccessor = httpContextAccessor;
        }

        public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
        {
            var attribute = (TagHelperAttribute)null;
            context.AllAttributes.TryGetAttribute("render",out attribute);

            var render = false;

            if(attribute != null)
            {
                render = Convert.ToBoolean(attribute.Value.ToString());
            }

            if (render)
            {
                if (_items.ContainsKey(ITEMSKEY))
                {
                    var scripts = _items[ITEMSKEY] as List<HtmlString>;

                    var content = String.Concat(scripts);

                    output.Content.SetHtmlContent(content);
                }
            }
            else
            {
                List<HtmlString> list = null;

                if (!_items.ContainsKey(ITEMSKEY))
                {
                    list = new List<HtmlString>();
                    _items[ITEMSKEY] = list;
                }

                list = _items[ITEMSKEY] as List<HtmlString>;

                var content = await output.GetChildContentAsync();

                list.Add(new HtmlString(content.GetContent()));
            }
        }
    }

我能想到的第一个解决方案是使用ViewBag来存储必须呈现的值。

我从来没有试过,如果这个工作从一个局部的观点,但它应该在我看来。

你可以使用这些扩展方法:(保存为PartialWithScript.cs)

namespace System.Web.Mvc.Html
{
    public static class PartialWithScript
    {
        public static void RenderPartialWithScript(this HtmlHelper htmlHelper, string partialViewName)
        {
            if (htmlHelper.ViewBag.ScriptPartials == null)
            {
                htmlHelper.ViewBag.ScriptPartials = new List<string>();
            }

            if (!htmlHelper.ViewBag.ScriptPartials.Contains(partialViewName))
            {
                htmlHelper.ViewBag.ScriptPartials.Add(partialViewName);
            }

            htmlHelper.ViewBag.ScriptPartialHtml = true;
            htmlHelper.RenderPartial(partialViewName);
        }

        public static void RenderPartialScripts(this HtmlHelper htmlHelper)
        {
            if (htmlHelper.ViewBag.ScriptPartials != null)
            {
                htmlHelper.ViewBag.ScriptPartialHtml = false;
                foreach (string partial in htmlHelper.ViewBag.ScriptPartials)
                {
                    htmlHelper.RenderPartial(partial);
                }
            }
        }
    }
}

像这样使用:

示例partial:(_MyPartial.cshtml) 把html放在if里,js放在else里。

@if (ViewBag.ScriptPartialHtml ?? true)
    <p>I has htmls</p>
}
else {
    <script type="text/javascript">
        alert('I has javascripts');
    </script>
}

在你的_Layout中。cshtml,或者任何你想要渲染的部分脚本的地方,放置以下(一次):它将只在当前页面的这个位置渲染所有部分的javascript。

@{ Html.RenderPartialScripts(); }

然后使用您的部分,只需这样做:它将只呈现该位置的html。

@{Html.RenderPartialWithScript("~/Views/MyController/_MyPartial.cshtml");}

遵循不引人注目的原则,“_myPartial”并不完全需要将内容直接注入脚本部分。您可以将这些部分视图脚本添加到单独的.js文件中,并从父视图中将它们引用到@scripts部分。