2017-06-13 76 views
4

我有一个View组件,其中包含Razor(.cshtml)文件中的一些jQuery。脚本本身对视图非常具体(处理一些第三方库的某些配置),所以我想为了组织的目的而将脚本和HTML保存在同一个文件中。查看组件中的Javascript

问题是该脚本未呈现在_Layout脚本部分。显然,这仅仅是关于View组件的how MVC handles脚本。

我可以只是有在剃刀文件的脚本,但脚本部分内绕过它。

但后来我遇到了依赖问题 - 因为jQuery在引用库之前使用(对库的引用接近_Layout文件的底部)。

除了将jQuery引用作为Razor代码的一部分(这将阻碍HTML渲染放置在组件的哪个位置)之外,是否有任何巧妙的解决方案?

我目前不在代码前面,但是如果有人需要更好地理解它,我一定会提供它。

回答

0

节只在查看工作不局部视图查看 组件工作(Default.cshtml独立于主ViewResult及其Layout值执行默认情况下是null),这就是由设计。

你可以用它来render sectionsLayoutpartial viewview component's视图声明。但是,在部分和视图组件中定义的部分不会返回到呈现视图或其布局。 如果您想在部分视图或视图组件中使用jQuery或其他库引用,则可以在Layout页面中将库引入head而不是body

实施例:

查看组件: ViewComponent的

public class ContactViewComponent : ViewComponent 
{ 
    public IViewComponentResult Invoke() 
    { 
     return View(); 
    } 
} 

位置:

/Views/[CurrentController]/Components/[NameOfComponent]/Default.cshtml 
/Views/Shared/Components/[NameOfComponent]/Default.cshtml 

Default.cshtml:

@model ViewComponentTest.ViewModels.Contact.ContactViewModel 

<form method="post" asp-action="contact" asp-controller="home"> 
    <fieldset> 
     <legend>Contact</legend> 
     Email: <input asp-for="Email" /><br /> 
     Name: <input asp-for="Name" /><br /> 
     Message: <textarea asp-for="Message"></textarea><br /> 
     <input type="submit" value="Submit" class="btn btn-default" /> 
    </fieldset> 
</form> 

_Layout.cshtml

<!DOCTYPE html> 
    <html> 
    <head> 
    ... 
     @RenderSection("styles", required: false) 
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script> 
    </head> 
    <body> 
     @RenderBody() 
    ... 
    //script move to head 
     @RenderSection("scripts", required: false) 
    </body> 
    </html> 

查看。CSHTML:

@{ 
    Layout = "~/Views/Shared/_Layout.cshtml";  
} 
.................. 
@{Html.RenderPartial("YourPartialView");} 
.................. 
@await Component.InvokeAsync("Contact") 
.................. 
@section Scripts { 
    <script> 
    //Do somthing 
    </script> 
} 

View组件由grahamehorner(可以了解更多信息here

脚本并没有在ViewComponent渲染@section,视图组件 应具备的能力在@section中包含脚本,而不像 部分视图,因为组件可以在许多视图中重用,并且组件负责其自身的功能。

2

我决定写一个ScriptTagHelper,它提供了一个“OnContentLoaded”属性。如果为true,那么使用Javascript函数将脚本标记的内容包裹起来,一旦文档准备好就执行。这可以避免当ViewComponent脚本触发时尚未加载jQuery库的问题。一个ViewComponent内

[HtmlTargetElement("script", Attributes = "on-content-loaded")] 
    public class ScriptTagHelper : TagHelper 
    { 
     /// <summary> 
     /// Execute script only once document is loaded. 
     /// </summary> 
     public bool OnContentLoaded { get; set; } = false; 

     public override void Process(TagHelperContext context, TagHelperOutput output) 
     { 
     if (!OnContentLoaded) base.Process(context, output); 

     var content = output.GetChildContentAsync().Result; 
     var javascript = content.GetContent(); 

     var sb = new StringBuilder(); 
     sb.Append("document.addEventListener('DOMContentLoaded',"); 
     sb.Append("function() {"); 
     sb.Append(javascript); 
     sb.Append("});"); 

     output.Content.SetHtmlContent(sb.ToString()); 
     } 
    } 

用法示例:

<script type="text/javascript" on-content-loaded="true"> 
    $('.button-collapse').sideNav(); 
</script> 

可能有比这更好的办法,但这迄今已为我工作。