1

我的 Web 应用程序是带有 Razor 和 Knockout.js 的 ASP.NET MVC4。视图模型层次结构变得相当深和复杂,我更倾向于为相应的视图使用嵌套的 Knockout 模板(每个视图都有一个 for/each 用于其子模板等),而不是单一的 HTML 板。

让我烦恼的是,当使用内容的 Knockout 模板定义语法时,<script type="text/html" id="scary-template">它会在 Visual Studio 中失去其 Razor 语法突出显示,因为它被解释为脚本。模板足够复杂,没有文本也都是纯黑色的。

我考虑过的一些方法是使用 Html.Raw 来输出开始和结束脚本标签,或者像 Html.BeginKOTemplate(id) 这样的 HtmlHelper 扩展。

我很想听听其他 ASP.NET MVC 人员如何处理这个问题。我是不是很迂腐?无论如何,下一个需要选择此解决方案的开发人员可能会感谢我的关心。

4

5 回答 5

5

我不使用 Visual Studio,但我有一些对你有用的建议。

从 Knockout 2.1 开始,您可以使用textarea标签定义模板,这将支持许多编辑器中的语法高亮(包括我使用的两个,phpDesigner 和 Notepad++)。为了确保textarea它实际上没有显示在页面上,它必须具有display:none样式(或位于具有该样式的容器中)。

<textarea id="mytemplate" style="display:none">
    <div>template content</div>
</textarea>

或者

<div style="display:none">
    <textarea id="mytemplate">
        <div>template content</div>
    </textarea>
</div>

您还可以使用任何标签,例如div定义模板。但这增加了一些开销。首先,模板内容将被浏览器解析(并且可能修改)。其次,除非您另有指示,否则它将由 Knockout 解析。您可以通过将容器节点传递给applyBindings不包含模板节点的容器节点,或者通过创建绕过模板绑定的自定义绑定来做到这一点(参见allowBindings 此处)。当然,你仍然需要这种display:none风格。

<div style="display:none" data-bind="allowBindings:false">
    <div id="mytemplate">
        <div>template content</div>
    </div>
</div>
于 2012-06-27T01:56:46.050 回答
1

我已经创建了一个 HtmlHelper 扩展,它返回一个实现 IDisposable 的 KnockoutTemplate 类:

public static KnockoutTemplate KnockoutTemplate(this HtmlHelper htmlHelper, string templateID)
    {
        return new KnockoutTemplate(templateID, htmlHelper.ViewContext.Writer);
    }

public class KnockoutTemplate: IDisposable
{
    private TextWriter _textWriter;
    private bool _disposed;

    public KnockoutTemplate(string templateID, TextWriter textWriter)
    {
        _textWriter = textWriter;

        _textWriter.WriteLine(String.Format("<script type=\"text/html\" id=\"{0}\">", templateID));
    }

    public void EndTemplate()
    {
        Dispose(true);
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (!_disposed)
        {
            _disposed = true;
            _textWriter.WriteLine("</script>");
        }
    }
}

像这样使用:

@using (Html.KnockoutTemplate("sum-assured-template"))
{
<div>Template markup...</div>
}

进一步考虑,我不喜欢使用 div 的想法,模板本身的标记将被浏览器解释为模板实例,所以我现在坚持使用脚本块方法,但至少我可以如果我愿意,可以稍后在一个地方更改所有实例。

于 2012-06-27T03:20:53.820 回答
1

就个人而言,我使用淘汰赛外部模板引擎从其他文件动态加载模板。这有其自身的优点和缺点,但一个很好的副作用是模板可以存储在 .html 文件中并且根本不需要包装 - 保留所有语法突出显示。外部模板引擎不仅使用脚本标签的 id,还将在您告诉它的模板名称(例如 mytemplate.html)的任何目录中查找文件。

根据我的经验,这也倾向于使项目更有条理,并有助于促进项目之间的代码重用。唯一的缺点是下载更多文件会增加延迟 - 这实际上可以通过延迟加载来提高性能,因为它只会在需要时加载模板(并且不会对同一个模板发出多个请求)

于 2012-06-27T13:12:44.577 回答
0

只是一个快速的建议,像我在这里描述的那样分开 JavaScript 和 Razor:https ://stackoverflow.com/a/11109799/538387

于 2012-06-27T03:24:50.323 回答
0

使用 Razors 局部视图来克服这个问题。

<script type="text/html" id="launchTemplate">
   @Html.Partial("Templates/_LaunchView", null)
</script>

上述语法允许您将模板保存在单独的文件中。在该文件中,您将获得完整的 razor 语法突出显示(更不用说重新格式化)

于 2012-09-21T00:00:36.273 回答