如何在模板字面量(``)中使用模板字面量?

7

我有一个非常特殊的边缘情况,需要在模板字面量内部使用另一个模板字面量,但无法完成。

代码大致如下:

<p>Something something <a href={`${SOMELINK}/blah`}>SomeLink</a></p>

然而,我必须将其包装在一个函数中,同时保持SOMELINK变量的值,这会导致错误发生,不管我是否转义引号。
someFunction (`<p>Something something <a href={`${SOMELINK}/blah`}>SomeLink</a></p>`)

使用了转义的单引号后,我得到了以下错误信息:

错误: 期望 SOMELINK 但没有提供

没有转义时,我得到了:

意外的标记,期望“,”

我该如何处理这个问题?

编辑:需要注意的是,在传递给 someFunction 的代码将被渲染并且需要使用。它最终将通过 dangerouslySetInnetHTML 传递到另一个标签中。因此,它看起来应该类似于:

<div dangerouslySetInnerHTML={{__html: someFunction(`<p>Something something <a href={`${SOMELINK}/blah`}>SomeLink</a></p>`)}}/>

不确定这是否相关,但是someFunction只是对文本进行一些修改。


这是因为模板字面量是 JavaScript 的一个特性,而不是 HTML5... 你应该阅读以下链接:https://wesbos.com/template-strings-html/,以及为了保险起见,https://css-tricks.com/html-templates-via-javascript-template-literals/。 - manAbl
这看起来像是JSX语法。你不能把它放在模板字面量中。 - Bergi
@ManuelBlanco 这个问题被标记为 reactjs,所以更可能是JSX而不是HTML5。你应该阅读:https://reactjs.org/docs/jsx-in-depth.html - Derek 朕會功夫
糟糕!我沒有意識到標籤錯了,我的錯誤 @Derek朕會功夫 - manAbl
5个回答

4

我认为你过于复杂化了。如果你只需要维护SOMELINK的值,那么这个应该可以工作:

someFunction(`<p>Something something <a href="${SOMELINK}/blah">SomeLink</a></p>`)

那个将被渲染出来。如果我这样做,它会把我发送到错误的链接。而不是去SOMELINK指向的地方,它会跳转到:http://www.myoriginalpage.com/%7B%22http://www.somelinkpage.com/blah%22%7D。而不是http://www.somelinkpage.com/blah - theJuls
似乎这是您的函数存在问题,而且该函数在您的问题中没有描述。 - imjared
我以前觉得这不相关,但现在仔细一想,它确实很重要。那个传递给函数的字面值将被传递给另一个标签,并且我使用dangerouslySetInnerHTML来呈现内容。我会更新原贴以包含更详细的信息。 - theJuls
更新:我不知道我在第一次回复你的答案时做了什么不同。但我尝试了第二次,它完美地运行了。可能是我的无能。谢谢! - theJuls

2

介绍

正如imjared在他的答案中所说,你正在复杂化JavaScript模板的概念。但我想通过解释模板的语法来使其更加清晰。

模板包含最多四个不同的部分,你可以在模板内编写一个模板,就像我将要展示的那样,但不完全是你提到的方式。

高级字符串

首先,模板只是一种使用内部表达式编写字符串的高级方式。如果你输入:

typeof `this template`                                      (1)

在您的浏览器控制台中,它将输出 "string"。
在旧时代,当您想要连接许多字符串时,您最终会写下以下代码:
"string1" + "string2" + ... + "stringN"                     (2)

有些参数可能是数字,这些数字通常会自动转换为字符串(在大多数情况下,它会按预期工作)。但是,如果您想计算一个表达式,您通常需要将该表达式写在括号之间:

"string1" + (a + b * c) + "string2"                         (3)

现代JavaScript有模板

模板使用${...}特殊语法替换原有的写法。在${...}中,您可以编写表达式。这意味着(3)可以使用模板语法重写如下:

`string1${a + b * c}string2`                                (4)

语法的优点在于看起来可以像这样在模板中插入变量:
`string1${varname}string2`                                  (5)

这仍然是一个表达式,只是它被限制在varname中。

因此,在模板中有四个可能的不同部分:

  1. One String

    If your template is just one string (i.e. no ${...}) then it is just like a string.

    `this is just like a string`                            (6)
    
  2. Two Parts

    If you have one expression within a template, then you have a HEAD and a TAIL in your template. (4) and (5) above are templates with a HEAD and a TAIL.

  3. Three Parts

    If you write a template with more than one expression, that adds one or more special parts in between the expressions. These are called MIDDLE templates.

    `head${expr1}middle${expr2}middle${expr3}tail`          (7)
    

模板内的模板

就像我上面提到的,你可以实际上在一个模板中写另一个模板。大多数情况下,你不需要这样做,但是这是可能的,因为出现在${}之间的内容被视为表达式,而模板则被视为主要文字(或多或少,实际上有一点更复杂...)

`string1${v
  + `sub-template${ sub_sub_template_is_possible }tail`
  + w}string2`                                             (8)

如(8)中的子模板示例所述,您可以在子模板中再嵌套另一个子子模板。我认为在大多数情况下,您不太可能需要这样做,因为根模板已经为您提供了所有必要的功能。

转义字符

与字符串一样,模板也支持使用反斜杠来转义各种字符:

  • \<octal>

  • \x<hexadecimal>

  • \u<hexadecimal>

  • Some special characters such as the character n which represents the newline (\n)

  • Finally, the other characters are escaped as is, this would include:

    \`                                                      (9)
    

    to escape the template quotes, in which case they are viewed as the quote character, not a template starting or ending point. In other words, string (10) is equal to string (11):

    `\``                                                   (10)
    "`"                                                    (11)
    

非常简化的语法

以下是上述部分使用简化的 BNF 类似语法:

TemplateLiteral ::= Template
              | TemplateHead TemplateExpression* TemplateTail

TemplateExpression ::= Expression
              | TemplateExpression TemplateMiddle Expression

Template ::= '`' Character* '`'

TemplateHead ::= '`' Character* '${'

TemplateMiddle ::= '}' Character* '${'

TemplateTail ::= '}' Character* '`'

Character ::= ... -- characters valid in strings,
                     except '${' and '`'                 (12)

参考文献

JavaScript语言的描述可以在此页面找到ECMA-262文档:

https://www.ecma-international.org/publications-and-standards/standards/ecma-262/

搜索 模板文字词法组件。 您将找到我上面提到的四个部分(以及更多内容):TemplateTemplateHeadTemplateMiddleTemplateTail


2
你可以这样做:

你可以像这样:

someFunction(`<p>Something something <a href={${SOMELINK}/blah>SomeLink</a></p>`);

1
尝试这个。
someFunction("<p>Something something <a href={"+`${SOMELINK}/blah`+"}>SomeLink</a></p>")

我认为您还需要将路由设置为相对路径。
"<p>Something something <a href={/"+`${SOMELINK}/blah`+"}>SomeLink</a></p>"

0
我认为在那种情况下,SOMELINK变量是不可用的。 你应该先提供SOMELINK。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接