【问题标题】:Rendering comma separated list of links呈现逗号分隔的链接列表
【发布时间】:2014-05-12 20:57:48
【问题描述】:

我正在尝试输出逗号分隔的链接列表,这是我的解决方案。

var Item = React.createComponent({
  render: function() {

    var tags = [],
        tag;

    for (var i = 0, l = item.tags.length; i < l; i++) {
      if (i === item.tags.length - 1) {
        tag = <span><Tag key={i} tag={item.tags[i]} /></span>;
      } else {
        tag = <span><Tag key={i} tag={item.tags[i]} /><span>, </span></span>;
      }
      tags.push(tag);
    }

    return (
      <tr>
        <td>
          {item.name}
        </td>
        <td>
          {tags}
        </td>
      </tr>
    );

  }
});

我只是想知道是否有更好、更干净的方法来完成此任务?

谢谢

【问题讨论】:

    标签: reactjs react-jsx


    【解决方案1】:

    简单

    {tags.map((tag, i) => <span key={i}>
        {i > 0 && ", "}
        <Tag tag={tag} />
    </span>)}
    


    在 React 16 中,它可以做得更简单:

    {tags.map((tag, i) => [
        i > 0 && ", ",
        <Tag key={i} tag={tag} />
    ])}
    

    【讨论】:

    • 甜蜜又简单!
    • @imos 你介意解释一下吗? {!!i &amp;&amp; ", "}
    • @Macxim 此行在除第一个标记之外的每个标记之前打印逗号。表达式!!i 只是将i 转换为布尔值。 !!i 也可以替换为 i &gt; 0
    • @imos 非常感谢。
    • 我见过的每字符价值最好的答案之一。我应该建议将其迁移到 Code Golf 吗? =)
    【解决方案2】:

    在可汗学院,我们为此使用了一个名为 intersperse 的助手:

    /* intersperse: Return an array with the separator interspersed between
     * each element of the input array.
     *
     * > _([1,2,3]).intersperse(0)
     * [1,0,2,0,3]
     */
    function intersperse(arr, sep) {
        if (arr.length === 0) {
            return [];
        }
    
        return arr.slice(1).reduce(function(xs, x, i) {
            return xs.concat([sep, x]);
        }, [arr[0]]);
    }
    

    它允许您编写如下代码:

    var tags = item.tags.map(function(tag, i) {
        return <Tag key={i} tag={item.tags[i]} />;
    };
    tags = intersperse(tags, ", ");
    

    【讨论】:

    • 知道如何将元素(如&lt;span/&gt;)作为第二个参数传递吗?它确实有效,但我收到关于未指定密钥的警告...我尝试将 &lt;span&gt; 包装在一个函数中(并生成一个随机密钥),但这似乎不太正确或无法正常工作。
    • 我刚刚意识到这是我可以做到的;传递一个函数作为接受和 idx 的分隔符,然后使用数组 reducer 的索引作为键。
    • 类似this gist
    【解决方案3】:

    或者简单地将列表项写入无序列表并使用 CSS。

    var Item = React.createComponent({
      render: function() {
    
        var tags = this.props.item.tags.map(function(i, item) {
          return <li><Tag key={i} tag={item} /></li>
        });
    
        return (
          <tr>
            <td>
              {this.props.item.name}
            </td>
            <td>
              <ul className="list--tags">
                {tags}
              </ul>
            </td>
          </tr>
        );
    
      }
    });
    

    还有 CSS:

    .list--tags {
        padding-left: 0;
        text-transform: capitalize;
    }
    
    .list--tags > li {
        display: inline;
    }
    
    .list--tags > li:before {
        content:',\0000a0'; /* Non-breaking space */
    }
    .list--tags > li:first-child:before {
        content: normal;
    }
    

    【讨论】:

    • 这样真的不明确
    • 我喜欢这种方法。我刚刚使用了.csv 类并使其适用于任何元素:.csv&gt;*,而不仅仅是ui&gt;li,这是完全可以理解的
    • 我喜欢这种方法,因为它是语义化的,据我所知,它更适合可访问性。
    【解决方案4】:
    import React from 'react';
    import { compact } from 'lodash';
    
    // Whatever you want to separate your items with commas, space, border...
    const Separator = () =>  { ... }; 
    
    // Helpful component to wrap items that should be separated
    const WithSeparators = ({ children, ...props }) => {
    
      // _.compact will remove falsey values: useful when doing conditional rendering
      const array = compact(React.Children.toArray(children));
    
      return array.map((childrenItem, i) => (
        <React.Fragment key={`${i}`}>
          {i > 0 && <Separator {...props} />}
          {childrenItem}
        </React.Fragment>
      ));
    };
    
    const MyPage = () => (
      <WithSeparators/>
        <div>First</div>
        {second && (<div>Maybe second</div>)}
        {third && (<div>Maybe third</div>)}
        <div>Fourth</div>
      </WithSeparators>
    );
    

    【讨论】:

      【解决方案5】:

      一个可以解决问题的函数组件。受到@imos 回复的启发。适用于 React 16。

      const Separate = ({ items, render, separator = ', ' }) =>
        items.map((item, index) =>
          [index > 0 && separator, render(item)]
        )
      
      <Separate
        items={['Foo', 'Bar']}
        render={item => <Tag tag={item} />}
      />
      

      【讨论】:

        【解决方案6】:

        这是一个允许&lt;span&gt;s 和&lt;br&gt;s 和垃圾作为分隔符的解决方案:

        const createFragment = require('react-addons-create-fragment');
        
        function joinElements(arr,sep=<br/>) {
            let frag = {};
            for(let i=0,add=false;;++i) {
                if(add) {
                    frag[`sep-${i}`] = sep;
                }
                if(i >= arr.length) {
                    break;
                }
                if(add = !!arr[i]) {
                    frag[`el-${i}`] = arr[i];
                }
            }
            return createFragment(frag);
        }
        

        它也会过滤掉虚假的数组元素。我用它来格式化地址,其中一些地址字段没有填写。

        它使用片段来避免丢失键的警告。

        【讨论】:

          【解决方案7】:

          简单一:

          {items.map((item, index) => (
              <span key={item.id}>
                {item.id}
                {index < items.length - 1 && ', '}
              </span>
           ))}
          

          【讨论】:

            【解决方案8】:

            要添加到上面的精彩答案,Ramda 有intersperse

            用逗号分隔你可以做的一堆项目:

            const makeLinks = (x: Result[]) =>
              intersperse(<>,</>, map(makeLink, x))
            

            相当简洁

            【讨论】:

              【解决方案9】:

              无需额外标签的解决方案

              <p className="conceps inline list">
                {lesson.concepts.flatMap((concept, i) =>
                  [concept, <span key={i} className="separator">&#8226;</span>]
                , ).slice(-1)}
              </p>
              

              产生类似的东西

              函数•函数类型•高阶函数•偏应用

              【讨论】:

                【解决方案10】:

                最简单的方法

                const elementsArr = ["a", "b", "c"];
                let elementsToRender = [] ;
                elementsArr.forEach((element, index) => {
                    let elementComponent = <TAG className="abc" key={element.id}>{element}</TAG>
                    elementsToRender.push(elementComponent);
                    if(index !== (elementsArr.length - 1)){
                        elementsToRender.push(", ");
                    }
                });
                
                render(){
                    return (
                        <div>{elementsToRender}</div>
                    )
                }
                

                【讨论】:

                  猜你喜欢
                  • 2012-03-03
                  • 2020-04-21
                  • 1970-01-01
                  • 2013-07-03
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多