如何将Underscore模板转换为Handlebars模板? [英] How to translate an Underscore template to a Handlebars template?

查看:48
本文介绍了如何将Underscore模板转换为Handlebars模板?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在升级使用旧主题的Shopify商店.

在(旧的)购物车页面中的代码是运费估算器"的代码(由于效果很好),他们希望在新主题中重复使用该代码.我已经复制了相关文件,但是在执行并按下计算"按钮后,将显示以下内容:

class =成功";<%} else {%>class =错误"<%}%>><%,如果(成功){%><%if(rates.length> 1){%>有<%= rates.length%><%=地址%>可用的运费,始于<%=利率[0].价格%>.<%}否则,如果(rates.length == 1){%>....

这来自以下代码:

 < script id ="shipping-calculator-response-template"type ="text/template">< p id =运费率反馈";<%,如果(成功){%>class =成功"<%} else {%>class =错误"<%}%>><%,如果(成功){%><%if(rates.length> 1){%>有<%= rates.length%><%=地址%>可用的运费,始于<%= rates [0] .price%>.<%}否则,如果(rates.length == 1){%>...</script> 

因此,我猜该脚本未被识别/视为文本/模板"

新主题包括对以下内容的引用:

 < script src ="//cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.10/handlebars.min.js"</script> 

旧主题:

 <脚本src ="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.6.0/underscore-min.js"type ="text/javascript"></script> 

所以我注释掉了把手,并替换为下划线.但是结果还是一样.

我是在正确的轨道上吗,还是以上无关紧要?

我需要从Underscore解密的完整代码-并重新编码HandleBars如下:

 < script id ="shipping-calculator-response-template"type ="text/template">< p id =运费率反馈";<%,如果(成功){%>class =成功"<%} else {%>class =错误"<%}%>><%,如果(成功){%><%if(rates.length> 1){%>有<%-rates.length%><%-address%>可用的运费,始于<%= rates [0] .price%>.<%}否则,如果(rates.length == 1){%><%-address%>有一种运费.<%} else {%>我们不运送到这个目的地.<%}%><%} else {%><%-errorFeedback%><%}%></p>< ul id =运费".<%for(var i = 0; i< rates.length; i ++)< li><%-rates [i] .name%>以<%= rates [i] .price%</li;<%}%></ul></script> 

如果我们可以解决这个问题,那么很多Shopify商家都会非常高兴;)

解决方案

通常,下划线 <代码><脚本src =" https://cdn.jsdelivr.net/npm/underscore@1.12.0/underscore-min.js"<;/script>< script src =" https://cdn.jsdelivr.net/npm/handlebars@4.7.7/dist/handlebars.js"</script>

或将它们都导入为模块,

 从下划线"导入_;从"handlebars"导入*作为Handlebars; 

或对较旧的模块格式(例如AMD或CommonJS)执行相同操作.

但是,Underscore确实具有 template 函数,最小的模板实现,可以替代Handlebars之类的库.在旧版本的应用程序中似乎是这种情况,并且由于Underscore的最小模板语言与Handlebars的模板语言不同而引起冲突.这些库之间的编译和渲染步骤也有所不同.

比较模板语言

两种模板语言都允许您在一段文本中插入特殊标签,以使该文本的各个部分成为参数化,有条件的或重复的.但是他们支持的标签是不同的.

下划线:

  • <%=表达式%> 将在文本中插入JavaScript expression 的字符串值.这称为插值标签.
  • <%-表达式%> 将执行相同的操作,但会转义HTML.
  • <%代码%> 使您可以编写任意JavaScript code ,以使模板的某些部分有条件或重复.通常,您会发现其中一个这样的标记类似于(...){%> 的<%,然后在模板的下方,有一个匹配的<%}%> .然后,这两个代码标签之间的模板部分就是一个循环,该循环将按照 for 的逻辑进行重复.同样,您可能会发现<%if(...){%> ...<%}%> 来使 ... 部分成为有条件的模板.(老实说,这很丑陋,但是它可以最小化实现.下划线的模板模块仅为一页.)
  • <%code%> code 部分中,您有时可能会找到 print(expression).这是一种简写方式,旨在避免不得不突破代码标签,使用 expression 插入插值标签,然后立即使用新的代码标签恢复的情况.换句话说,<%code1打印(表达式)code2%> <%code1%><%=表达式%><%code2%的简写.> .

