为什么越来越多的互联网公司都在转向React.js去开发前端组件,除了性能因素外,很大一部分原因是因为用jQuery去写很复杂的DOM操作,后期代码会变得越来越难维护。现在大部分的 Web APP 都有一个特点:后端的Model层很简单,但是随着产品业务的拓展前端View却变得越来越复杂,这个时候如果还在用纯jQuery去写DOM操作将会变得很不直观,代码也会变的很臃肿进而变的越来越难以维护,下面就拿一个微博发送框的简单例子来展示一些React的简洁与强大。
注意:
React并不适合所有项目,需要结合实际情况综合考虑
jQuery与React并不是一个层面上的东西,jQuery只是一个工具库,这里只是展示两种编程模式的思维差异
理解一个技术的思想比学会怎么用它更重要,同时我们还需要知道不同的技术间的区别的核心在哪,这样我们才能学会用合适的技术去解决合适的问题
这里的tweet box只是一个简化版的UI模型,仅用来说明jQuery和React的思维差异,并不具备发Twitter的功能
你也可以写出简洁的jQuery代码。但是你必须想出良好的代码结构,每次想要增加新功能的时候还需要特别注意是否影响代码的重构,使用React会帮助你团队内部拥有更好的代码结构,页面性能也会得到相应的提高
需要实现的效果
tweet box为空时,tweet button显示为灰色不可点击状态
tweet box下方显示还可以输入的字符数量
点击add photo,剩余字符数量及add photo按钮状态发生改变(假定图片占用23个字符)
先来看看React版本:
React.js的提供了一整套Virtual DOM,所有的操作都在这个Virtual DOM上,只有当事件发生的时候,state
才发生改变,之后,React自动调用render()
来更新UI
下面是我托管在jsBin上的Demo:
React版本演示代码
React代码处理问题的思路:
创建一个状态变量用来追踪textarea中的字符的数量
在textarea的onChange事件发生时改变其状态
使用render()重新渲染tweet box,显示还可以输入的字符的数量
var TweetBox = React.createClass({
getInitialState: function() {
return {
text: "",
photoAdded: false
};
},
handleChange: function(event) {
this.setState({ text: event.target.value });
},
togglePhoto: function(event) {
this.setState({ photoAdded: !this.state.photoAdded });
},
remainingCharacters: function() {
if (this.state.photoAdded) {
return 140 - 23 - this.state.text.length;
} else {
return 140 - this.state.text.length;
}
},
render: function() {
return (
<div className="well clearfix">
<textarea className="form-control" onChange={this.handleChange}></textarea>
<br/>
<span>{ this.remainingCharacters() }</span>
<button className="btn btn-primary pull-right"
disabled={this.state.text.length === 0 && !this.state.photoAdded}>
Tweet
</button>
<button className="btn btn-default pull-right" onClick={this.togglePhoto}>
{this.state.photoAdded ? "✓ Photo Added" : "Add Photo" }
</button>
</div>
);
}
});
React.render(
<TweetBox />,
document.body
);
再来看看熟悉的jQuery版本
这里用到了Bootstrap框架,但是仅仅只是为了好看,如果不熟悉BootStrap的话请自动忽略CSS Class
因为jQuery只是一个工具库,它处理问题的思路是,用选择器选择DOM元素,有需要的话就对某个DOM元素进行监听,然后再事件监听函数里进行相对应的处理
jQuery处理问题的思路
给按钮或者文本框绑定监听事件
如果事件触发则开始判断,各个DOM对象的当前状态(通常会借助css class来表示状态)
改变对应的DOM来实现想要达到的效果(tweet box下方显示还可以输入的字符数量,按钮是否可点击)
<div class="well clearfix">
<textarea class="form-control"></textarea><br>
<span>140</span>
<button class="js-tweet-button btn btn-primary pull-right" disabled>Tweet</button>
<button class="js-add-photo-button btn btn-default pull-right">Add Photo</button>
</div>
// 给文本框绑定事件,监听是否有输入
$("textarea").on("input", function() {
if ($(".js-add-photo-button").hasClass("is-on")) {
// add phtot按钮已经点击,剩余输入文本数量再减23
$("span").text(140 - 23 - $(this).val().length);
} else {
// 计算剩余文本数量
$("span").text(140 - $(this).val().length);
}
if ($(this).val().length > 0 || $(".js-add-photo-button").hasClass("is-on")) {
// 如果文本框里有内容或者add phtot按钮已经点击,tweet button设置为可点击状态
$(".js-tweet-button").prop("disabled", false);
} else {
// tweet button设置为不可点击状态
$(".js-tweet-button").prop("disabled", true);
}
});
// 给添加照片的按钮绑定点击事件监听
$(".js-add-photo-button").on("click", function() {
if ($(this).hasClass("is-on")) {
$(this).removeClass("is-on").text("Add Photo"); // 切换add photo按钮显示状态
$("span").text(140 - $("textarea").val().length);
if ($("textarea").val().length === 0) {
// 切换tweet按钮前需要先判断textarea当前状态
$(".js-tweet-button").prop("disabled", true);
}
} else {
$(this).addClass("is-on").text("✓ Photo Added"); // 切换add photo按钮显示状态
$("span").text(140 - 23 - $("textarea").val().length);
$(".js-tweet-button").prop("disabled", false);
}
});
总结
在React中,只有当事件发生的时候,state才发生改变,之后,React自动调用render()来更新UI
-
state成为了事件以及render()之间过渡:
每个事件不需要担心哪一部分的DOM发生变化,他们只需要设置state就可以了
相应的,当你写render()的时候,你也只需要担心现在的state是什么
jQuery没有中间的过渡层'state',我们需要花费很大的精力来解决它们之间相互的联系(对于复杂的组件,建议使用React而不是jQuery)
React中把各个UI组件独立出来,有利于提高UI组件的复用率同时降低各个UI组件的耦合
新手在直接操作DOM时很难写出高效而又优雅的代码,从而使得前端代码满满变得越来越难以维护
也就是说,React适合用在那些DOM操作复杂的单页面应用,有利于提高代码可读性以及提高页面性能(可以参考React Diff算法);
jQuery则是个用来帮你完成一些基本操作的工具库
本文原文(不定期持续更新):为什么是React-浅谈React与jQuery的思维差异
如果需要阅读完整的教程,请阅读英文原文:React.js Introduction For People Who Know Just Enough jQuery To Get By
英文原文的中文翻译版(墨白):React.js 的介绍 - 针对了解 jQuery 的工程师(译)
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。