我应该在哪里包含视图组件的脚本?

时间:2017-03-30 09:47:49

标签: razor asp.net-core asp.net-core-viewcomponent

我尝试在视图组件的视图中添加一个section脚本。

@section scripts {
    <script src="~/somepath" asp-append-version="true"></script>
}

我在共享布局中也有渲染部分

@RenderSection("scripts", required: false)

在部分视图和项目中的其他位置使用时,脚本加载正常。但是,在View Component中,脚本不会加载。

我想我可以将脚本包含在调用组件的每个视图的section标签中。我觉得这不符合视图组件的自包含特性。

我还有其他办法吗?

7 个答案:

答案 0 :(得分:4)

我在viewcomponents中也遇到了section标签的问题。事实证明,据我所知,在viewcomponents中没有它的支持。见https://github.com/aspnet/Home/issues/2037

Jake Shakesworth实施了一个标签助手,如下所示: Javascript in a View Component

另一方面,您可以将它作为

包含在viewcomponent中
<script defer src"...">
  </script>

我的要求是从viewcomponent显示谷歌地图。问题是脚本在jquery,jquery.ui之前调用了 通过使用延迟,您告诉解析器在文档加载之前不执行它,从而避免了必须将其放入布局以便正确执行的问题。 延迟由chrome,safari支持,即(10+),ff(3.6 +),o(15+)

希望这有帮助

这是我的代码示例:

@using MobileVet.WebApp.Services;
@inject ISettingsService SettingsService
@{
     var Options = SettingsService.Value();

    <!--Service Area-->
    <div class="container-fluid">
         <div class="row p-3">
            <!--First column-->
            <div class="col-md-3">
                <h5 class="title">Site Navigation</h5>
                <ul>
                    <li><a href="#!">Home</a></li>
                    <li><a href="#!">Services</a></li>
                    <li><a href="#!">Link 3</a></li>
                    <li><a href="#!">Link 4</a></li>
                </ul> 

            </div>
            <!--/.First column-->
            <hr class="w-100 clearfix d-md-none">

            <!--Second column-->
            <div class="col-md-9">

                <div id="map-canvas" style="min-height: 300px; min-width: 200px;"> 
                </div>
            </div>
            <!--/.Second column-->

        </div>
    </div>
    <!--Service Area-->


<script src="http://maps.google.com/maps/api/js?key=XXXXXXXXXXXXXXXXXXXXXXX&sensor=false"></script>
<script type="text/javascript" src="~/js/components/servicearea.js" defer ></script>

}

请注意,如果视图组件在页面上出现多次,您可能需要编写一些逻辑来防止脚本被多次包含,这不是我的情况

答案 1 :(得分:1)

从我看到的情况来看,ViewComponent中的.bio, .web { position: relative; } 会被忽略,并且不会在"@section Scripts {}"的相关@RenderSection()中呈现

为什么我不知道。

答案 2 :(得分:1)

这就是我使用 Asp.net core 2.0 将脚本插入视图组件的方法。

首先,我创建了一个局部视图,我将其置于视图组件视图文件夹中。

路径:观看/共享/组件/ CalendarWidget / _CalendarScriptsPartial.cshtml

<强> _CalendarScriptsPartial.cshtml

<environment include="Development">
    <script src="~/lib/jquery/dist/jquery.js"></script>
    <script src="~/lib/moment/moment.js"></script>
    <script src="~/lib/fullcalendar/dist/fullcalendar.js"></script>
    <script src="~/js/calendarWidget.js"></script>
</environment>
<environment exclude="Development">
    <script src="~/lib/jquery/dist/jquery.min.js"></script>
    <script src="~/lib/moment/min/moment.min.js"></script>
    <script src="~/lib/fullcalendar/dist/fullcalendar.min.js"></script>
    <script src="~/js/calendarWidget.js"></script>
</environment>

然后,我通过视图组件视图中的Html部分异步辅助方法引入了脚本。

路径:观看/共享/组件/ CalendarWidget / Default.cshtml

<强> Default.cshtml

<section id="calendar"></section>
@await Html.PartialAsync( "Components/CalendarWidget/_CalendarScriptsPartial" )

为了完整起见,这里是我的视图组件类。

路径: ViewComponents / CalendarWidgetViewComponent.cs

