【问题标题】:Preserving Razor syntax highlighting in Knockout.js templates在 Knockout.js 模板中保留 Razor 语法突出显示
【发布时间】:2012-06-27 01:16:15
【问题描述】:

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

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

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

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

【问题讨论】:

    标签: javascript asp.net-mvc visual-studio razor knockout.js


    【解决方案1】:

    我不使用 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 here)。当然,您仍然需要display:none 样式。

    <div style="display:none" data-bind="allowBindings:false">
        <div id="mytemplate">
            <div>template content</div>
        </div>
    </div>
    

    【讨论】:

    • 谢谢,我不知道渲染 Knockout 模板的其他选项。 +1 以获得出色的答案。我正在开发一个 HtmlHelper 解决方案,它结合了第二种方法,并且具有简洁性和灵活性的优点,可以根据需要更换以后使用的模板语法。
    【解决方案2】:

    我已经创建了一个 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 的想法,模板本身的标记将被浏览器解释为模板实例,所以我现在坚持使用脚本块方法,但在如果我愿意,至少我可以稍后在一个地方更改所有实例。

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

        【解决方案4】:

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

        【讨论】:

          【解决方案5】:

          使用 Razors 局部视图来解决这个问题。

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

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2014-09-13
            • 1970-01-01
            • 2012-11-13
            • 2011-02-04
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多