我将ASP.NET MVC5
与knockout.js
一起使用。我有几个knockout.js
模板,或者部分视图。当我在视图或部分视图中有一个需要一个或多个特定模板的组件时,我会在Html.Partial
中包含相应的模板。但是,我需要解决一个问题:这样,如果组件本身是部分的,并且我在视图中包含两个或更多组件,模板将被包含两次或更多次,这是不可取的。 / p>
我想实现这一点,每当我需要包含部分模板时,我不必担心它们是否已被包括在内。我可以将相同的部分模板包含两到三次,但最后,它只会在渲染视图中出现一次。
这个问题是否存在任何形式的第三方解决方案?
答案 0 :(得分:1)
我有类似的问题。这就是我解决它的方式。我不喜欢这个解决方案,但它确实有效。如果有更好的方式,我会喜欢听到它。
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>
答案 1 :(得分:0)
我知道Razor /部分视图无法解决此问题。
您应该查看旨在解决此问题的Knockout Components(在3.2版中引入)。
Knockout组件可以通过各种方式呈现模板和viewModel。模板和视图模型仅定义一次,并根据需要重复使用多次。
如果您使用像requireJS这样的模块加载器(Knockout允许使用任何加载器),它还可以根据需要动态加载模板和脚本。组件也可以嵌套和重用。这应该涵盖你的要求。