前面的文章或多或少提到了React.js。React.js能带来什么好处?让我们来分析一下常用的jQuery和React之间的不同。
问题描述:
有一个项目列表,每个条目默认带有隐藏着的详细信息。当用户点击某一条就展开并显示该条目的详细信息。其他的条目则变灰。当我们再次点击同一条项目时,就收起,其他的条目恢复到初始状态:收起和黑色字体。我们也可以展开其他条目,来收起之前展开的条目。
2种解决方案:
jQuery (JSBin)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
$(function() { $('li').on('click', function(e) { var $clickedItemDetails = $(e.currentTarget).find('.details'); var $allDetails = $('li .details'); if ($clickedItemDetails.is(':hidden')) { $allDetails.hide().parent().removeClass('collapsed'); $clickedItemDetails.show(); } else { $clickedItemDetails.hide(); } $allDetails.each(function(index, el) { if ($(el).is(':hidden')) { $(el).parent().addClass('collapsed'); } }); if ($('li.collapsed').length === $('li').length) { $('li').removeClass('collapsed'); } }); }); |
我们的数据和状态包含在了DOM中,并没有结构化。数据,状态,表现之间显得比较冗杂。
我们使用jQuery选择器(像is(‘hidden’)和.find(‘.details’))。然后我们用hide(),show(),addClass()和removeClass()方法直接操作DOM来改变状态。
写完这些代码后过段时间再回来看,需要从头到尾重新阅读一遍代码才能理解。由于功能有限,我可以不用破坏原有代码来重构这个功能。但是当我们增加复杂的特征后恐怕没那么容易了。
React (JSBin)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
/** @jsx React.DOM */ var PRODUCTS = [ { "id": 1, "name": "Bag of suck", "price": 100, "details": "You don't want to own this!" }, { "id": 2, "name": "Bag of luck", "price": 200, "details": "You might want to own this!" }, { "id": 3, "name": "Bag of fuck", "price": 300, "details": "You really want to own this!" } ]; var ItemsList = React.createClass({ getInitialState: function() { return { expandedProductId: null }; }, handleProductClick: function(product) { var newSelectedProductId = product.id; if (this.state.expandedProductId === product.id) { newSelectedProductId = null; } this.setState({expandedProductId: newSelectedProductId}); }, render: function() { var self = this, noneSelected = this.state.expandedProductId === null; var products = PRODUCTS.map(function(product) { var details, isExpanded = self.state.expandedProductId === product.id; if (isExpanded) { details = <div>{product.details}</div>; } return ( <li key={product.id} onClick={self.handleProductClick.bind(self, product)} className={isExpanded || noneSelected ? '' : 'collapsed'}> {product.name} ({product.price}) {details} </li> ); }); return ( <ul> {products} </ul> ); } }); React.render(<ItemsList />, document.body); |
我的第一反应是“哇,这么多代码,用这库不够好吧”,真是这样吗?我们来分析一下:
- 数据漂亮地独立了出来,存到PRODUCTS这个数组中
- 所有状态用expandedProductId这个变量
- 所有的渲染逻辑写在了render方法中
- 我们能从头到尾阅读代码
- 快速浏览代码后容易理解代码所做的事情
结论
这个例子比较简单,但能够显示出两个库是如何帮助你把你所关注的部分分离出来,React无疑是更好的选择,它让我们把数据抽离出来,注意力集中在这些数据的处理上,至于页面的渲染,就交给React吧。
原文:jQuery versus React.js thinking