【问题标题】:Use lodash in Angular Directive to combine items from array into html string在 Angular 指令中使用 lodash 将数组中的项目组合成 html 字符串
【发布时间】:2016-02-04 02:49:42
【问题描述】:

我正在使用一个有趣的 API,该 API 在它自己的对象中返回资源的每个元素。我将来自 ng-repeat 的数据传递到一个指令中,然后我需要返回完整的 HTML 字符串。对 lodash 来说是全新的,并且在弄清楚这一点时遇到了一些麻烦。段类型有很多可能性,我最终需要有案例。 View API Docs

  • 链接
  • 提及
  • 标签
  • 标记开始
  • 标记结束

NG 指令

angular.module('Community.directives.feedBody', [])
  .directive('feedBody', function feedBodyDirective() {
    return {
      restrict: 'E',
      link: convertSegments
    };

    function convertSegments($scope, elem, attrs) {
      var content = attrs.content;
    }

  }
);

JSON

[
    {
        "htmlTag": "p",
        "markupType": "Paragraph",
        "text": "",
        "type": "MarkupBegin"
    },
    {
        "text": "This is a ",
        "type": "Text"
    },
    {
        "htmlTag": "b",
        "markupType": "Bold",
        "text": "",
        "type": "MarkupBegin"
    },
    {
        "text": "post",
        "type": "Text"
    },
    {
        "htmlTag": "b",
        "markupType": "Bold",
        "text": "",
        "type": "MarkupEnd"
    },
    {
        "text": " from the standard ",
        "type": "Text"
    },
    {
        "htmlTag": "i",
        "markupType": "Italic",
        "text": "",
        "type": "MarkupBegin"
    },
    {
        "text": "chatter",
        "type": "Text"
    },
    {
        "htmlTag": "i",
        "markupType": "Italic",
        "text": "",
        "type": "MarkupEnd"
    },
    {
        "text": " UI with some HTML tags",
        "type": "Text"
    },
    {
        "htmlTag": "p",
        "markupType": "Paragraph",
        "text": "\n",
        "type": "MarkupEnd"
    }
]

UI 路由模板

<feed-body content="{{comment.body.messageSegments}}"></feed-body>

应该返回

<p><b>post</b> from the standard <i>chatter</i> ui with some HTML tags</p>

【问题讨论】:

    标签: javascript angularjs loops lodash


    【解决方案1】:

    您不一定需要 lodash 来构建 html 字符串。您可以只使用 for 循环并完成相同的操作:

    编辑:我创建了一个plunker that demonstrates the behavior I think you're going for。假设您将 json 数据作为 ` 传递,您可以在从控制器派生内容值的指令中设置一个隔离范围(请注意,我删除了花括号...):

    <feed-body content="comment.body.messageSegments"></feed-body>
    

    在你的控制器中:

      var json = [
           ...
      ];
    
      $scope.comment = {
          body: {
              messageSegments: json
          }
      };
    

    在你的指令中:

    return {
          restrict: 'E',
          scope: {
            content: '='
          },
          link: convertSegments
      };
    
      function convertSegments(scope, elem, attrs) {
          var content = scope.content;
    
          function concatenateJson(jsonData) {
              var html = []
              for (var i = 0; i < jsonData.length; i++) {
                   if (jsonData[i].type === 'MarkupBegin') {
                      html.push('<' + jsonData[i].htmlTag + '>');
                  } else if (jsonData[i].type === 'MarkupEnd') {
                      html.push('</' + jsonData[i].htmlTag + '>');
                  } else if (jsonData[i].type === 'Text') {
                      html.push(jsonData[i].text);
                  }
              }
              return html.join('');
          }
    
          var elemHtml = concatenateJson(content);
    
          elem.html(elemHtml);
      }
    
      // FYI: running the lodash method 100,000 times took 719 and 552 msecs, respectively
      // running the native for loop instead 100,000 times took 528 and 565 msecs
      // not a large sample size, obv, but not a huge difference between the two one way or the other
    
      // Using the lodash _.each method would just look like:
      // function concatenateJson(jsonData) {
      //     var html = [];
      //     _.each(jsonData, function(datum) {
      //         if (datum.type === 'MarkupBegin') {
      //             html.push('<' + datum.htmlTag + '>');
      //         } else if (datum.type === 'MarkupEnd') {
      //             html.push('</' + datum.htmlTag + '>');
      //         } else if (datum.type === 'Text') {
      //             html.push(datum.text);
      //         }
      //     });
      //     return html.join('');
      // }
    

    【讨论】:

    • 对这个很新,这会同样有效吗?强烈建议我使用 lodash
    • 我真的怀疑你是否会注意到性能上的任何显着差异,但比我更有经验的人可能想插话。我读过这没什么优势(有时轻微的缺点)放弃原生 JS for 循环以支持库函数。标准的 for 循环可能会比原生 .forEach 方法执行得更好,但除非您正在处理大量数据,否则性能差异可能可以忽略不计。尽管如此,我将使用标准 for 循环更新答案。
    • 我还添加了函数的 lodash 版本,出于好奇,我在 100,000 次迭代的循环中运行了每个版本两次。性能上的差异很小,如果有的话,for 循环似乎要快一些。但小样本量和您的浏览器可能会有所不同......
    • 您没有显示您的控制器,但是如果您传递给 html 指令的 comment.body.messageSegments 是在控制器范围内设置的 json 数组,那么您可以将指令设置为具有 scope.content从控制器继承,从内容属性值中删除花括号,在指令的链接函数中抓取它,就像您已经使用var content = scope.content; 一样,然后设置var html = concatenateJson(content);,最后插入带有elem.html(html); @987654322 的html @
    • 是的,在我发布最后一条评论后一分钟,它终于开始工作了。这非常有帮助,两个选项之间的比较非常好。谢谢!
    猜你喜欢
    • 2021-10-17
    • 1970-01-01
    • 1970-01-01
    • 2018-08-14
    • 2016-06-07
    • 2015-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多