一、了解ReactJS:
现在最热门的前端框架有AngularJS、React、Bootstrap等,其中ReactJS独特的Virtual DOM,很具有创新性。
React 起源于 Facebook的内部项目,因为该公司对市场上所有 JavaScript MVC框架,都不满意,就决定自己写一套,用来架设 Instagram的网站。做出来以后,发现这套东西很好用,就在2013年5月开源了。由于 React 的设计思想极其独特,属于革命性创新,性能出众,代码逻辑却非常简单。所以,越来越多的人开始关注和使用,认为它可能是将来 Web开发的主流工具。
ReactJS官网地址:http://facebook.github.io/react/
Github地址:https://github.com/facebook/react
下载ReactJs地址:http://facebook.github.io/react/downloads.html,将下载下来的压缩包解压后,我们新建一个html文件,引用react.js和JSXTransformer.js这两个js文件。html模板如下
<!DOCTYPE html><html>
<head>
<scriptsrc="build/react.js"></script>
<scriptsrc="build/JSXTransformer.js"></script>
</head>
<body>
<div id="container"></div>
<scripttype="text/jsx">
//在此处编写代码
</script>
</body></html>
其中引用JSXTransformer.js是将JSX语法转换成JavaScript语法。凡是使用JSX 的地方,都要加上 type="text/jsx" 。
二、深入了解
1、
<!DOCTYPEhtml>
<html>
<head>
<scriptsrc="build/react.js"></script>
<scriptsrc="build/JSXTransformer.js"></script>
</head>
<body>
<divid="example"></div>
<script type="text/jsx">
React.render(
<h1>Hello, world!</h1>,
document.getElementById('example')
);
</script>
</body>
</html>
以上代码为简单的页面中展示Hello,world!的代码。
在JavaScript 代码里写着 XML 格式的代码称为 JSX;可以去 JSX 语法 里学习更多JSX 相关的知识。为了把 JSX 转成标准的 JavaScript,我们用 <script type="text/jsx"> 标签包裹着含有 JSX 的代码,然后引入 JSXTransformer.js 库来实现在浏览器里的代码转换。
ps:jsx语法是HTML 语言直接写在JavaScript 语言之中,不加任何引号;
2、我们可以将JSX的代码文件单独放到一个文件里面可以在单独的js文件里面写入
React.render(
<h1>Hello,world!</h1>
Document.getElementById("example");
);
然后再在在页面中引用它
<scripttype="text/jsx" src="src/helloworld.js"></script>
PS:某些浏览器无法加载该文件,除非它通过HTTP服务。
3、离线转换
要先安装命令行工具(依赖npm)
Npm instal -g react-tools
安装完成命令行工具就可以使用
jsx --watch src/ build/
修改build/helloworld.js文件自动转换成标准的JavaScript文件。
三、制作组件
1、封装第一个commentBox:
var CommentBox =React.createClass({
render: function(){
return(
<divclassName="commentBox">Hello,我是发表评论的组件</div>
);
}
});
React.render(
<CommentBox/>,
docuement.getElementById('content')
);
原生HTML元素名小写字母开头,而自定义的React类名以大写字母开头。
React.creatClass()来创建一个新的React组件,Render为重要的方法,其返回一个React组件树,这个渲染的组件最终会被渲染成一个HTML。其中的div标签并不是真正的DOM节点,而是React div的实例,所以React是安全的,不操作HTML,默认阻止了XSS攻击。所以说React并不是返回基本的HTML而是返回创建的组件,然React组件化,这个有点类似于angularJS。
ReactDOM.render()实例化根组件,启动框架把标记注入到第二个参数指定的原声的DOM中。
ReactDOM模块提供了一些DOM相关的方法,而React模块包含了React团队分享的不同平台上的核心工具,如React Native。
2、制作组件
//CommentList组件
var CommentList = React.createClass({
render: function() {
return (
<divclassName="commentList">
Hello, world! I am a CommentList.
</div>
);
}
});
//CommentForm组件
var CommentForm = React.createClass({
render: function() {
return (
<divclassName="commentForm">
Hello, world! I am a CommentForm.
</div>
);
}
});
//CommentBox包含CommentList和CommentForm
var CommentBox = React.createClass({
render: function() {
return (
<divclassName="commentBox">
<h1>Comments</h1>
<CommentList />
<CommentForm />
</div>
);
}
});
//渲染CommentBox
React.render(
<CommentBox />,
document.getElementById('content')
);
Ps:在编写时候采用React.render();进行渲染,经过编译后变成ReactDom.render()的js代码。
四、使用组件属性(props)
1、
varComment=React.createClass({
render:function() {
return(
<div className="comment">
<h2 className="commentAuthor">
{this.props.name}
</h2>
{this.props.children}
</div>
);
}
});
React.render(
<Commentname="123456789"/>,
document.getElementById('content')
);
在JSX中我们可以使用大括号包裹一个JavaScript表达式(如上代码中包裹住属性或者儿子节点),可以从树形结构中生成文本或者React组件。通过this.props来访问传入组件的数据,键名就是对应的命名属性,也可以通过this.props.children访问组建内嵌的任何元素。
也就是说我们定义组件中{this.props.name},可以获取<Commentname="123456789"/>中传入的name的值,{this.props.children}可以获取<Comment>123456789</Comment>中文本节点的值。
需要注意的是:
获取属性的值用的是this.props.属性名
创建的组件名称首字母必须大写。
为元素添加css的class时,要用className.
组件的style属性的设置方式也值得注意,要写成style={{width: this.state.witdh}}
2、组件状态
varComment=React.createClass({
render:function() {
return(
<div className="comment">
<h2 className="commentAuthor">
{this.props.name}
</h2>
{this.props.children}
</div>
);
}
});
这里,我们又使用到了一个方法getInitialState,这个函数在组件初始化的时候执行,必需返回NULL或者一个对象。这里我们可以通过this.state.属性名来访问属性值,这里我们将enable这个值跟input的disabled绑定,当要修改这个属性值时,要使用setState方法。我们声明handleClick方法,来绑定到button上面,实现改变state.enable的值.效果如下:
理分析:
当用户点击组件,导致状态变化,this.setState方法就修改状态值,每次修改以后,自动调用 this.render方法,再次渲染组件。
这里值得注意的几点如下:
getInitialState函数必须有返回值,可以是NULL或者一个对象。
访问state的方法是this.state.属性名。
变量用{}包裹,不需要再加双引号。
3、组件的生命周期
组件的生命周期分成三个状态:
- Mounting:已插入真实 DOM
- Updating:正在被重新渲染
- Unmounting:已移出真实 DOM
React 为每个状态都提供了两种处理函数,will函数在进入状态之前调用,did函数在进入状态之后调用,三种状态共计五种处理函数。
- componentWillMount()
- componentDidMount()
- componentWillUpdate(object nextProps, object nextState)
- componentDidUpdate(object prevProps, object prevState)
- componentWillUnmount()
此外,React 还提供两种特殊状态的处理函数。
- componentWillReceiveProps(object nextProps):已加载组件收到新的参数时调用
- shouldComponentUpdate(object nextProps, object nextState):组件判断是否重新渲染时调用
以下例子:
var Hello = React.createClass({
getInitialState: function () {
return {
opacity: 1.0
};
},
componentDidMount: function () {
this.timer = setInterval(function() {
var opacity = this.state.opacity;
opacity -= .05;
if (opacity < 0.1) {
opacity = 1.0;
}
this.setState({
opacity: opacity
});
}.bind(this), 100);
},
render: function () {
return (
<div style={{opacity:this.state.opacity}}>
Hello {this.props.name}
</div>
);
}
});
React.render(
<Helloname="world"/>,
document.body
);
以上代码通过componentDidMount方法设置一个定时器,每隔100毫秒就重新设置组件的透明度重新引发组建渲染。
五、小结:
ReactJs是组件化的开发方式,组件的首字母必须大写。
变量名必须用花括号进行包裹且不可以加双引号。
组件添加外部CSS样式时类名不是class而是className;添加内部样式时候应为style={{opacity:this.state.opacity}}
页面有若干个组件进行嵌套组成。我们可以通过<Comment name=“1234567">1234567890</Comment>设置属性的值将值传递到组件内部,组件内{this.props.name}获取值。
子页面向父页面传值:
// 父组件
varMyContainer = React.createClass({
getInitialState:function () {
return {
checked:false
};
},
onChildChanged:function (newState) {
this.setState({ checked: newState });
},
render:function(){
var isChecked =this.state.checked?'yes' :'no';
return (
<div>
<div>Are you checked: {isChecked}</div>
<ToggleButtontext="Toggle me"initialChecked={this.state.checked}callbackParent={this.onChildChanged}/> </div>
);
}
});
// 子组件
var ToggleButton = React.createClass({
getInitialState: function () {
return { checked:this.props.initialChecked };
},
onTextChange: function () {
var newState = !this.state.checked;
this.setState({
checked: newState
});
// 这里要注意:setState 是一个异步方法,所以需要操作缓存的当前值this.props.callbackParent(newState); },
render: function () {
// 从【父组件】获取的值 var text =this.props.text;
// 组件自身的状态数据
var checked = this.state.checked;
return (
<label>{text}:<inputtype="checkbox"
checked={checked}
onChange={this.onTextChange}/></label>
);
}
});