如何包含部分但仅在尚未包含的情况下?
How to include a Partial but only if it wasn't yet included?
我使用 ASP.NET MVC5
和 knockout.js
。我有几个 knockout.js
模板,组织成局部视图。当我在视图或局部视图中有一个组件需要一个或多个特定模板时,我将相应的模板包含在 Html.Partial
中。但是,我需要解决一个问题:这样,如果一个组件本身是局部的,而我在一个视图中包含两个或多个组件,模板将被包含两次或更多次,这是不可取的。
我想实现的是,每当我需要包含部分模板时,我都不必担心它们是否已经包含在内。我可以在模板中包含相同的部分两次或三次,但最后,它只会在呈现的视图中出现一次。
这个问题有任何内置或第三方解决方案吗?
据我所知,Razor/partial 视图没有解决此问题的方法。
您应该看看 Knockout Components(在版本 3.2 中引入),它旨在解决这个问题。
Knockout 组件可以以多种方式呈现模板和 viewModel。模板和视图模型仅定义一次,并根据需要多次重复使用。
如果您使用像 requireJS 这样的模块加载器(Knockout 允许使用任何加载器),它还可以按需动态加载模板和脚本。组件也可以嵌套和重复使用。这应该能满足您的要求。
我遇到了类似的问题。我就是这样解决的。我不喜欢这个解决方案,但它确实有效。如果有更好的方法我很想听听。
public static class PartialExtension
{
public static void AddPartial(this HtmlHelper html, string partialLocation)
{
//Get a name for the template. This is used to identify the template and
//to ensure that a blank location has not been sent it.
var partialName = Path.GetFileNameWithoutExtension(partialLocation);
if (partialName == null)
throw new Exception("The partial location can not be null");
//Get the extension and directory. If the location doesn't specify
//a directory, like the location is in the current directory, then
//we need to remove the extension. Not sure why, but html.Partial()
//throws an exception if you don't.
var extension = Path.GetExtension(partialLocation);
var dir = Path.GetDirectoryName(partialLocation);
if (string.IsNullOrWhiteSpace(dir) && string.IsNullOrWhiteSpace(extension) == false)
partialLocation = partialLocation.Replace(extension, "");
var tmpBag = html.ViewBag;
tmpBag.TbdTemplates = tmpBag.TbdTemplates as Dictionary<string, MvcHtmlString> ?? new Dictionary<string, MvcHtmlString>();
//Only add this template once.
if (((Dictionary<string, MvcHtmlString>)tmpBag.TbdTemplates).ContainsKey(partialName)) return;
//FYI: because html.Partial can call this recursively, we want to set the item in the dictionary
//as soon as possible. Then we call Partial(). The final call to that method will be what is
//set as the value in the dictionary.
((Dictionary<string, MvcHtmlString>)tmpBag.TbdTemplates)[partialName] = MvcHtmlString.Create("");
var tmpHtml = html.Partial(partialLocation, html.ViewData);
((Dictionary<string, MvcHtmlString>)tmpBag.TbdTemplates)[partialName] = tmpHtml;
}
public static MvcHtmlString WritePartials(this HtmlHelper html)
{
var tmpBag = html.ViewBag;
tmpBag.TbdTemplates = tmpBag.TbdTemplates as Dictionary<string, MvcHtmlString> ?? new Dictionary<string, MvcHtmlString>();
if (tmpBag.TbdTemplates == null) return MvcHtmlString.Create("");
var builder = new StringBuilder();
foreach (var value in tmpBag.TbdTemplates.Values)
{
builder.Append(value);
}
return MvcHtmlString.Create(builder.ToString());
}
}
然后在我的_Layout.cshtml。 (向底部)
<div id="Partials" style="display: none;">
@Html.WritePartials()
</div>
我使用 ASP.NET MVC5
和 knockout.js
。我有几个 knockout.js
模板,组织成局部视图。当我在视图或局部视图中有一个组件需要一个或多个特定模板时,我将相应的模板包含在 Html.Partial
中。但是,我需要解决一个问题:这样,如果一个组件本身是局部的,而我在一个视图中包含两个或多个组件,模板将被包含两次或更多次,这是不可取的。
我想实现的是,每当我需要包含部分模板时,我都不必担心它们是否已经包含在内。我可以在模板中包含相同的部分两次或三次,但最后,它只会在呈现的视图中出现一次。
这个问题有任何内置或第三方解决方案吗?
据我所知,Razor/partial 视图没有解决此问题的方法。
您应该看看 Knockout Components(在版本 3.2 中引入),它旨在解决这个问题。
Knockout 组件可以以多种方式呈现模板和 viewModel。模板和视图模型仅定义一次,并根据需要多次重复使用。
如果您使用像 requireJS 这样的模块加载器(Knockout 允许使用任何加载器),它还可以按需动态加载模板和脚本。组件也可以嵌套和重复使用。这应该能满足您的要求。
我遇到了类似的问题。我就是这样解决的。我不喜欢这个解决方案,但它确实有效。如果有更好的方法我很想听听。
public static class PartialExtension
{
public static void AddPartial(this HtmlHelper html, string partialLocation)
{
//Get a name for the template. This is used to identify the template and
//to ensure that a blank location has not been sent it.
var partialName = Path.GetFileNameWithoutExtension(partialLocation);
if (partialName == null)
throw new Exception("The partial location can not be null");
//Get the extension and directory. If the location doesn't specify
//a directory, like the location is in the current directory, then
//we need to remove the extension. Not sure why, but html.Partial()
//throws an exception if you don't.
var extension = Path.GetExtension(partialLocation);
var dir = Path.GetDirectoryName(partialLocation);
if (string.IsNullOrWhiteSpace(dir) && string.IsNullOrWhiteSpace(extension) == false)
partialLocation = partialLocation.Replace(extension, "");
var tmpBag = html.ViewBag;
tmpBag.TbdTemplates = tmpBag.TbdTemplates as Dictionary<string, MvcHtmlString> ?? new Dictionary<string, MvcHtmlString>();
//Only add this template once.
if (((Dictionary<string, MvcHtmlString>)tmpBag.TbdTemplates).ContainsKey(partialName)) return;
//FYI: because html.Partial can call this recursively, we want to set the item in the dictionary
//as soon as possible. Then we call Partial(). The final call to that method will be what is
//set as the value in the dictionary.
((Dictionary<string, MvcHtmlString>)tmpBag.TbdTemplates)[partialName] = MvcHtmlString.Create("");
var tmpHtml = html.Partial(partialLocation, html.ViewData);
((Dictionary<string, MvcHtmlString>)tmpBag.TbdTemplates)[partialName] = tmpHtml;
}
public static MvcHtmlString WritePartials(this HtmlHelper html)
{
var tmpBag = html.ViewBag;
tmpBag.TbdTemplates = tmpBag.TbdTemplates as Dictionary<string, MvcHtmlString> ?? new Dictionary<string, MvcHtmlString>();
if (tmpBag.TbdTemplates == null) return MvcHtmlString.Create("");
var builder = new StringBuilder();
foreach (var value in tmpBag.TbdTemplates.Values)
{
builder.Append(value);
}
return MvcHtmlString.Create(builder.ToString());
}
}
然后在我的_Layout.cshtml。 (向底部)
<div id="Partials" style="display: none;">
@Html.WritePartials()
</div>