React.js学习之理解JSX和组件
在开启JSX的学习旅程前,我们先了解一下React的基本原理。React本质上是一个"状态机",它只关心两件事:更新DOM和响应事件,React不处理Ajax、路由和数据存储,也不规定数据组织的方式。它不是一个MVC的框架,只是MVC里的"V"。
在每次状态改变时,使用JavaScript重新渲染整个页面会异常慢,这应该归咎于读取和更新DOM的性能问题。React使用虚拟DOM实现了一个非常强大的渲染系统,在React中对DOM只更新不读取。React以渲染函数为基础,读取当前的状态,将其转换为目标页面的一个虚拟表现,它采用了非常高效的算法,计算出虚拟页面当前版本和新版本的差异,基于这些差异对DOM进行必要的最少更新。
React的优势在于最小化重绘,并避免了不必要的DOM操作。
1 初识JSX
JSX(JavaScript XML),是一种在React组件内部构建标签的类XML语法。相比JS中嵌入HTML标签,JSX有以下几个明显的特征:
1.JSX是一种句法变换——每一个JSX节点都对应一个JavaScript函数;
2.JSX既不提供也不需要运行时库;
3.JSX并没有改变或添加JavaScript的语义——它只是简单的函数调用。
使用JSX的好处:更加熟悉,更加语义化,更加直观,抽象化,关注点分离。
2 JSX练习
2.1 定义一个自定义组件
React中通过React.createClass定义自定义组件。React组件实现了一个render()方法,该方法接受输入数据并返回要显示的内容。本例采用了类XML语法JSX。render()方法通过this.props来获取传递给组件的输入数据。
1 var HelloWorld = React.createClass({ 2 render: function () { 3 return <div>hello {this.props.name}</div> 4 } 5 }); 6 7 ReactDOM.render( 8 <HelloWorld name="wulei"/>, 9 document.getElementById('example') 10 );
使用react-tools编译后的js代码如下:
1 var HelloWorld = React.createClass({displayName: "HelloWorld", 2 render: function () { 3 return React.createElement("div", null, "hello ", this.props.name) 4 } 5 }); 6 7 ReactDOM.render( 8 React.createElement(HelloWorld, {name: "wulei"}), 9 document.getElementById('example') 10 );
对比会发现,使用JSX后代码变得更熟悉且简洁。
2.2 使用动态值
JSX将两个花括号之间的内容渲染为动态值,花括号指明了一个JavaScript的上下文环境,在花括号中的内容会被进行求值,求值得到的结果会被渲染为标签中的若干节点。对于简单值,比如文本或者数字,可以直接引用对应的变量;对于更复杂的逻辑,可以将其转换为一个函数进行求值。
1 var dynamicText = "test Me!"; 2 3 var HelloWorld = React.createClass({ 4 getName: function () { 5 return "wulei"; 6 }, 7 render: function () { 8 return <div>hello {this.getName()}, {dynamicText}</div> 9 } 10 }); 11 12 ReactDOM.render( 13 <HelloWorld name="wulei"/>, 14 document.getElementById('example') 15 );
2.3 子节点
React将开始标签与结束标签之间的所有子节点保存在一个名为this.props.children的特殊组件属性中。例如在HelloWorld组件中,我们可以把<HelloWorld>标签中的子节点渲染出来,这里我们可以像使用HTML元素一样使用HelloWord组件。
1 var HelloWorld = React.createClass({ 2 getName: function () { 3 return "wulei"; 4 }, 5 render: function () { 6 return <div>hello {this.props.children}</div> 7 } 8 }); 9 10 ReactDOM.render( 11 <HelloWorld name="wulei">I am child!</HelloWorld>, 12 document.getElementById('example') 13 );
运行结果可以看到子节点被成功地渲染。
2.4 属性
与HTML类似,JSX中以内联的方式设置节点属性,同时还提供了将属性设置为动态JavaScript变量的便利,设置动态属性方法同2.2动态值。
2.5 非DOM属性
JSX提供了三个特殊的非DOM属性:
键(key):独一无二,确保在渲染周期保持一致,使得React能够更智能地决定该重用一个组件还是销毁并重新创建一个新的组件进而提升渲染性能。
引用(ref):允许父组件在render方法外保持对子组件的一个引用。
设置原始的HTML(dangerouslySetInnerHTML):将HTML内容设置为字符串。
2.6 事件
事件名统一用驼峰形式表示,如onChange,onClick。
1 var HelloWorld = React.createClass({ 2 getName: function () { 3 return "wulei"; 4 }, 5 handleClick: function(event){ 6 alert("clicked!"); 7 }, 8 render: function () { 9 return <div onClick={this.handleClick}>hello {this.props.children}</div> 10 } 11 }); 12 13 ReactDOM.render( 14 <HelloWorld name="wulei">I am child!</HelloWorld>, 15 document.getElementById('example') 16 );
2.7 样式
React把所有的内联样式都规范化为驼峰形式,与JavaScript中DOM的style属性一致。
3 需要注意的问题
1.React可以渲染HTML标签(strings)或React组件(classes),要渲染HTML标签,只需在JSX里使用小写字母开头的标签名;要渲染React组件,只需创建一个以大写字母开头的本地变量。
2.由于JSX会转换为原生的JavaScript,因此有一些关键词不建议作为JSX标签的属性名,如for(用htmlFor替代)和class(用className替代)。
2.在使用条件判断时,在JSX的花括号中直接加入if语句会渲染出无效的JavaScript。
解决方法:1>使用三目运算符,2>设置一个变量并在属性中引用它,3>将逻辑转换到函数中,4>使用&&运算符。