我在我的_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视图中注入一些内容。
我该怎么做呢?
我解决这个完全不同的路线(因为我很着急,不想实现一个新的HtmlHelper):
我用一个大的if-else语句包装了我的Partial View:
@if ((bool)ViewData["ShouldRenderScripts"] == true){
// Scripts
}else{
// Html
}
然后,我用自定义ViewData调用了两次Partial:
@Html.Partial("MyPartialView", Model,
new ViewDataDictionary { { "ShouldRenderScripts", false } })
@section scripts{
@Html.Partial("MyPartialView", Model,
new ViewDataDictionary { { "ShouldRenderScripts", true } })
}
OP的目标是将内联脚本定义到他的Partial View中,我假设这个脚本仅特定于该Partial View,并将该块包含到他的脚本部分中。
我明白他想要局部视图是独立的。这个想法类似于使用Angular时的组件。
我的方法是将脚本原样保存在Partial View中。现在的问题是,当调用Partial View时,它可能会在所有其他脚本(通常被添加到布局页面的底部)之前执行脚本。在这种情况下,您只需让Partial View脚本等待其他脚本。有几种方法可以做到这一点。我之前用过的最简单的方法是在body上使用事件。
在我的布局中,我会在底部有这样的东西:
// global scripts
<script src="js/jquery.min.js"></script>
// view scripts
@RenderSection("scripts", false)
// then finally trigger partial view scripts
<script>
(function(){
document.querySelector('body').dispatchEvent(new Event('scriptsLoaded'));
})();
</script>
然后在我的局部视图(在底部):
<script>
(function(){
document.querySelector('body').addEventListener('scriptsLoaded', function() {
// .. do your thing here
});
})();
</script>
另一种解决方案是使用堆栈来推送所有脚本,并在最后调用每个脚本。其他解决方案,如前所述,是RequireJS/AMD模式,它也非常有效。
有一种方法可以在局部视图中插入部分,尽管它并不漂亮。你需要从父视图中访问两个变量。由于部分视图的部分目的就是创建该section,因此需要这些变量是有意义的。
下面是在局部视图中插入一个section的样子:
@model KeyValuePair<WebPageBase, HtmlHelper>
@{
Model.Key.DefineSection("SectionNameGoesHere", () =>
{
Model.Value.ViewContext.Writer.Write("Test");
});
}
在页面中插入部分视图…
@Html.Partial(new KeyValuePair<WebPageBase, HtmlHelper>(this, Html))
您还可以使用此技术在任何类中以编程方式定义节的内容。
享受吧!
使用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()));
}
}
}