了解JavaScript中的模板文字的途径

2015 ECMAScript规范(ES6)向JavaScript添加了新功能-模板文字。模板文字为我们提供了一种创建字符串值的新机制...该机制具有许多强大的功能,例如简化多行构造的创建以及使用占位符将表达式结果嵌入字符串中。另外,这里还有另一种可能性-带标签的模板文字。这是模板文字的扩展形式。标记模板允许您使用字符串内部的表达式以及特殊功能来创建字符串。所有这些扩展了程序员使用字符串的能力,例如,允许创建可以是URL的动态字符串,或者编写用于微调HTML元素的函数







在本文中,您将了解用单引号或双引号指定的常规字符串值与模板文字之间的区别。您将了解声明具有不同特征的字符串的不同方法,包括根据变量或表达式的值而变化的多行字符串和动态字符串。您将学习如何使用标签模板,并查看其用法的实际示例。



声明字符串



在本节中,我们回顾如何使用单引号或双引号声明字符串,然后看看使用模板文字时如何完成相同操作。



JavaScript字符串可以看作是用单引号(' '括起来的一系列字符



const single = 'Every day is a good day when you paint.'


声明字符串的另一种方法是使用双引号(" "):



const double = "Be so very light. Be a gentle whisper."


在JavaScript中,这些字符串之间没有主要区别。在其他语言中,声明字符串时使用不同的引号可能意味着,例如,一种字符串可以插值,而其他字符串则不能。在这里,我们的意思是通过``插值''来计算占位符表达式的值,这些占位符在字符串的动态部分中起作用并参与生成的字符串值的形成。



用单引号或双引号声明时使用哪个字符串在很大程度上取决于个人喜好和编码约定。但是,如果在用这些引号之一定界的字符串中出现相同类型的引号,则必须对它们进行转义。这样的字符串中的另一种引号不需要转义。



//     ,   
const single = '"We don\'t make mistakes. We just have happy accidents." - Bob Ross'

//     ,   
const double = "\"We don't make mistakes. We just have happy accidents.\" - Bob Ross"

console.log(single);
console.log(double);


调用一对方法log()将导致两条相同的行发送控制台



"We don't make mistakes. We just have happy accidents." - Bob Ross
"We don't make mistakes. We just have happy accidents." - Bob Ross


另一方面,模板文字是使用反引号(` `声明的



const template = `Find freedom on this canvas.`


无需在此处转义单引号或双引号:



const template = `"We don't make mistakes. We just have happy accidents." - Bob Ross


但是必须避免这样的字符串中的反引号:



const template = `Template literals use the \` character.`


模板文字具有常规字符串的所有功能。因此,您可以用模板文字替换项目中的所有字符串,而不会丢失任何内容。但是,最常见的编码约定指定仅在需要模板文字的特殊功能时才使用它们。普通字符串始终使用单引号或双引号声明,以保持代码的一致性。遵循此标准编写的项目代码库,对于以前不熟悉它的开发人员将更易于阅读。



既然我们已经讨论过使用单引号,双引号和反引号声明字符串,那么我们可以继续研究模板文字的第一个优点。即-能够描述多行字符串。



多行字符串



在本节中,我们将首先讨论在ES6之前如何声明多行字符串,然后我们将研究模板文字如何简化此任务。



最初,如果您必须在文本编辑器中输入由几行组成的字符串变量,则使用字符串串联运算符。下面的字符串连接示例说明了这种想法:



const address =
  'Homer J. Simpson' +
  '742 Evergreen Terrace' +
  'Springfield'


这种方法可以使您将长行分成小块,并在文本编辑器中将它们排列成几行。但这丝毫不影响最后一行的结果。在这种情况下,字符串常量的值将位于一行上。组装字符串值的零件不会由换行或空格分隔。如果在控制台上打印一个常量address,则将在其中显示以下内容:



Homer J. Simpson742 Evergreen TerraceSpringfield


在代码编辑器中编写此类行的另一种方法是使用反斜杠字符(\),该字符位于行片段的末尾,然后在新行上找到新的片段:



const address =
  'Homer J. Simpson\
  742 Evergreen Terrace\
  Springfield'


例如,这种方法保留了行片段之前的空格,但是如果将变量的值打印到控制台,它将再次由单行表示:



Homer J. Simpson  742 Evergreen Terrace  Springfield


您可以使用换行符(\n创建真正的多行字符串



const address =
  'Homer J. Simpson\n' +
  '742 Evergreen Terrace\n' +
  'Springfield'


显示存储在控制台中的字符串值时address,该值将跨越多行:



Homer J. Simpson
742 Evergreen Terrace
Springfield


但是,使用换行符创建多行字符串并不是特别方便和容易。另一方面,使用模板文字创建多行字符串要容易得多,也更加方便。无需连接字符串,无需使用换行符或反斜杠。要使用模板文字创建多行字符串,这非常简单,在一行下一行的末尾,按键Enter,然后继续输入模板文字的下一行:



const address = `Homer J. Simpson
742 Evergreen Terrace
Springfield`


如果将此常量输出到控制台,则文本将与编辑器中的文本相同:



Homer J. Simpson
742 Evergreen Terrace
Springfield


在此应该牢记,如果反引号之间有用于对齐代码的空格,则这些空格将包含在最终模板文字中。考虑以下示例:



const address = `Homer J. Simpson
                 742 Evergreen Terrace
                 Springfield`


尽管这种编码风格使它更易于阅读,但是输出后进入控制台的内容看起来并不吸引人:



Homer J. Simpson
                 742 Evergreen Terrace
                 Springfield


现在,在处理了多行字符串之后,让我们讨论如何将对各种表达式求值的结果嵌入以不同方式声明的字符串中,即让我们讨论表达式插值。



表达式插值



以前,在ES6之前,使用串联来创建由变量或表达式值形成的动态字符串:



const method = 'concatenation'
const dynamicString = 'This string is using ' + method + '.'


如果输出dynamicString到控制台,则会得到以下信息:



This string is using concatenation.


使用模板文字时,可以使用占位符将表达式嵌入字符串中。占位符是视图构造${}在这种情况下,花括号中包含的所有内容均被视为JavaScript代码,而此构造之外的所有内容均被视为字符串:



const method = 'interpolation'
const dynamicString = `This string is using ${method}.`


输出dynamicString到控制台时,将得到以下结果:



This string is using interpolation.


在字符串中嵌入值的一个常见示例是创建动态URL。为此目的使用串联导致了笨重且不便的构造。例如,这是一个生成OAuth访问字符串函数



function createOAuthString(host, clientId, scope) {
  return host + '/login/oauth/authorize?client_id=' + clientId + '&scope=' + scope
}

createOAuthString('https://github.com', 'abc123', 'repo,user')


如果将此功能的结果打印到控制台,则会得到以下信息:



https://github.com/login/oauth/authorize?client_id=abc123&scope=repo,user


使用插值时,程序员不再需要注意界定字符串部分的引号以及连接运算符的确切位置。这是使用模板文字重写的相同示例:



function createOAuthString(host, clientId, scope) {
  return `${host}/login/oauth/authorize?client_id=${clientId}&scope=${scope}`
}

createOAuthString('https://github.com', 'abc123', 'repo,user')


该函数的结果如下:



https://github.com/login/oauth/authorize?client_id=abc123&scope=repo,user


您可以使用trim()方法从使用模板文字创建的字符串中删除开头和结尾的空格例如,在下面的代码片段中创建一个HTML元素具有自定义引用,则使用箭头功能



const menuItem = (url, link) =>
  `
<li>
  <a href="${url}">${link}</a>
</li>
`.trim()

menuItem('https://google.com', 'Google')


最后一行将删除开头和结尾的空格,以确保正确呈现项目:



<li>
  <a href="https://google.com">Google</a>
</li>


整个表达式可以插值,而不仅仅是变量。例如-像这里,两个数字相加的结果嵌入在字符串中:



const sum = (x, y) => x + y
const x = 5
const y = 100
const string = `The sum of ${x} and ${y} is ${sum(x, y)}.`

console.log(string)


在此声明函数sum()和常量xy之后,该行同时使用函数和这些常量。这是常量string打印到控制台后的样子



The sum of 5 and 100 is 105.


当使用三元运算符时该机制特别有用,它允许您在形成字符串时检查条件:



const age = 19
const message = `You can ${age < 21 ? 'not' : ''} view this page`
console.log(message)


message打印到控制台 的常数可以更改,具体取决于存储在中的值是大于还是小于21 age由于在我们的示例中此值为19,因此以下内容将发送到控制台:



You can not view this page


现在您知道了使用模板文字时如何从表达式插值中受益。在下一节中,我们将进一步研究标记模式,并讨论使用在与占位符匹配的范围中传递的表达式。



标签模板



标记模板是模板文字的扩展形式。带标签的模板以带标签的函数开始,该函数解析模板文字,使开发人员可以更好地控制动态字符串生成过程。



在下面的示例中,我们创建了一个tag计划用作在标签模板上执行操作的功能的功能。此函数的第一个命名参数strings是字符串文字的数组。内联表达式使用其余参数语法放置在第二个参数中为了查看这些参数的内容,可以将它们显示在控制台中:



function tag(strings, ...expressions) {
  console.log(strings)
  console.log(expressions)
}


如果在创建标签模板时使用函数tag,则可以得到以下构造:



const string = tag`This is a string with ${true} and ${false} and ${100} interpolated inside.`


由于该函数将tag输出输出到控制台strings,因此expressions,在执行此代码时,会将以下内容发送到控制台:



["This is a string with ", " and ", " and ", " interpolated inside."]
[true, false, 100]


您可以看到第一个参数strings是包含所有字符串文字的数组:



"This is a string with "
" and "
" and "
" interpolated inside."


此参数还具有一个raw可以称为的属性strings.raw它包含未处理任何转义序列的行。例如,它将\n只是一个字符\n,而不是换行命令。



第二个参数...expressions是包含所有表达式的数组:



true
false
100


结果是将tag字符串文字和表达式传递到标记模板函数请注意,该函数不需要返回字符串。它可以使用传递给它的值并返回任何东西。例如,我们可能有一个函数,它什么都不关注,只返回nullreturnsNull在下面的示例中就是这样编写函数的



function returnsNull(strings, ...expressions) {
  return null
}

const string = returnsNull`Does this work?`
console.log(string)


执行此代码后,控制台中将显示以下内容:



null


作为您可以在带标签的模板中执行的操作的示例,可以对每个表达式进行更改,例如更改以在HTML标签中包含表达式。让我们创建一个功能bold,增加了标签<strong></strong>开始和每个表达式的结尾:



function bold(strings, ...expressions) {
  let finalString = ''

  //    
  expressions.forEach((value, i) => {
    finalString += `${strings[i]}<strong>${value}</strong>`
  })

  //    
  finalString += strings[strings.length - 1]

  return finalString
}

const string = bold`This is a string with ${true} and ${false} and ${100} interpolated inside.`

console.log(string)


在这里,expressions一个forEach循环用于遍历array 每个元素都包含在标签中<strong></strong>



This is a string with <strong>true</strong> and <strong>false</strong> and <strong>100</strong> interpolated inside.


在流行的JavaScript库中,您可以找到一些使用标记模板的示例。例如,graphql-tag使用模板文字gql来解析GraphQL查询字符串并将其转换为GraphQL可以理解的抽象语法树(AST):



import gql from 'graphql-tag'

//        5
const query = gql`
  {
    user(id: 5) {
      firstName
      lastName
    }
  }
`


带标签的模板功能还用于styled-components库中,该允许您从常规DOM元素创建新的React组件并将其他CSS样式应用于它们



import styled from 'styled-components'

const Button = styled.button`
  color: magenta;
`

// <Button>     


另外,您可以通过将标准String.raw方法应用于加标签的模板来使用它,以防止转义序列的处理:



const rawString = String.raw`I want to write /n without it being escaped.`
console.log(rawString)


执行此代码后,控制台中将显示以下内容:



I want to write /n without it being escaped.


结果



在本文中,我们记住了有关用单引号或双引号引起来的普通字符串文字的基本信息,并且还讨论了模板文字和标记模板。模板文字简化了许多字符串处理任务。特别是,我们正在谈论在字符串中嵌入不同的值以及在不使用串联或转义的情况下创建多行字符串。标记是一种有用的高级模板文字功能,已在许多流行的库中使用。



您是否使用模板文字?






All Articles