如何使用 Angular 中变量的 ${text} 插值?

How to use ${text} interpolation from a variable in Angular?

这个问题是关于 Angular 中的 ts 内联 text interpolation(不是 HTML 文件的模板插值)。

我找不到关于我的问题的相关信息,所以我不确定这是否可能,如果您在无法完成我所要求的情况下提供源文档,我们将不胜感激.

目前我可以做到以下几点:

export class SomeClass {
    parseString(name: string): string {
        const baseString = `
            Hello ${name}...
        `;
        return baseString;
    }
}

// later... when `parseString` is called I get the following result:
parseString('John');                             // Hello John...
parseString('Mr. Smith');                        // Hello Mr. Smith...

我想做的是类似这样的事情:

export class SomeClass {
    parseString(name: string, baseString: string): string {
        return baseString;
    }
}
// later... when `parseString` is called I want to get the following result:
parseString('John', `Hello Mr.${name}`);         // Hello Mr.John...
parseString('Mr. Smith', `Hi ${name}`);          // Hi Mr. Smith...

我提出的语法是完全错误的,因为 baseStringname 甚至存在于它的范围内或有一个值之前被评估,所以它总是 returns 没有字符串变量值:Hello Mr.Hi .

我不关心语法,任何利用变量文本插值的方法都很棒。最终我希望能够做这样的事情:

/** 
 * The reason that I'm using `of` from `RxJS` is that 
 * I want to show that I want to be able to gather labels from
 * anywhere, let's say a REST API or a service (?)
 **/
of(`Greetings ${name}...`).subscribe(val => {
  const name = 'John';
  console.log(val);                              // Greetings John...
});

目前,为了完成所有这些,我只使用:

parseString(name: string, baseString: string): string {
    return baseString.replace(/$\{name\}/g, 'John');
}

但我想知道 text interpolation 是否缺少某个功能。

编辑:

这个问题和建议的重复问题之间的主要区别 是建议不关心反引号文本是否可能是动态的,在这里我试图能够从头开始或基于其他变量“创建”那些反引号字符串。

编辑 2:

建议的副本确实回答了我的问题 here,但仅适用于 ES6 环境。

编辑 3:

简要解释 ES5ES6 问题。我意识到建议的重复问题在运行时创建了一个 Function 对象,其语法仅在 ES6 中可用,这意味着它不适用于 ES5 环境。相反,Angular TypeScript 编译器可以在使用文本插值时创建与 ES5 兼容的代码。

如果您所做的只是连接 baseStringname,您只需执行以下操作:

parseString(name: string, baseString: string): string {
    return baseString + name;
}

或者如果它不会总是那么简单,你可以传递一个函数而不是 baseString:

// inside class
parseString(name: string, greeting: (s: string) => string): string {
    return greeting(name);
}

function makeGreeting(name: string) { 
   return `Hi ${name}, I’m Jack.`;
}

console.log(parseString("Bill", makeGreeting)); // “Hi Bill, I’m Jack.”

试试这个

/**
 * Text interpolation
 * https://www.w3schools.com/js/js_string_templates.asp
 *
 * Example:
 *   const text: string = this.helloI18nTag; // <-- "Hello ${name}, welcome"
 *   const res = StringUtil.interpolate(text, { name: 'John Connor' });
 *   console.log(res);                       // <-- "Hello John Connor, welcome"
 *
 * @param template : string to interpolate
 * @param args     : an object wiht key -> value to replace
 * @returns
 */
public static interpolate(template: string, args: { [key: string]: string }): string {
    if (typeof args !== 'object') {
      return template;
    }
    try {
      return new Function('return `' + template.replace(/$\{(.+?)\}/g, '${this.}') + '`;').call(args);
    } catch (e) {
      // ES6 syntax not supported
    }
    Object.keys(args).forEach((key) => {
      template = template.replace(new RegExp('\$\{' + key + '\}', 'g'), args[key]);
    });
    return template;
}
interpolate('Hello ${name}', {name: 'John'});

找到 Angular 插值的答案。

@ngx-translate/core 中有一个名为 TranslateDefaultParser 的包,该包已经负责根据 ES5ES6 标准生成正确的代码。这是它的用法:

import { TranslateDefaultParser } from '@ngx-translate/core';
export class SomeClass {
    ...
    public parser = new TranslateDefaultParser();
    
    parseString(name: string, baseString: string): string {
        return this.parseStringMap(baseString, {name: name});
    }

    parseStringMap(baseString: string, args: { [key: string]: string }): string {
        return this.parser.interpolate(baseString, args);
    }
    ...
}

以后可以直接使用:

this.parseString('John', 'Hello Mr.{{name}}');              // Hello Mr.John
this.parseString('Mr. Smith', 'Hi {{name}}');               // Hi Mr. Smith
this.parseString('Ms. Connor', 'Hello {{name}}, welcome.'); // Hello Ms. Connor, welcome.
this.parseString('Jack', "Hi {{name}}, I'm Bill");          // Hi Jack, I'm Bill

// A bit more complete examples:
// Input string: "Hello {{name}}, today is {{day}}, enjoy... {{something}}"

this.parseStringMap('Hello {{name}}, today is {{day}}, enjoy {{something}}', {
    name: 'John',
    day: 'Wednesday',
    something: 'your stay'
}); // <-- Outputs "Hello John, today is Wednesday, enjoy your stay"


this.parseStringMap('Hello {{name}}, today is {{day}}, enjoy {{something}}', {
    name: 'Everyone!',
    day: 'Friday!',
    something: 'your meal'
}); // <-- Outputs "Hello Everyone!, today is Friday!, enjoy your meal"
...

我不会将我自己的答案标记为正确的,因为 @ngx-translate/core 不是内部的官方 Angular 包;实际上与 相同。希望以后会有官方的实现。