React.js深入学习详细解析
今天,继续深入学习react.js。
目录:
一、JSX介绍
二、React组件生命周期详解
三、属性、状态的含义和用法
四、React中事件的用法
五、组件的协同使用
六、React中的双向绑定
一、JSX介绍
①定义
JSX=JavaScript XML,是一种在React组件内部构建标签的类XML语法。React在不使用JSX的情况下一样可以工作,但是使用JSX可以提高组件的可读性,增强JS语义,结构清晰,抽象程度高,代码模块化。因此推荐在React中使用JSX。
②特点
1、元素名首字母大写
2、符合嵌套规则
3、可以写入求值表达式
4、驼峰式命名
5、不能使用javascript原生函数的一些关键词,如for和class。需要替换成htmlFor和className
③使用方法
1、使用动态值:JSX将两个花括号之间的内容{...}渲染为动态值,花括号指明了一个javascript上下文环境,花括号里面可以是一个变量,也可以是函数。 例如:
var name=“winty”; <p>{name}</p>
function date(d){
return [
d.getFullYear(),
d.getMonth()+1,
d.getDate()
].join('-);
};
<p>{date(new Date()}</p>
2.注释:首先,在子节点中注释要用大括号包裹起来,然后就可以单行注释/**/,也可以多行注释//。
var Hello=React.createClass({ render:function(){ return <p name="winty"> //set name Hello ,World /* 多行注释 多行注释 */ </p> } });
3.使用CSS内联样式
var style={ color:#000; }; React.render(<div style={style}>....</div>,document.body);
4.使用条件判断
//方法1,三目运算符 var Hello=React.createClass({ render:function(){ return <p>Hello,{this.props.name?this.props.name : "LuckyWinty"}</p> } }); //方法2,if-else语句 var Hello1=React.createClass({ getName:function(){ if(this.props.name) return this.props.name; else return "LuckyWinty"; render:function(){ return <p>Hello,{this.getName}</p> } });
//方法3,使用逻辑||运算符 var Hello3=React.createClass({ render:function(){ return <p>Hello,{this.props.name||"LuckyWinty"}</p> } });
④非DOM属性介绍
JSX中有3个非DOM属性,分别是:dangerouslySetInnerHTML、ref、key。
dangerouslySetInnerHTML:在JSX中直接插入HTML代码,但是如果能避免使用这个属性则尽量避免使用。
innerHTML
可能会导致 cross-site scripting (XSS) 攻击。 净化用户的输入来显示的时候,经常会出现错误,不合适的净化也是导致网页攻击 的原因之一。在彻底的理解安全问题后果并正确地净化数据之后,生成只包含唯一 key __html
的对象,并且对象的值是净化后的数据。例如:
function createMarkup() { return {__html: 'First · Second'}; }; <div dangerouslySetInnerHTML={createMarkup()} />
ref:父组件引用子组件,你可以通过在属性中设置期望的引用名来定义一个引用。例如:
... render:function(){ return <div> <input ref="MyInput" .../> </div> } ...
//然后你就可以在组件中的任何地方使用this.refs.myInput获取这个引用了
key:是一个可选的唯一标识符,通过给组件设置一个独一无二的键,并确保它在一个渲染周期中保持一致,使得React能够更只能地决定应该重用一个组件还是销毁并重建一个组件,进而提高渲染性能。例如:
var Hello3=React.createClass({ render:function(){ return <ul> <li key="1">1</li> <li key="2">2</li> <li key="3">3</li> </ul> } });
更多详细信息请参考:http://facebook.github.io/jsx/
二、React组件生命周期详解
<script type="text/babel"> var Hello=React.createClass({ getDefaultProps:function(){ console.log("getDefaultProps, 1"); }, getInitialState:function(){ console.log("getInitialState, 2"); return null; }, componentWillMount:function(){ console.log("componentWillMount, 3"); }, render:function(){ console.log("render, 4"); return <p>Hi,LuckyWinty!</p> }, componentDidMount:function(){ console.log("componentDidMount, 5"); }, }); React.render(<Hello></Hello>,document.body); </script>
运行结果:
三、属性、状态的含义和用法
<Hello name="winty"/> 字符串
<Hello name={123}/> 大括号包裹的求值表达式
<Hello name={[1,2,3]}/> 传入数组
<Hello name={winty}/> 变量
var props={ one:"123", two:"22" }
var instance=React.render(<HelloWorld></HelloWorld>,document.body);
instance.setProps({name:"winty"});
handleChange:function(event){ console.log(event.target.value); }
其他不同类型的事件有不同的属性,简单了解一下
知道了事件的一些属性,我们就可以很方便地在React中获取这些属性,进行一些逻辑的处理,实现一些复杂的业务功能、页面效果等。
例如:我们可以利用鼠标事件属性,实时显示鼠标在某个区域的坐标:
<script type="text/jsx"> var HelloWorld = React.createClass({ getInitialState: function () { return { x: 0, y: 0 } }, handleMouseMove: function (event) { this.setState({ x: event.clientX, y: event.clientY }); }, render: function () { return <div onMouseMove={this.handleMouseMove} style={{ height: '500px', width: '500px', backgroundColor: 'gray' }}> {this.state.x + ', ' + this.state.y} </div>; }, }); React.render(<HelloWorld></HelloWorld>, document.body); </script>
五、组件的协同使用
①组件嵌套使用:也就是说,用一个父组件把子组件包裹起来,本质就是父子关系。如下图描述:
实例代码:
var React = require('react'); var CommentList=require('./CommentList.jsx'); var CommentForm=require('./commentFrom.jsx'); var CommentBox = React.createClass({ render: function() { return ( <div className="commentBox"> <h1>Comments</h1> <CommentList /> //这是一个组件 <CommentForm /> //这是另一个组件 </div> ); } }); module.exports = CommentBox;
②Mixin:也就是可以把相同的代码抽象出来,封装成一个函数,然后再调用。
var Time=React.createClass({ mixins:[IntervalMixin(1000)], getInitialState:function(){ return {secondElapsed:0}; }, onTick:function(){ this.setState({secondElapsed:this.state.secondElapsed+1}); }, render:function(){ return ( <div>Seconds Elapsed:{this.state.secondsElapsed}</div> ); } });
mixin相当简单,它们就是混合进组件类中的对象而已。React在这方面实现得更加深入,它能防止静默函数覆盖,同时还支持多个mixin混合。但是这些功能在别的系统中可能引起冲突。例如:
React.createClass({ mixins:[{ getInitialState:function(){ return {a:1}} }], getInitialState:function(){ return {b:2}} });
这样在mixin和组件类中同时定义了getInitialState方法,得到的初始state是{a:1,b:2}.如果mixin中的方法和组件类中的方法返回的对象中存在重复的键,React会抛出一个错误来警示这个问题。
六、React中的双向绑定
React创立的理念跟angular那些框架就是不同的,React是单向数据绑定的。那么怎么实现像angular那样的双向绑定效果呢?看代码:
<!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset="UTF-8"> <title>React中的双向数据绑定</title> </head> <body> <script src="./react-0.13.2/react-0.13.2/build/react-with-addons.js"></script> <script src="./react-0.13.2/react-0.13.2/build/JSXTransformer.js"></script> <script type="text/jsx"> var BindingMixin = { handleChange: function(key) { var that = this var newState = {} return function(event) { newState[key] = event.target.value that.setState(newState) } } } var BindingExample = React.createClass({ mixins: [React.addons.LinkedStateMixin], getInitialState: function() { return { text: '', comment: '', } }, render: function() { return <div> <input type="text" placeholder="请输入内容" valueLink={this.linkState('text')} /> <textarea valueLink={this.linkState('comment')}></textarea> <h3>{this.state.text}</h3> <h3>{this.state.comment}</h3> </div> } }) React.render(<BindingExample></BindingExample>, document.body); </script> </body> </html>
效果图(没有CSS样式,有点不优雅,见谅):
更多学习demo已上传至:https://github.com/LuckyWinty/ReactStudyDemo,欢迎参考!
参考资料:
《React引领未来的用户界面开发框架》
极客学院视频课程
PS:react.js模块化开发及打包方式欢迎参考我的上一篇博文《React.js入门必须知道的那些事》,后续会有更多深入的学习,欢迎大家给我学习意见^_^