Как я могу визуализировать повторяющиеся элементы React?
Я написал некоторый код для визуализации повторяющихся элементов в ReactJS, но я ненавижу, насколько это уродливо.
render: function(){
var titles = this.props.titles.map(function(title) {
return <th>{title}</th>;
});
var rows = this.props.rows.map(function(row) {
var cells = [];
for (var i in row) {
cells.push(<td>{row[i]}</td>);
}
return <tr>{cells}</tr>;
});
return (
<table className="MyClassName">
<thead>
<tr>{titles}</tr>
</thead>
<tbody>{rows}</tbody>
</table>
);
}
есть ли лучший способ добиться этого?
(Я хотел бы вставить for
циклы в коде шаблона, или какой-то подобный подход.)
5 ответов:
вы можете поместить выражения внутри скобок. Обратите внимание в скомпилированном JavaScript, почему a
for
цикл никогда не будет возможен внутри синтаксиса JSX; JSX равнозначен вызовам функций и аргументам функции sugared. Допускаются только выражения.(также: не забудьте добавить
key
атрибуты компонентов, отображаемых внутри циклов.)JSX + ES2015:
render() { return ( <table className="MyClassName"> <thead> <tr> {this.props.titles.map(title => <th key={title}>{title}</th> )} </tr> </thead> <tbody> {this.props.rows.map((row, i) => <tr key={i}> {row.map((col, j) => <td key={j}>{col}</td> )} </tr> )} </tbody> </table> ); }
JavaScript:
render: function() { return ( React.DOM.table({className: "MyClassName"}, React.DOM.thead(null, React.DOM.tr(null, this.props.titles.map(function(title) { return React.DOM.th({key: title}, title); }) ) ), React.DOM.tbody(null, this.props.rows.map(function(row, i) { return ( React.DOM.tr({key: i}, row.map(function(col, j) { return React.DOM.td({key: j}, col); }) ) ); }) ) ) ); }
чтобы расширить ответ Росса Аллена, вот немного более чистый вариант с использованием синтаксиса стрелки ES6.
{this.props.titles.map(title => <th key={title}>{title}</th> )}
он имеет то преимущество, что часть JSX изолирована (нет
return
или;
), что делает его легче поставить петлю вокруг него.
в духе функционального программирования, давайте сделаем наши компоненты немного легче работать с помощью абстракций.
// converts components into mappable functions var mappable = function(component){ return function(x, i){ return component({key: i}, x); } } // maps on 2-dimensional arrays var map2d = function(m1, m2, xss){ return xss.map(function(xs, i, arr){ return m1(xs.map(m2), i, arr); }); } var td = mappable(React.DOM.td); var tr = mappable(React.DOM.tr); var th = mappable(React.DOM.th);
теперь мы можем определить наш рендер следующим образом:
render: function(){ return ( <table> <thead>{this.props.titles.map(th)}</thead> <tbody>{map2d(tr, td, this.props.rows)}</tbody> </table> ); }
jsbin
альтернативой нашей map2d была бы функция карты Карри, но люди, как правило, уклоняются от каррирования.
мелкий (через массив
from()
:<table> { Array.from({length:3}).map(() => <tr/> } </table>
другой способ будет через массив
fill()
:<table> { Array(3).fill(<tr/>) } </table>
Вложенные Узлы:
var table = ( <table> { Array.from(Array(3)).map((tr, tr_i) => <tr> { Array.from(Array(4)).map((a, td_i, arr) => <td>{arr.length * tr_i + td_i + 1}</td> )} </tr> )} </table> ); ReactDOM.render(table, document.querySelector('main'))
td{ border:1px solid silver; padding:1em; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> <main></main>
это, ИМО, самый элегантный способ сделать это (с ES6). Создайте экземпляр пустого массива с 7 индексами и картой в одной строке:
Array.apply(null, Array(7)).map((i)=> <Somecomponent/> )
спасибо https://php.quicoto.com/create-loop-inside-react-jsx/