【问题标题】:Javascript Replace - Dynamic Value of ReplacementJavascript 替换 - 替换的动态值
【发布时间】:2019-08-14 15:35:43
【问题描述】:

我在字符串中有一个模板,我想用另一个字符串中的值替换一些占位符。对于我替换的每个占位符,我还想插入一个中断标记。

例如,如果在模板中找到#ADDRESS2#,我将使用以下代码将其所有出现替换为字符串val.address2 中的值。

    template_html = template_html.replace(/#ADDRESS2#/g, '<br />'+ val.address_2);

但是,在某些情况下,字符串 val.address2 为空。在这种情况下,我不想插入中断标签。

所以我改变了我的代码如下

    if( val.address_2.length > 0 ) {
        template_html = template_html.replace(/#ADDRESS2#/g, '<br />'+ val.address_2);
    } else {
        template_html = template_html.replace(/#ADDRESS2#/g, '');
    }

是否有更好的方法来编写上述代码,因为我有多个占位符,并且对于每个占位符,我必须编写 2 次代码。

【问题讨论】:

  • 因为 jQuery (主要)是一个 DOM 操作库,所以在这里并不重要。我已经删除了那个标签。
  • 为什么不在文本和对象中使用相同的模板字符串。它可以更容易地替换为相同的字符串。
  • 您能否展示更多您拥有的“多个占位符”?例如。它们是否都非常规则,它们与用于替换的属性名称有什么关系?
  • @nina 是的,我可以将模板更改为与字符串同名。
  • @peter 其他 vplaceholders 像 City、State、zip。如果有帮助,我可以使占位符名称与对象相同

标签: javascript


【解决方案1】:

使用正则表达式替换,向其传递函数。

该函数将获取替换键作为输入,并且根据是否有可用替换,它将插入一个空字符串,或者使用换行符进行替换:

const template = "#foo# this bla bla #bar# but #baz# and stuff";

const replacements = {
  foo: "test",
  bar: "",
  baz: "not empty"
};

const result = template.replace(/#([^#]+)#/g, (match, key) => {
  // If there's a replacement for the key, return that replacement with a `<br />`. Otherwise, return a empty string.
  return replacements[key] !== undefined
    ? "<br />" + replacements[key]
    : "";
});

console.log("template:", template);
console.log("result:", result);

这里唯一的“陷阱”是模板字符串中的键必须与替换对象中的键匹配。不过,这并不一定是件坏事,因为如果您稍后再回顾您的代码,它会更加直观。

正则表达式可能看起来很吓人,但实际上非常简单:

/#([^#]+)#/g

  • /:正则表达式的开始,
  • #:字面意思是# 字符,
  • (:捕获组的开始,
  • [^#]+ 任何不是# 的字符。 + 确保它尽可能匹配,
  • ):捕获组结束,
  • #:字面意思是# 字符,
  • /g:正则表达式的结尾。 g 是全局标志,因此它不会在第一个结果处停止。

捕获组基本上告诉正则表达式对括号之间的所有内容进行分组。然后分别返回这些组。

【讨论】:

  • 感谢这工作。也感谢您解释使用的正则表达式
  • 我很高兴能提供帮助。感谢“接受”投票:-)
  • @Cerbrus 你可以捕获一个组.replace(/#([^#]+)#/g, (match, key) =&gt; { 以避免使用第二个正则表达式删除#
  • @barbsan:好多了!感谢您的提示:D
【解决方案2】:

也许你是这个意思?

var val = {
  "address_1": "Address 1",
  "address_2": "",
  "address_10": "Address 10",
}  
var template_html = `My address is #ADDRESS1# delivery address is #ADDRESS2# and billing is #ADDRESS10#`
template_html = template_html.replace(/#ADDRESS(\d+)#/g, function(addr, num) { 
  var str = val["address_"+num]; return str?str+"<br/>":""
})
console.log(template_html)

【讨论】:

    【解决方案3】:

    如果应该对多个地址字段应用相同的逻辑,那么您可能会受益于辅助函数:

    template_html = template_html
        .replace(/#CITY1#/g, PrefixBrIfNotEmpty(val.city_1))
        .replace(/#CITY2#/g, PrefixBrIfNotEmpty(val.city_2))
        .replace(/#CITY3#/g, PrefixBrIfNotEmpty(val.city_3))
        .replace(/#ADDRESS1#/g, PrefixBrIfNotEmpty(val.address_1))
        .replace(/#ADDRESS2#/g, PrefixBrIfNotEmpty(val.address_2))
        .replace(/#ADDRESS3#/g, PrefixBrIfNotEmpty(val.address_3));
    
    function PrefixBrIfNotEmpty(str) {
        return str ? '<br />' + str : '';
    }
    

    【讨论】:

      【解决方案4】:

      您可以使用三元运算符(空字符串计算结果为假)

      template_html = template_html.replace(/#ADDRESS2#/g, val.address_2 ? '<br />'+ val.address_2 : '');
      

      【讨论】:

      • 仍然需要为 OP 想要替换的每个替换密钥编程此替换。
      • 是的,但它仍然比if else块短
      • 不过,多个占位符是 OP 问题的一部分。
      【解决方案5】:

      最简单的改变是像这样使用三元运算符:

      template_html = template_html.replace(/#ADDRESS2#/g, ( val.address_2.length > 0 ) ? '<br />'+ val.address_2 : '');
      

      仍然不是特别优雅,但比原版短了一点。

      【讨论】:

      • 仍然需要为 OP 想要替换的每个替换密钥编程此替换。
      【解决方案6】:

      你可以用支票取值。

      template_html = template_html.replace(
          /#ADDRESS2#/g,
          val.address_2 && '<br />' + val.address_2
      );
      

      对于多个占位符,您可以采用动态方法并使用相同的模式进行搜索和替换。

      var val = { address_2: 'foo', country_1: 'bar' }
          template_html = 'Address: #ADDRESS2#\nCountry: #COUNTRY1#\nnothing: #NOTHING#'
      
      template_html = template_html.replace(
          /#([^#]+)#/g,
          (_, group) => {
              var key = group.match(/^(\D+)(\d*)$/).slice(1).map(s => s.toLowerCase()).join('_');
      
              return (val[key] || '') && '<br />' + val[key];
           }
      );
      console.log(template_html);

      为了获得更智能的替换,您可以采用与 tempate 相同的字符串的想法,并从对象中获取数据。在这种情况下,取替换值并将其作为对象的键,或者为未知值取一个空字符串。

      var val = { ADDRESS2: 'foo', COUNTRY1: 'bar' }
          template_html = 'Address: #ADDRESS2#\nCountry: #COUNTRY1#\nnothing: #NOTHING#'
      
      template_html = template_html.replace(
          /#([^#]+)#/g,
          (_, key) => (val[key] || '') && '<br />' + val[key]
      );
      console.log(template_html);

      【讨论】:

      • 好吧,我之前已经说过了,但是你有办法让代码工作,但很难理解。也许这就是为什么有些人不赞成这个答案。
      【解决方案7】:

      你的意思是这样的:

      template_html = template_html.replace(/#ADDRESS(\d+)#/g, function(address, number) {
          return val.hasOwnProperty('address_' + number)
              ? '<br />' + val['address_' + number]
              : '';
      };
      

      您应该使用val.hasOwnProperty,以防val.['address_' + number] 包含类似0false''undefinedNaN 或其他虚假值的值。
      它确保无论如何都会显示该值,因为undefined 与根本没有该属性不同。

      它还避免从原型中获取值,以防万一。

      这是基于mplungjan's 的回答。


      如果这是不希望的,并且您只想显示字符串,请尝试以下操作:

      template_html = template_html.replace(/#ADDRESS(\d+)#/g, function(address, number) {
          return val.hasOwnProperty('address_' + number)
          && val['address_' + number].length
          && (
              (typeof val['address_' + number]) === 'string'
              || val['address_' + number] instanceof String
          )
              ? '<br />' + val['address_' + number]
              : '';
      };
      

      所有这些检查确保它是一个非空字符串(或String 实例,因为new String() 返回一个字符串对象)。
      检查它是否是String 的实例可以防止由于typeof new String() 返回object 而导致的问题。

      数组和类数组对象具有length 属性(例如:jQuery 实例、NodeList、{length: 1}[0] 和类似的),但您不想将它们显示为字符串。

      【讨论】:

      • 为什么val 对象会包含数组呢?
      • @Cerbrus 为什么不呢?它只是一个对象。 OP 没有指定它没有数组,或者保证它只有字符串或根本没有值。据我所知,您可以使用var val = {address2: [] },因为它是 JavaScript 基础知识的一部分。由于没有太多关于 val 的说明,所以多加注意没有错。
      • 这似乎有点过分,就像typeof instanceOf 的组合检查一样。一个让另一个变得多余。
      • 并非如此。正如我所解释的,new String() 返回一个字符串对象,它在每个方面都像一个字符串文字,除了使用typeof 检查类型时,它返回object 而不是预期的string。此外,执行 '' instanceof String 会返回 false。但是,是的,这有点过分了。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-08-13
      • 2018-01-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-24
      • 1970-01-01
      相关资源
      最近更新 更多