先讲故事:周一同事给我看了新页面的原型,有大量新增的表单。也就是说,会有相当数量的dom操作。众所周知,用js去生成dom性能是相当差的。怎么来实现需求的同时提升性能呢? 找小强讨论--用React!
漫谈
现在最红的几个前端框架是什么?AngularJs?Backboon?ReactJs?对,他们都算是当红炸子鸡。都是用来实现模块化、自动化双向数据绑定、语义化标签。
于是,为什么我选React?Backboon第一个被排除,对他是这个领域的鼻祖。然并卵,他老了,且很久没跟新了,最根本的内存泄漏问题始终没有解决。
AngularJS,唔嗷~ 很抱歉我没用过这货,尽管它扩展性非常强,但是他的学习曲线太陡峭了,而且这次我们仅仅是为了解决动态dom性能的问题,AngularJS太庞大了。我们并不是说React的功能不强大,要知道React是从最早的UI引擎变成了一整套前后端通吃的 Web App 解决方案。终极目标是用web app的方式去写native app~ 然后我们只要写一次ui,就同时能在服务区 浏览器和手机上看啦~
回归主题,React生成dom为毛性能那么好?根据 React 的设计,所有的 DOM 变动,都先在虚拟 DOM 上发生,然后再将实际发生变动的部分,反映在真实 DOM上,这种算法叫做 DOM diff ,它可以极大提高网页的性能表现。有兴趣可以了解下,当然你也别来问我,我是拾人牙慧,算法什么的我完全不懂。
搞起
明确下我们只搞浏览器端!好了 搞~
标准代码格式
<!DOCTYPE html>
<html>
<head>
<script src="../build/react.js"></script>
<script src="../build/JSXTransformer.js"></script>
</head>
<body>
<div id="example"></div>
<script type="text/jsx">
xx帅帅嗒
</script>
</body>
</html>
script 标签的 type 属性为 text/jsx 。这是因为 React 独有的 JSX 语法,跟 JavaScript 不兼容。凡是使用 JSX 的地方,都要加上 type="text/jsx"
- React 提供两个库: react.js 和 JSXTransformer.js ,它们必须首先加载。其中,JSXTransformer.js 的作用是将 JSX 语法转为 JavaScript 语法。这一步很消耗时间,实际上线的时候,应该将它放到服务器完成。这个我倒最后再讲。下面我们就写个demo
- ```
<!DOCTYPE html>
<html>
<head>
<script src="../build/react.js"></script>
<script src="../build/JSXTransformer.js"></script>
</head>
<body>
<div id="example"></div>
<script type="text/jsx">
React.render(
<h1>Hello, Rex!</h1>,
document.getElementById('example')
);
</script>
</body>
</html>
啊发现有什么特别~ 跟传统js相比jsx语法允许直接写html标签,不需要引号~
<!DOCTYPE html>
<html>
<head>
<script src="../build/react.js"></script>
<script src="../build/JSXTransformer.js"></script>
</head>
<body>
<div id="example"></div>
<script type="text/jsx">
var names = ['Rex', 'xx', 'Sxx'];
React.render(
<div>
{
names.map(function (name) {
return <div>Hello, {name}!</div>
})
}
</div>,
document.getElementById('example')
);
</script>
</body>
</html>
这个demo说明把jsx语法解释的更清楚,遇到<开头的html标签就用html来解析,遇到{开头的用js规则解析。
var arr = [
<h1>Hello world!</h1>,
<h2>Rex is superman</h2>,
];
React.render(
<div>{arr}</div>,
document.getElementById('example')
);
如果数组里的对象像这个demo一样是html结构的话,将会直接被输出
var LikeButton = React.createClass({
getInitialState: function() {
return {liked: false};
},
handleClick: function(event) {
this.setState({liked: !this.state.liked});
},
render: function() {
var text = this.state.liked ? 'like' : 'haven\'t liked';
return (
<p onClick={this.handleClick}>
You {text} this. Click to toggle.
</p>
);
}
});
React.render(
<LikeButton />,
document.getElementById('example')
);
getInitialState 方法用于定义初始状态,也就是一个对象,这个对象可以通过 this.state 属性读取。当用户点击组件,导致状态变化,this.setState 方法就修改状态值,每次修改以后,自动调用 this.render 方法,再次渲染组件
警告!
- 昨天回去尝试写demo,发现出问题了,搞了好久~ 问题出在0.13版更新之后提供了对ES6的支持。并且取消了了函数自动绑定。用新版React去跑我demo的同学,xx在这里给你道歉了~举例:
<button onClick={this.handleSubmit}>Submit</button>
需要改写成
<button onClick={this.handleSubmit.bind(this)}>Submit</button>
未完待续