<强> CalendarWidgetViewComponent.cs

using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;

namespace LodgersChoice.ViewComponents
{
    public class CalendarWidgetViewComponent : ViewComponent
    {
        public async Task<IViewComponentResult> InvokeAsync( )
        {
            return View( );
        }
    }
}

注意:我的示例中当前不需要Async,但我打算将一个存储库注入到将使用async / await的类的ctor中。

注意2:一旦我完成了这项工作,我计划将所有内容捆绑并缩小为一个脚本。

答案 3 :(得分:0)

ASP.NET Core中的视图组件的作用类似于具有单独控制器的独立视图,因此您可以在视图组件上方插入波纹管标签

@{
Layout = null;
}

在插入波纹管标签后使用相关脚本,例如:

<environment include="Development">

<script src="~/js/chart.js"></script>

</environment>
 <environment exclude="Development">

<script src="~/js/chart.min.js"></script>

</environment>

答案 4 :(得分:0)

视图组件中的

@section脚本{}将被Asp.Net渲染引擎忽略并且不进行渲染。因此,只需在视图组件的末尾使用。另外,如果在布局的末尾指定了jquery脚本,则jquery在视图组件中将不可用。当然,将jquery脚本移到layout的head部分可以解决该问题,但建议最后加载js文件。

因此,如果您希望将jquery脚本保留在布局的末尾并且仍在视图组件中使用jquery,则可以使用javascript domcontentloaded,并且可以将jquery写入domcontentloaded内。这不是永久的好方法,但对我有用。

<script>
    document.addEventListener('DOMContentLoaded', function (event) {
        console.log($ === jQuery)
    });
</script>

或者如@Alberto L. Bonfiglio所述,您还可以尝试将脚本移动到另一个JS文件并推迟将其加载到viewcomponent中:

<script src="viewComponentScript.js" defer></script>

答案 5 :(得分:0)

我正在范围服务中注册 ViewComponents 脚本,然后在布局中的脚本部分之后呈现注册的脚本。

ViewComponentsService.cs

using System;
using System.Collections.Generic;

namespace YourProject.Services
{
    public class ViewComponentsService
    {
        
        private readonly List<Func<object>> _scripts = new List<Func<object>>();

        public IEnumerable<Func<object>> Scripts {
            get { 
                foreach (var script in _scripts)
                {
                    yield return script;
                }
            }
        }
        
        // A dictionary could be used as type for the _scripts collection.
        // Doing so a script Id could be passed to RegisterScript.
        // Usefull if only one script per ViewComponent type needs to be rendered.
        public void RegisterScript(Func<object> script) {
            _scripts.Add(script);
        }

    }
}

不要忘记在启动时注册服务。

services.AddScoped<ViewComponentsService>();

示例视图组件

这里我们有 ViewComponent 和它的脚本在同一个文件中

@model UI.FailUserFeedback
@inject Services.ViewComponentsService _viewComponentsService

@{
    var modalId = UI.Utilities.RandomId();
    var labelId = UI.Utilities.RandomId();
}

<div class="modal fade" id="@modalId" tabindex="-1" aria-labelledby="@labelId" aria-hidden="true">
    @*omitted for brevity*@
</div>

@{
    // the script is written here
    Func<dynamic, object> RenderScript =
    @<script>
            (function () {
                var modal = new bootstrap.Modal(document.getElementById('@modalId'));
                modal.show();
            })();
    </script>;
    // and registered here
    _viewComponentsService.RegisterScript(() => RenderScript(this));
}

布局

@inject Services.ViewComponentsService _viewComponentsService
...
@await RenderSectionAsync("Scripts", required: false)
@foreach(var script in _viewComponentsService.Scripts) {
    @script();
}

答案 6 :(得分:0)

如果在页面完全加载后被渲染的模态或其他元素中的控制器调用了 ViewComponent,则 defer 也将不起作用。相反,您必须将这些脚本放在父视图或 _Layout 中。 在我的情况下,它是一个 ajax 形式和

<script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"></script>
<script src="~/lib/jquery-ajax-unobtrusive/jquery.unobtrusive-ajax.js"></script>

甚至@{await Html.RenderPartialAsync("_ValidationScriptsPartial");} 将无法加载并导致正确发布表单的问题。