我应该在哪里包含视图组件的脚本?
Where should I include a script for a view component?
我试过在视图组件的视图中添加部分脚本。
@section scripts {
<script src="~/somepath" asp-append-version="true"></script>
}
我在共享布局中也有渲染部分
@RenderSection("scripts", required: false)
在项目的部分视图和其他地方使用时,脚本加载正常。但是,当在视图组件中时,脚本不会加载。
我想我可以将脚本包含在调用该组件的每个视图的部分标记中。我觉得这不符合视图组件的自包含性质。
还有其他方法吗?
据我所见,ViewComponent 中的 "@section Scripts {}"
被忽略并且不会在 ViewComponents _*layout.cshtml
的相关 @RenderSection()
中呈现
我不知道这是为什么。
我在 viewcomponents 中的 sections 标签也有问题。事实证明,据我所知,viewcomponents 不支持它。参见 https://github.com/aspnet/Home/issues/2037
Jake Shakesworth 实现了一个标签助手,如下所示:
Javascript in a View Component
另一方面,您可以将它作为
包含在视图组件中
<script defer src"...">
</script>
我的要求是从视图组件显示 google 地图。问题是脚本在 jquery、jquery.ui 之前被调用。
通过使用延迟,您告诉解析器在文档加载之前不要执行它,从而避免了必须将它放在布局中才能正确执行的问题。
chrome、safari 和 ie(10+)、ff(3.6+)、o(15+)
支持 Defer
希望对您有所帮助
这是我的代码示例:
@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>
}
请注意,如果视图组件在页面上多次出现,您可能需要编写一些逻辑来防止脚本被多次包含,而我的情况并非如此
这就是我使用 Asp.net 核心 2.0.
将脚本插入视图组件的方法
首先,我创建了一个局部视图,并将其放置在视图组件视图文件夹中。
路径:Views/Shared/Components/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 部分异步辅助方法引入了脚本。
路径:Views/Shared/Components/CalendarWidget/Default.cshtml
Default.cshtml
<section id="calendar"></section>
@await Html.PartialAsync( "Components/CalendarWidget/_CalendarScriptsPartial" )
为了完整起见,这里是我的视图组件 class。
路径: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( );
}
}
}
注意:我的示例目前不需要异步,但我打算将存储库注入 class 的构造函数,它将使用 async/await.
注意 2:完成开发后,我计划将所有内容捆绑并缩小到一个脚本中。
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>
@section scripts { } in viewcomponents 被忽略并且不被 Asp.Net 渲染引擎渲染。所以只需在视图组件的末尾使用。此外,如果您的 jquery 脚本在布局的末尾指定,那么 jquery 将在您的视图组件中不可用。当然把jquery脚本移到layout的head部分就可以解决问题,但是建议在最后加载js文件。
所以如果你想在布局的末尾保留 jquery 脚本并且仍然在 viewcomponents 中使用 jquery,你可以使用 javascript domcontentloaded 并且任何 jquery 都可以写在domcontentloaded里面。这不是一个永久的好方法,但对我有用。
<script>
document.addEventListener('DOMContentLoaded', function (event) {
console.log($ === jQuery)
});
</script>
或者如@Alberto L. Bonfiglio 所述,您也可以尝试将脚本移动到另一个 JS 文件并延迟将其加载到视图组件中:
<script src="viewComponentScript.js" defer></script>
我在范围服务中注册 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();
}
如果 ViewComponent 在页面完全加载后由模式内部的 Controller 调用或呈现另一个元素,则 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");}
将无法加载并导致正确发布表单时出现问题。
我试过在视图组件的视图中添加部分脚本。
@section scripts {
<script src="~/somepath" asp-append-version="true"></script>
}
我在共享布局中也有渲染部分
@RenderSection("scripts", required: false)
在项目的部分视图和其他地方使用时,脚本加载正常。但是,当在视图组件中时,脚本不会加载。
我想我可以将脚本包含在调用该组件的每个视图的部分标记中。我觉得这不符合视图组件的自包含性质。
还有其他方法吗?
据我所见,ViewComponent 中的 "@section Scripts {}"
被忽略并且不会在 ViewComponents _*layout.cshtml
@RenderSection()
中呈现
我不知道这是为什么。
我在 viewcomponents 中的 sections 标签也有问题。事实证明,据我所知,viewcomponents 不支持它。参见 https://github.com/aspnet/Home/issues/2037
Jake Shakesworth 实现了一个标签助手,如下所示: Javascript in a View Component
另一方面,您可以将它作为
包含在视图组件中<script defer src"...">
</script>
我的要求是从视图组件显示 google 地图。问题是脚本在 jquery、jquery.ui 之前被调用。
通过使用延迟,您告诉解析器在文档加载之前不要执行它,从而避免了必须将它放在布局中才能正确执行的问题。
chrome、safari 和 ie(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>
}
请注意,如果视图组件在页面上多次出现,您可能需要编写一些逻辑来防止脚本被多次包含,而我的情况并非如此
这就是我使用 Asp.net 核心 2.0.
将脚本插入视图组件的方法首先,我创建了一个局部视图,并将其放置在视图组件视图文件夹中。
路径:Views/Shared/Components/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 部分异步辅助方法引入了脚本。
路径:Views/Shared/Components/CalendarWidget/Default.cshtml
Default.cshtml
<section id="calendar"></section>
@await Html.PartialAsync( "Components/CalendarWidget/_CalendarScriptsPartial" )
为了完整起见,这里是我的视图组件 class。
路径: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( );
}
}
}
注意:我的示例目前不需要异步,但我打算将存储库注入 class 的构造函数,它将使用 async/await.
注意 2:完成开发后,我计划将所有内容捆绑并缩小到一个脚本中。
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>
@section scripts { } in viewcomponents 被忽略并且不被 Asp.Net 渲染引擎渲染。所以只需在视图组件的末尾使用。此外,如果您的 jquery 脚本在布局的末尾指定,那么 jquery 将在您的视图组件中不可用。当然把jquery脚本移到layout的head部分就可以解决问题,但是建议在最后加载js文件。
所以如果你想在布局的末尾保留 jquery 脚本并且仍然在 viewcomponents 中使用 jquery,你可以使用 javascript domcontentloaded 并且任何 jquery 都可以写在domcontentloaded里面。这不是一个永久的好方法,但对我有用。
<script>
document.addEventListener('DOMContentLoaded', function (event) {
console.log($ === jQuery)
});
</script>
或者如@Alberto L. Bonfiglio 所述,您也可以尝试将脚本移动到另一个 JS 文件并延迟将其加载到视图组件中:
<script src="viewComponentScript.js" defer></script>
我在范围服务中注册 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();
}
如果 ViewComponent 在页面完全加载后由模式内部的 Controller 调用或呈现另一个元素,则 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");}
将无法加载并导致正确发布表单时出现问题。