我在 TagHelper 类的 process 方法中生成脚本,如下所示
[TargetElement("MyTag")]
public Class MYClass: TagHelper{
public override void Process(TagHelperContext context, TagHelperOutput output)
{
StringBuilder builder = new StringBuilder();
builder.Append("<script>");
builder.Append("//some javascript codes here);
builder.Append("</script>");
output.Content.Append(builder.ToString());
}
}
现在,它将脚本放置在标签元素的旁边,作为其同级元素。
我需要将脚本放在正文部分的末尾。
最佳答案
我创建了一对自定义标签助手,可以解决您的问题。
第一个是<storecontent>
它只是将包裹在其中的 html 内容存储在 TempData 字典中。它不提供直接输出。内容可以是内联脚本或任何其他 html。许多这种类型的标签助手可以放置在不同的位置,例如在局部 View 中。
第二个标签助手是 <renderstoredcontent>
并将所有先前存储的内容呈现在所需的位置,例如在 body 元素的末尾。
代码 StoreContentTagHelper.cs
:
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
namespace YourProjectHere.TagHelpers
{
[TargetElement("storecontent", Attributes = KeyAttributeName)]
public class StoreContentTagHelper : TagHelper
{
private const string KeyAttributeName = "asp-key";
private const string _storageKey = "storecontent";
private const string _defaultListKey = "DefaultKey";
[HtmlAttributeNotBound]
[ViewContext]
public ViewContext ViewContext { get; set; }
[HtmlAttributeName(KeyAttributeName)]
public string Key { get; set; }
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
output.SuppressOutput();
TagHelperContent childContent = await context.GetChildContentAsync();
var storageProvider = ViewContext.TempData;
Dictionary<string, List<HtmlString>> storage;
List<HtmlString> defaultList;
if (!storageProvider.ContainsKey(_storageKey) || !(storageProvider[_storageKey] is Dictionary<string,List<HtmlString>>))
{
storage = new Dictionary<string, List<HtmlString>>();
storageProvider[_storageKey] = storage;
defaultList = new List<HtmlString>();
storage.Add(_defaultListKey, defaultList);
}
else
{
storage = ViewContext.TempData[_storageKey] as Dictionary<string, List<HtmlString>>;
if (storage.ContainsKey(_defaultListKey))
{
defaultList = storage[_defaultListKey];
}
else
{
defaultList = new List<HtmlString>();
storage.Add(_defaultListKey, defaultList);
}
}
if (String.IsNullOrEmpty(Key))
{
defaultList.Add(new HtmlString(childContent.GetContent()));
}
else
{
if(storage.ContainsKey(Key))
{
storage[Key].Add(new HtmlString(childContent.GetContent()));
}
else
{
storage.Add(Key, new List<HtmlString>() { new HtmlString(childContent.GetContent()) });
}
}
}
}
}
代码 RenderStoredContentTagHelper.cs
:
using System;
using System.Linq;
using System.Collections.Generic;
using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
namespace YourProjectHere.TagHelpers
{
[TargetElement("renderstoredcontent", Attributes = KeyAttributeName)]
public class RenderStoredContentTagHelper : TagHelper
{
private const string KeyAttributeName = "asp-key";
private const string _storageKey = "storecontent";
[HtmlAttributeNotBound]
[ViewContext]
public ViewContext ViewContext { get; set; }
[HtmlAttributeName(KeyAttributeName)]
public string Key { get; set; }
public override void Process(TagHelperContext context, TagHelperOutput output)
{
output.TagName = String.Empty;
var storageProvider = ViewContext.TempData;
Dictionary<string, List<HtmlString>> storage;
if (!storageProvider.ContainsKey(_storageKey) || !(storageProvider[_storageKey] is Dictionary<string, List<HtmlString>>))
{
return;
}
storage = storageProvider[_storageKey] as Dictionary<string, List<HtmlString>>;
string html = "";
if (String.IsNullOrEmpty(Key))
{
html = String.Join("", storage.Values.SelectMany(x => x).ToList());
}
else
{
if (!storage.ContainsKey(Key)) return;
html = String.Join("", storage[Key]);
}
TagBuilder tagBuilder = new TagBuilder("dummy");
tagBuilder.InnerHtml = html;
output.Content.SetContent(tagBuilder.InnerHtml);
}
}
}
基本用法:
在某些 View 或部分 View 中:
<storecontent asp-key="">
<script>
your inline script...
</script>
</storecontent>
在另一个位置:
<storecontent asp-key="">
<script src="..."></script>
</storecontent>
最后在应该呈现两个脚本的所需位置:
<renderstoredcontent asp-key=""></renderstoredcontent>
就是这样。
一些注意事项:
- 可以有任意数量的
<storecontent>
标签。asp-key
属性是必需的,至少为空“”。如果您为此属性指定特定值,则可以对存储的内容进行分组并在不同位置呈现特定组。例如。如果您使用asp-key="scripts"
指定一些内容以及其他一些内容asp-key="footnotes"
那么您可以使用以下方法仅将第一组渲染为某个位置:
<renderstoredcontent asp-key="scripts"></renderstoredcontent>
另一组“脚注”可以在其他位置呈现。
<storecontent>
必须在<renderstoredcontent>
之前定义被申请;被应用。在 ASP.NET 中,响应是以相反的层次顺序生成的,首先生成最里面的部分 View ,然后是父部分 View ,然后是主视图,最后是布局页面。因此,您可以轻松地使用这些标签助手在分部 View 中定义脚本,然后在布局页面中的正文部分的末尾呈现脚本。不要忘记使用命令
@addTagHelper "*, YourProjectHere"
在 _ViewImports.cshtml 文件中引用自定义标记助手。
很抱歉这篇文章很长,希望对您有所帮助!
关于asp.net-core - 如何将 TagHelper 处理方法中生成的脚本渲染到页面底部而不是标签元素旁边?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31313529/