车把:

  • {{name}} 在模板中插入带有键 name 的属性的HTML转义字符串值.
  • {{{{name}}} 相同,但是没有 HTML转义.
  • {{#if condition}} ... {{/if}} 仅在 condition 时插入 ... 部分被满足.
  • {{#each name}} ... {{/each}} 将对 name

的每个元素或属性重复 ... 代码>. name 成为 ... context ;也就是说,如果您在 ... 中编写 {{otherName}} ,Handlebars将尝试查找 otherName 作为所标识对象的属性通过 name .

  • {{#name}} ... {{/name}} 是Handlebars继承自
  • 我现在将不再涉及更多标签.
  • 将下划线模板转换为车把

    由于Underscore允许在模板中插入任意JavaScript代码,因此并非总是可能将Underscore模板转换为等效的Handlebars模板.但是,幸运的是,模板实际上并不需要JavaScript的全部表达能力,因此Underscore模板可能以 移植到限制性更强的模板语言的方式编写("lucky by事故").在可能的情况下,以下策略在大多数情况下就足够了:

    1. 将出现在任何<%...%> 标记内的所有 print(_.escape(expression))替换为%><%-表达式%><%.
    2. %><%= expression%>替换<%...%> print(expression)的任何其他出现;<%.
    3. {{expression}} 替换所有出现的 <%-expression%> (包括在步骤1之前已经存在的所有内容).
    4. {{{{expression}}} 替换所有出现的<%=表达式%> (包括步骤2之前已经存在的所有内容)./li>
    5. 如果您在任何地方(<.> 括号内的除外,都找到格式为 var name = otherName.propertyName 的别名)>语句),在此变量在范围内的任何位置用 otherName.propertyName 替换 name ,并删除该变量.请勿使用 for(...)中的循环变量执行此操作;这些将在第7步中替换.
    6. 如果找到任何形式为<%if(condition1){%> ...<%} else的模式,则if(condition2){%> ...<%} else... if(conditionN){%> ...<%} else {%> ...<%}%> ,从最后一个最里面的块开始,然后从在那里,如下所示:
      • {{else}} 替换最终的<%} else {%> (车把将其识别为特殊符号).
      • {{else}} {{#ifconditionN}} ... {{/if}}<%}%> .重复此步骤,直到不再有 else if .请注意,最后的<%}%> 保持不变;您要在其前面为每个中间 else if 插入一个附加的 {{/if}} .
      • 将最外面的<%if(condition1){%> ...<%}%> 替换为 {{#if condition1}} ...... {{/if}} .这次,最后的<%}%> 消失了.
    7. 替换循环,再次从最里面的表达式开始,然后从那里向外进行操作:
      • <%_.each(objectName,function(valueName,keyName,collectionName){%> ...<%})的形式替换功能遍历对象%> ,用符号 {{#each objectName}} ... {{/each}} 表示.检查嵌套的 {{}} / {{{}}} / {{#if}} / {{#each}} 中的} 标记,用于显示 keyName collectionName objectName 的任何外观,并替换它们通过分别由 @key .. .(不是错字; collectionName objectName 都应替换为 .. ,因为它们引用的是同一对象).请注意,在Underscore版本中传递给 _.each 的函数可能会使用较少的参数,在这种情况下,可能会缺少 collectionName 甚至 keyName .无论如何,替换都一样.
      • <%_.each(arrayName,function(valueName,indexName,collectionName){%> ...<%})的形式替换函数遍历数组%> ,用符号 {{#each arrayName}} ... {{/each}} 表示.检查嵌套的 {{}} / {{{}}} / {{#if}} / {{#each}} 中的} 标记,用于显示 indexName collectionName arrayName 的任何外观,并替换它们分别通过 @index .. .. .同样,在Underscore版本中传递给 _.each 的函数可以使用更少的参数.无论如何,替换都一样.
      • <%for(objectName中的var keyName){%> ...<%}%> 形式的<%替换程序循环对象 {{#eachobjectName}} ... {{/each}} 表示法.检查嵌套的 {{}} / {{{}}} / {{#if}} / {{#each}} 中的} 标记,用于显示 keyName objectName [keyName] objectName 并分别用 @key this .. 替换.
      • <%的形式替换遍历数组的循环,其中(var indexName = 0; indexName< arrayName.length; ++ indexName){%> ...<;%}%> ,用符号 {{#eacharrayName}} ... {{/each}} 表示.检查嵌套的 {{}} / {{{}}} / {{#if}} / {{#each}} 标签中的 ... 标签,用于显示 indexName arrayName [indexName] arrayName 的任何外观并分别用 @index this .. 替换.
    8. 修复表达式语法:
      • 如果在上一步中创建的格式为 ... propertyName ,则前两个句点 .. 最初是一个名称( objectName arrayName (如第7步所述),将其替换为 ../propertyName .您可能具有这种形式的较长路径,例如 ../../propertyName .
      • 格式为 name [index1] [index2] 的子表达式应转换为 name.[index].[index2] (注意句点).
    9. 检查您翻译的所有表达式 condition 是否都可以通过车把按原样进行评估.根据经验,Handlebars只能直接评估(嵌套)当前上下文的属性名称(例如 keyName keyName.subProperty )以及它可以识别的一些特殊符号例如 @key @index @root this .. .使用 helpers 来计算除某些名称之外的表达式 @root .. 所必需的对象和锚名称:
      • 请注意, this.propertyName 等效于 propertyName ,因为 this 指的是当前上下文.
      • 当将类似 {a:foo,b:{c:baz}} 的对象传递给模板时,始终可以使用 @ root.a引用此最外层对象的属性. @ root.bc 等.请注意,在原始的Underscore模板中可能已为该对象指定了自己的名称.在这种情况下,此名称本身可以替换为 @root .
      • .. 用于在循环内引用父上下文,如我们在步骤7-8中所看到的.有时,原始Underscore模板中的循环可以通过关闭父上下文直接引用其属性.在这种情况下,可以根据需要在此属性的名称前加上 ../前缀,从而帮助车把找到合适的属性.
    10. 在之前的转换之后,您可能剩下了空的<%%> 标记;这些可以安全地删除.

    如果在执行上述步骤之后,模板中仍带有<%code%> 表示法,或者Handlebars无法评估的表达式,则可能需要使用Handlebars语言中的其他功能或创建特殊的解决方法.如果您很不幸,则模板根本无法翻译,但是大多数时候都会有一种方法.

    演示:您的模板

    在这里从您的问题中重复下划线模板:

     < p id ="shipping-rates-feedback"<%,如果(成功){%>class =成功"<%} else {%>class =错误"<%}%>><%,如果(成功){%><%if(rates.length> 1){%>有<%-rates.length%><%-address%>可用的运费,始于<%= rates [0] .price%>.<%}否则,如果(rates.length == 1){%><%-address%>有一种运费.<%} else {%>我们不运送到这个目的地.<%}%><%} else {%><%-errorFeedback%><%}%></p>< ul id =运费".<%for(var i = 0; i< rates.length; i ++)< li><%-rates [i] .name%>以<%= Rates [i] .price%</li;<%}%></ul> 

    遵循上述算法,并使用表达式 rates.[1] 代替 rates.length>1 (因为Handlebars无法立即进行比较评估),我们成功获得了以下Handlebars模板:

     < p id ="shipping-rates-feedback"{{#if success}} class =成功";{{else}} class ="error"(错误){{/if}}>{{#if成功}}{{#if利率.[1]}}{{addresss}}有{{rates.length}}运费,起始价格为{{{rates.[0] .price}}}.{{else}} {{#if rates}}{{address}}有一种运费.{{别的}}我们不运送到这个目的地.{{/如果如果}}{{别的}}{{errorFeedback}}{{/如果}}</p>< ul id =运费".{{#每个费率}}< li> {{name}}的价格为{{{price}}}</li>{{/每个}}</ul> 

    您可能还会找到其他需要翻译的模板.对于其他模板,您可以采用相同的方法.

    最后的注意:嵌入HTML的模板

    您的主题在页面中包含带有以下符号的模板.

     < script id ="shipping-calculator-response-template"type ="text/template">//模板</script> 

    重要的是要认识到,尽管这是一个< script> 标记,但浏览器实际上并未将内容解释为脚本.相反,由于标签具有浏览器不知道的 type ,因此浏览器只是将标签留在DOM中,然后继续解释下一个元素.这是在HTML页面中嵌入任意文本数据的常见技巧,因此以后可以由脚本拾取它,而无需用户查看.在这种情况下,您的JavaScript会在某处执行类似的操作

      var templateText = document.querySelector('#shipping-calculator-response-template').textContent; 

    ,然后将 templateText 传递给Handlebars进行处理.这也是为什么用Underscore替换回车把并不能解决您的问题的原因.该脚本仍将尝试将模板传递给Handlebars.最后,在您的特定情况下,可能无需放下底线参考.

    I'm upgrading a Shopify store that's using an old theme.

    In the (old) Cart page is code for a 'Shipping Estimator' which (because it works well) they want to re-use in the new theme. I've copied across the relevant files but on execution and pressing the Calculate button, we get the following displayed:

    class="success" <% } else { %> class="error" <% } %>> <% if (success) { %> <% if (rates.length > 1) { %> There are <%= rates.length %> shipping rates available for <%= address %>, starting at <%= rates[0].price %>. <% } else if (rates.length == 1) { %> ....

    This comes from the following code:

    <script id="shipping-calculator-response-template" type="text/template">
      <p id="shipping-rates-feedback" <% if (success) { %> class="success" <% } else { %> class="error" <% } %>>
      <% if (success) { %>
        <% if (rates.length > 1) { %> 
        There are <%= rates.length %> shipping rates available for <%= address %>, starting at <%= rates[0].price %>.
        <% } else if (rates.length == 1) { %>
        ... 
    </script>
    

    So, I guess the script is not being recognise/treated as 'text/template'

    The new theme includes a reference to:

    <script src="//cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.10/handlebars.min.js"></script>
    

    And the old theme:

    <script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.6.0/underscore-min.js" type="text/javascript"></script>
    

    So I commented out handlebar, and replaced with underscore. But still the same result.

    Am I on the right track, or is the above irrelevant?

    The full code that I need to decipher from Underscore - and re-code for HandleBars is as follows:

    <script id="shipping-calculator-response-template" type="text/template">
      <p id="shipping-rates-feedback" <% if (success) { %> class="success" <% } else { %> class="error" <% } %>>
      <% if (success) { %>
        <% if (rates.length > 1) { %> 
        There are <%- rates.length %> shipping rates available for <%- address %>, starting at <%= rates[0].price %>.
        <% } else if (rates.length == 1) { %>
        There is one shipping rate available for <%- address %>.
        <% } else { %>
        We do not ship to this destination.
        <% } %>
      <% } else { %>
        <%- errorFeedback %>
      <% } %>
      </p>
      <ul id="shipping-rates">
        <% for (var i=0; i<rates.length; i++) { %>
        <li><%- rates[i].name %> at <%= rates[i].price %></li>
        <% } %>
      </ul> 
    </script>
    

    If we can get this to work, there are a lot of shopify merchants that will be very happy ;)

    解决方案

    Normally, Underscore and Handlebars are not really alternatives to each other. Underscore is a toolkit with general functional utilities, which helps you write shorter, more maintainable code in functional style. Handlebars, on the other hand, is a library entirely dedicated to template rendering, which helps you write cleaner, more maintainable templates.

    When using Underscore, you may find its functions being called everywhere throughout your JavaScript code, while Handlebars is only called in places where you'll be rendering a template. For this reason, these libraries normally don't conflict at all; it is perfectly possible to write an application that depends on both (in fact I've been doing this for a while in most of my applications). Just link both libraries into your page,

    <script src="https://cdn.jsdelivr.net/npm/underscore@1.12.0/underscore-min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/handlebars@4.7.7/dist/handlebars.js"></script>
    

    or import both as modules,

    import _ from 'underscore';
    import * as Handlebars from 'handlebars';
    

    or do the same with an older module format such as AMD or CommonJS.

    However, Underscore does have a template function, which is a very minimal templating implementation that can be used as an alternative to a library like Handlebars. This appears to be the case in the old version of your application, and it is causing conflicts because Underscore's minimal templating language is different from Handlebars's templating language. The compilation and rendering steps are also a bit different between these libraries.

    Comparing the template languages

    Both template languages let you insert special tags in a piece of text in order to make parts of that text parametric, conditional or repetitive. The tags that they support are however different.

    Underscore:

    • <%= expression %> will insert the string value of the JavaScript expression in the text. This is called an interpolation tag.
    • <%- expression %> will do the same, but HTML-escaped.
    • <% code %> lets you write arbitrary JavaScript code that will make parts of the template conditional or repetitive. Often, you'll find that one such tag goes something like <% for (...) { %> and then a bit further down the template, there is a matching <% } %>. The part of the template between those two code tags is then a loop that will repeat by the logic of the for. Similarly, you may find <% if (...) { %>...<% } %> to make the ... part of the template conditional. (Honestly, this is quite ugly, but it helps the implementation to be minimal. Underscore's template module is only one page.)
    • Inside the code part of <% code %> you may occasionally find print(expression). This is a shorthand meant to avoid having to break out of the code tag, insert an interpolation tag with expression and then immediately resume with a new code tag. In other words, <% code1 print(expression) code2 %> is a shorthand for <% code1 %><%= expression %><% code2 %>.

    Handlebars:

    • {{name}} inserts the HTML-escaped string value of the property with key name in the template.
    • {{{name}}} does the same, but without HTML-escaping.
    • {{#if condition}}...{{/if}} will insert the ... part only if condition is met.
    • {{#each name}}...{{/each}} will repeat ... for each element or property of name. name becomes the context of the ...; that is, if you write {{otherName}} within ..., Handlebars will try to find otherName as a property of the object identified by name.
    • {{#name}}...{{/name}} is a notation that Handlebars inherits from Mustache. It behaves similar to {{#each name}} when name is an array and similar to {{#if name}} otherwise (also changing the context to name if it is an object). The idea behind this (in Mustache) is to make the template even more declarative, or "logic-free" as the authors call it.
    • There are more tags that I won't go into now.

    Translating Underscore templates to Handlebars

    Since Underscore allows the insertion of arbitrary JavaScript code in a template, it is not always possible to translate an Underscore template to an equivalent Handlebars template. Fortunately, however, templates don't really need the full expressive power of JavaScript, so Underscore templates are likely to be written in a way that can be ported to a more restrictive template language ("lucky by accident"). When it is possible, the following strategy will be sufficient most of the time:

    1. Replace any occurrences of print(_.escape(expression)) that appear inside any <%...%> tag by %><%- expression %><%.
    2. Replace any other occurrences of print(expression) inside <%...%> by %><%= expression %><%.
    3. Replace all occurrences of <%- expression %> (including ones that were already there before step 1) by {{expression}}.
    4. Replace all occurrences of <%= expression %> (including ones that were already there before step 2) by {{{expression}}}.
    5. If you find aliases of the form var name = otherName.propertyName anywhere (except within the parentheses of a for (...) statement), substitute otherName.propertyName for name everwhere this variable is in scope and drop the variable. Don't do this with loop variables inside for (...); those are replaced in step 7.
    6. If you find any pattern of the form <% if (condition1) { %>...<% } else if (condition2) { %>...<% } else ... if (conditionN) { %>...<% } else { %>...<% } %>, start with the last, innermost block and work your way outwards from there, as follows:
      • Replace the final <% } else { %> by {{else}} (Handlebars recognizes this as a special notiation).
      • Replace the final intermediate <% } else if (conditionN) { %>...<% } %> by {{else}}{{#if conditionN }}...{{/if}}<% } %>. Repeat this step until there is no more else if. Note that the final <% } %> stays in place; you're inserting one additional {{/if}} in front of it for every intermediate else if.
      • Replace the outermost <% if (condition1) { %>...<% } %> by {{#if condition1}}...{{/if}}. This time, the final <% } %> disappears.
    7. Replace loops, again starting with the innermost expressions and working your way outwards from there:
      • Replace functional loops over objects of the form <% _.each(objectName, function(valueName, keyName, collectionName) { %>...<% }) %> by the notation {{#each objectName}}...{{/each}}. Check nested {{}}/{{{}}}/{{#if}}/{{#each}} tags within ... for any appearances of keyName, collectionName or objectName and replace them by by @key, .. and .. respectively (that is not a typo; collectionName and objectName should both be replaced by .. because they refer to the same object). Note that the function passed to _.each in the Underscore version may take fewer arguments, in which case collectionName and even keyName may be absent; the replacement works the same regardless.
      • Replace functional loops over arrays of the form <% _.each(arrayName, function(valueName, indexName, collectionName) { %>...<% }) %> by the notation {{#each arrayName}}...{{/each}}. Check nested {{}}/{{{}}}/{{#if}}/{{#each}} tags within ... for any appearances of indexName, collectionName or arrayName and replace them by by @index, .. and .. respectively. Again, the function passed to _.each in the Underscore version may take fewer arguments; the replacement works the same regardless.
      • Replace procedural loops over objects of the form <% for (var keyName in objectName) { %>...<% } %> by the notation {{#each objectName}}...{{/each}}. Check nested {{}}/{{{}}}/{{#if}}/{{#each}} tags within ... for any appearances of keyName, objectName[keyName] or objectName and replace them by by @key, this and .. respectively.
      • Replace procedural loops over arrays of the form <% for (var indexName = 0; indexName < arrayName.length; ++indexName) { %>...<% } %> by the notation {{#each arrayName}}...{{/each}}. Check nested {{}}/{{{}}}/{{#if}}/{{#each}} tags within ... for any appearances of indexName, arrayName[indexName] or arrayName and replace them by by @index, this and .. respectively.
    8. Fix expression syntax:
      • If you have created expressions of the form ...propertyName in the previous step, where the first two periods .. were originally a name (objectName or arrayName as described under step 7), replace this by ../propertyName. You may have longer paths of this form, for example ../../propertyName.
      • Subexpressions of the form name[index1][index2] should be turned into name.[index].[index2] (note the periods).
    9. Check whether all expressions and conditions that you translated can be evaluated as-is by Handlebars. As a rule of thumb, Handlebars can only directly evaluate (nested) property names of the current context (for example keyName or keyName.subProperty) and some special notations that it recognizes such as @key, @index, @root, this and ... Use helpers to evaluate expressions that are more than just the name of some object and anchor names as necessary to @root or ..:
      • Note that this.propertyName is equivalent to just propertyName, because this refers to the current context.
      • When passing an object like {a: foo, b: {c: baz}} to the template, the properties of this outermost object can always be referenced with @root.a, @root.b.c, etcetera. Note that this object may have been given a name of its own inside the original Underscore template; in that case, this name itself can be replaced by @root.
      • .. is for referencing the parent context inside loops, as we have seen in steps 7-8. Occasionally, a loop in the original Underscore template may reference a property of a parent context directly by closing over it; in such cases, you can help Handlebars find the right property by prefixing the name of this property with ../ as necessary.
    10. You may have leftover empty <% %> tags after the previous transformations; these can be safely removed.

    If, after the above steps, you still have <% code %> notation in your template, or expressions that Handlebars cannot evaluate, you may need to use other facilities from the Handlebars language or create special workarounds. If you are very unlucky, the template cannot be translated at all, but most of the time there will be a way.

    Demonstration: your template

    Repeating the Underscore template from your question here:

    <p id="shipping-rates-feedback" <% if (success) { %> class="success" <% } else { %> class="error" <% } %>>
    <% if (success) { %>
      <% if (rates.length > 1) { %>
      There are <%- rates.length %> shipping rates available for <%- address %>, starting at <%= rates[0].price %>.
      <% } else if (rates.length == 1) { %>
      There is one shipping rate available for <%- address %>.
      <% } else { %>
      We do not ship to this destination.
      <% } %>
    <% } else { %>
      <%- errorFeedback %>
    <% } %>
    </p>
    <ul id="shipping-rates">
      <% for (var i=0; i<rates.length; i++) { %>
      <li><%- rates[i].name %> at <%= rates[i].price %></li>
      <% } %>
    </ul>
    

    Following the above algorithm and using the expression rates.[1] instead of rates.length > 1 (because Handlebars cannot evaluate comparisons out of the box), we successfully obtain the following Handlebars template:

    <p id="shipping-rates-feedback" {{#if success}} class="success" {{else}} class="error" {{/if}}>
    {{#if success}}
      {{#if rates.[1]}}
      There are {{rates.length}} shipping rates available for {{address}}, starting at {{{rates.[0].price}}}.
      {{else}}{{#if rates}}
      There is one shipping rate available for {{address}}.
      {{else}}
      We do not ship to this destination.
      {{/if}}{{/if}}
    {{else}}
      {{errorFeedback}}
    {{/if}}
    </p>
    <ul id="shipping-rates">
      {{#each rates}}
      <li>{{name}} at {{{price}}}</li>
      {{/each}}
    </ul>
    

    You might find other templates that need to be translated as well. You can follow the same approach for those other templates.

    Final note: templates embedded in HTML

    Your theme includes the template in the page with the following notation.

    <script id="shipping-calculator-response-template" type="text/template">
        // the template
    </script>
    

    It is important to realize that, although this is a <script> tag, the browser does not actually interpret the contents as a script. Instead, because the tag has a type that the browser doesn't know, the browser just leaves the tag as-is in the DOM and moves on to interpret the next element. This is a common trick to embed arbitrary text data in an HTML page, so that it can be picked up by a script later without the user having to see it. In this particular case, there will be a piece of your JavaScript somewhere that will do something like

    var templateText = document.querySelector('#shipping-calculator-response-template').textContent;
    

    and then pass templateText to Handlebars in order to process it. This is also the reason why replacing Handlebars back by Underscore didn't solve your problem; that script will still try to pass the template to Handlebars. Concluding, in your particular case, there is probably no need to put back the Underscore reference.

    这篇关于如何将Underscore模板转换为Handlebars模板?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