Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/426.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
视图组件中的Javascript_Javascript_C#_Asp.net Mvc_Razor_Asp.net Core Mvc - Fatal编程技术网

视图组件中的Javascript

视图组件中的Javascript,javascript,c#,asp.net-mvc,razor,asp.net-core-mvc,Javascript,C#,Asp.net Mvc,Razor,Asp.net Core Mvc,我有一个视图组件,它在Razor(.cshtml)文件中包含一些jQuery。脚本本身非常特定于视图(处理一些第三方库的配置),因此为了组织起见,我希望将脚本和HTML保存在同一个文件中 问题在于_布局脚本部分中没有呈现脚本。显然,这只是有关视图组件的脚本 我可以通过将脚本放在Razor文件中来解决这个问题,但是不能放在脚本部分中 但随后我遇到了依赖性问题——因为jQuery是在对库的引用之前使用的(对库的引用位于_布局文件的底部附近) 除了将对jQuery的引用作为Razor代码的一部分(这会

我有一个视图组件,它在Razor(.cshtml)文件中包含一些jQuery。脚本本身非常特定于视图(处理一些第三方库的配置),因此为了组织起见,我希望将脚本和HTML保存在同一个文件中

问题在于_布局脚本部分中没有呈现脚本。显然,这只是有关视图组件的脚本

我可以通过将脚本放在Razor文件中来解决这个问题,但是不能放在脚本部分中

但随后我遇到了依赖性问题——因为jQuery是在对库的引用之前使用的(对库的引用位于_布局文件的底部附近)

除了将对jQuery的引用作为Razor代码的一部分(这会妨碍组件所在位置的HTML呈现)之外,还有其他聪明的解决方案吗

我目前不在代码前面,但如果有人需要查看代码以更好地理解它,我当然可以在有机会时提供它

节仅在视图中工作不在局部视图视图中工作 组件
Default.cshtml
独立于主
ViewResult
执行,默认情况下其
Layout
值为
null
),这是通过设计实现的

您可以使用它为
局部视图
视图组件的
视图声明的
布局
渲染节。但是,在partials和view组件中定义的节不会流回到渲染视图或其布局。 如果您想在局部视图或视图组件中使用jQuery或其他库引用,则可以在
布局
页面中将库拉入
标题
,而不是
正文

示例:

查看组件:

public class ContactViewComponent : ViewComponent
{
    public IViewComponentResult Invoke()
    {
        return View();
    }
}
/Views/[CurrentController]/Components/[NameOfComponent]/Default.cshtml
/Views/Shared/Components/[NameOfComponent]/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 =  "~/Views/Shared/_Layout.cshtml";     
}
..................
@{Html.RenderPartial("YourPartialView");}
..................
@await Component.InvokeAsync("Contact")
..................
@section Scripts {
    <script>
    //Do somthing
    </script>
}
视图组件的位置:

public class ContactViewComponent : ViewComponent
{
    public IViewComponentResult Invoke()
    {
        return View();
    }
}
/Views/[CurrentController]/Components/[NameOfComponent]/Default.cshtml
/Views/Shared/Components/[NameOfComponent]/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 =  "~/Views/Shared/_Layout.cshtml";     
}
..................
@{Html.RenderPartial("YourPartialView");}
..................
@await Component.InvokeAsync("Contact")
..................
@section Scripts {
    <script>
    //Do somthing
    </script>
}
Default.cshtml:

public class ContactViewComponent : ViewComponent
{
    public IViewComponentResult Invoke()
    {
        return View();
    }
}
/Views/[CurrentController]/Components/[NameOfComponent]/Default.cshtml
/Views/Shared/Components/[NameOfComponent]/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 =  "~/Views/Shared/_Layout.cshtml";     
}
..................
@{Html.RenderPartial("YourPartialView");}
..................
@await Component.InvokeAsync("Contact")
..................
@section Scripts {
    <script>
    //Do somthing
    </script>
}
@model ViewComponentTest.ViewModels.Contact.ContactViewModel
接触
电子邮件:
名称:
消息:
\u 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>

...
@RenderSection(“样式”,必填项:false)
@RenderBody()
...
//脚本移到头部
@RenderSection(“脚本”,必需:false)
View.cshtml:

public class ContactViewComponent : ViewComponent
{
    public IViewComponentResult Invoke()
    {
        return View();
    }
}
/Views/[CurrentController]/Components/[NameOfComponent]/Default.cshtml
/Views/Shared/Components/[NameOfComponent]/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 =  "~/Views/Shared/_Layout.cshtml";     
}
..................
@{Html.RenderPartial("YourPartialView");}
..................
@await Component.InvokeAsync("Contact")
..................
@section Scripts {
    <script>
    //Do somthing
    </script>
}
@{
Layout=“~/Views/Shared/_Layout.cshtml”;
}
..................
@{Html.RenderPartial(“YourPartialView”);}
..................
@wait Component.InvokeAsync(“联系人”)
..................
@节脚本{
//干坏事
}
查看组件的方式:(您可以查看更多信息)

@section脚本不会在ViewComponent、view component中呈现 应该能够在@section中包含脚本 作为组件的部分视图可以跨多个视图和 组件负责自己的功能


我决定写一个ScriptTagHelper,它提供一个“OnContentLoaded”属性。如果为true,则我使用Javascript函数包装脚本标记的内部内容,以便在文档准备就绪后执行。这避免了当ViewComponent的脚本启动时jQuery库尚未加载的问题

[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);
     } 
     else
     {
        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()); 
     }
  }
}
[HtmlTargetElement(“脚本”,Attributes=“on content loaded”)]
公共类ScriptTagHelper:TagHelper
{
/// 
///仅在加载文档后执行脚本。
/// 
public bool OnContentLoaded{get;set;}=false;
公共覆盖无效进程(TagHelperContext上下文,TagHelperOutput输出)
{
如果(!OnContentLoaded)
{
过程(上下文、输出);
} 
其他的
{
var content=output.GetChildContentAsync().Result;
var javascript=content.GetContent();
var sb=新的StringBuilder();
sb.追加(“document.addEventListener('DOMContentLoaded',”);
sb.Append(“函数(){”);
sb.Append(javascript);
某人加上(“}”);”;
output.Content.SetHtmlContent(sb.ToString());
}
}
}
ViewComponent中的用法示例:

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

$('.button collapse').sideNav();

可能还有比这更好的方法,但到目前为止,这对我来说很有效。

这是我正在使用的解决方案。它支持外部脚本加载和自定义内联脚本。虽然某些设置代码需要放入布局文件(例如_layout.cshtml),但所有内容都是从视图组件中编排的

布局文件:

public class ContactViewComponent : ViewComponent
{
    public IViewComponentResult Invoke()
    {
        return View();
    }
}
/Views/[CurrentController]/Components/[NameOfComponent]/Default.cshtml
/Views/Shared/Components/[NameOfComponent]/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 =  "~/Views/Shared/_Layout.cshtml";     
}
..................
@{Html.RenderPartial("YourPartialView");}
..................
@await Component.InvokeAsync("Contact")
..................
@section Scripts {
    <script>
    //Do somthing
    </script>
}
将其添加到页面顶部附近(在
标记内是一个好地方):


MYCOMPANY=window.MYCOMPANY |{};
MYCOMPANY.delayed=null;
MYCOMPANY.delay=function(f){var e=MYCOMPANY.delayed;MYCOMPANY.delayed=e?function(){e();f();}:f;};
将其添加到页面底部附近(就在关闭
标记之前是一个好地方):

MYCOMPANY.delay=函数(f){setTimeout(f,1)};if(MYCOMPANY.delayed){MYCOMPANY.delay(MYCOMPANY.delayed);MYCOMPANY.delayed=null;}
查看组件:

public class ContactViewComponent : ViewComponent
{
    public IViewComponentResult Invoke()
    {
        return View();
    }
}
/Views/[CurrentController]/Components/[NameOfComponent]/Default.cshtml
/Views/Shared/Components/[NameOfComponent]/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 =  "~/Views/Shared/_Layout.cshtml";     
}
..................
@{Html.RenderPartial("YourPartialView");}
..................
@await Component.InvokeAsync("Contact")
..................
@section Scripts {
    <script>
    //Do somthing
    </script>
}
现在,您可以在代码中的任何位置(包括视图组件)执行此操作,并在页面底部执行脚本:

<script>
    MYCOMPANY.delay(function() {
        console.log('Hello from the bottom of the page');
    });
</script>

MYCOMPANY.delay(函数(){
log(“页面底部的Hello”);
});


具有外部脚本依赖关系

但有时这还不够。有时,您需要加载外部JavaScript文件,并且只在加载外部文件后执行自定义脚本。您还希望在视图组件中协调这一切,以实现完全封装。为此,我在布局页面(或外部Java)中添加了更多的设置代码