JSX即JavaScript XML,一种在React组件内部构建标签的类XML语法。
在不使用JSX的状况下,React程序中建立DOM是这样的:html
//v0.11 React.DOM.h1({className: 'title'}, 'Title'); //v0.12 React.createElement('h1', {className: 'title'}, 'Title');
若是使用JSX的方式建立节点为:node
<h1 className="title">Title</h1>
JSX的特征:react
JSX是一种句法变换,每个JSX节点都对应着一个JavaScript函数jquery
JSX即不提供也不须要运行时库git
JSX并无改变或者添加JavaScript的语义,它只是简单的函数调用。github
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> <body> <div id="example"></div> <script src="../build/react.js"></script> <script src="../build/react-dom.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.24/browser.min.js"></script> <script type="text/babel"> ReactDOM.render( <h1>Hello,react!</h1>, document.getElementById('example') ); </script> </body> </html>
要点一:在整个Html文件中,只有定义了一个id为example的div标签,当程序运行时,JavaScript代码执行,
React会建立新的DOM节点,也就是<h1>Hello,react!</h1>。
ReactDOM.render(newDom,parentDom);这个函数是用来对视图进行渲染新的节点,函数的参数主要有两个,
一个是新的节点,另外一个是新节点要放在哪一个父节点中。ajax
要点二:<script> 标签的 type 属性为 "text/babel" 。这是由于 React 独有的 JSX 语法,跟
JavaScript 不兼容。凡是使用 JSX 的地方,都要加上 type="text/babel"算法
要点三:ReactDOM.render()方法中的第一个参数,也就是新的节点,只能有一个顶层的标签,而后里面嵌套多个子节点,
例以下面的写法就是不可行的:json
//Error ReactDOM.render( <p>Error</P> <h1>Hello,react!</h1>, document.getElementById('example') );
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> <body> <div id="example"></div> <script src="../build/react.js"></script> <script src="../build/react-dom.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.24/browser.min.js"></script> <script type="text/babel"> var names = ['lgy','Kb']; ReactDOM.render( <div> { names.map((name) => { return <div>Hello,{name} !</div> }) } </div>, document.getElementById('example') ); </script> </body> </html>
要点:经过在JavaScript中定义变量,可嵌入JSX中使用动态变量,使用的语法为:<div>Hello,{name} !</div>api
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> <body> <div id="example"></div> <script src="../build/react.js"></script> <script src="../build/react-dom.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.24/browser.min.js"></script> <script type="text/babel"> var arr = [ <h1>Hello react</h1>, <h2>Hello Node</h2> ]; ReactDOM.render( <div>{arr}</div>, document.getElementById('example') ); </script> </body> </html>
要点:能够经过传入节点数组的方式,直接把数组给予新的节点,<div>{arr}</div>,JSX语法会根据数组的元素动态生成对应的子节点
React的组件化模式是最大的亮点,组件中使用props或者state,当这两个变量改变时,相应的DOM表现也会有所改变,这主要缘由是一个
组件是一个状态机,对于特定的输入,他总会返回一致的输出。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> <body> <div id="example"></div> <script src="../build/react.js"></script> <script src="../build/react-dom.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.24/browser.min.js"></script> <script type="text/babel"> console.log(React); class HelloMessage extends React.Component{ render() { return <h1>Hello {this.props.name}</h1>; } } ReactDOM.render( <HelloMessage name="LGY" />, document.getElementById('example') ); </script> </body> </html>
要点一: 构造一个组件的语法使用ES6的标准进行,经过继承React.Component,使用render() {...}进行渲染对应的标签和变量输出组件
要点二: 命名新构造的组件的第一个字母须要大写!!!
要点三: 使用构造好的组件,经过使用标签<HelloMessage name="LGY"/>,其中name是传递进去的参数,在内部用this.props.name进行
调用变量
1.Mounting:已插入真实 DOM
2.Updating:正在被从新渲染
3.Unmounting:已移出真实 DOM
1.componentWillMount():改方法在完成首次渲染以前被调用。是在render方法调用前能够修改组件state的最后一次机会
2.componentDidMount():当render方法成功调用后,且DOM已经被渲染,能够在componentDidMount内部经过this.getDOMNode()方法访问到DOM节点
3.componentWillUpdate(object nextProps, object nextState):组件在收到新的props或者state进行渲染以前,这时调用该方法
4.componentDidUpdate(object prevProps, object prevState):这个方法可让咱们更新已经渲染好的DOM的机会
5.componentWillUnmount():当组件的生命结束时,这个方法就会被调用
1.componentWillReceiveProps(object nextProps):已加载组件收到新的参数时调用
2.shouldComponentUpdate(object nextProps, object nextState):组件判断是否从新渲染时调用
经过props能够把任意类型的数据传递给组件
var tables = [{title: 'React'}] <TableList tables={tables} />
能够经过this.props.tables访问对应的属性,然绝对不能修改。一个组件绝对不能够本身修改本身的props!!!
经过在组件中定义一个配置对象。组件初始化时,若是传递的属性和propsTypes不匹配,就会打印一个console.warn日志,
若是是可选的配置,就能够去掉isRequired。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> <body> <div id="example"></div> <script src="../build/react.js"></script> <script src="../build/react-dom.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.24/browser.min.js"></script> <script type="text/babel"> class MyTitle extends React.Component{ render() { return <h1>{this.props.title}</h1>; } } MyTitle.propTypes = { title: React.PropTypes.string.isRequired } //设置默认属性 MyTitle.defaultProps = { title: "lgy" } var data = 'KB'; ReactDOM.render( <MyTitle title={data}/>, document.getElementById('example') ); </script> </body> </html>
要点: 示例中定义了一个组件MyTitle,其中使用propTyps对组件的属性类型进行匹配,defaultProps对组件的属性类型设置默认值。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> <body> <div id="example"></div> <script src="../build/react.js"></script> <script src="../build/react-dom.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.24/browser.min.js"></script> <script type="text/babel"> class NodeList extends React.Component{ render() { return ( <ol> { React.Children.map(this.props.children,(child) => { return <li>{child}</li>; }) } </ol> ); } } ReactDOM.render( <NodeList> <span>Hello!</span> <p>LGY</p> </NodeList>, document.getElementById('example') ); </script> </body> </html>
要点: 经过this.props.children来获取组件的子节点
每一个React组件均可以拥有本身的state,state与props的区别在于前者只存在于组件的内部中,this.props
表示那些一旦定义,就再也不改变的特性,而 this.state 是会随着用户互动而产生变化的特性。state能够肯定
视图的状态。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> <body> <div id="example"></div> <script src="../build/react.js"></script> <script src="../build/react-dom.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.24/browser.min.js"></script> <script type="text/babel"> class LikeButton extends React.Component { constructor(props) { super(props); console.log(this); this.state = {liked: false}; } handleClick(event) { console.log(this); this.setState({liked: !this.state.liked}); }; render() { var text = this.state.liked ? 'like' : 'haven\' t liked'; return( <div> <input type="button" value="Click to toggle." onClick={this.handleClick.bind(this)} /> <p>You {text} this.</p> </div> ); } } ReactDOM.render( <LikeButton />, document.getElementById('example') ); </script> </body> </html>
要点:组件LikeButton经过constructor构造函数进行初始化状态,this.state = {liked: false} 把liked的状态设置为false,
而后经过handleClick绑定this,当用户点击按钮时,改变liked变量的状态,这时视图也会随着一块儿改变。
组件并非真实的 DOM 节点,而是存在于内存之中的一种数据结构,叫作虚拟 DOM (virtual DOM)。只有当它
插入文档之后,才会变成真实的 DOM 。根据 React 的设计,全部的 DOM 变更,都先在虚拟 DOM 上发生,而后
再将实际发生变更的部分,反映在真实 DOM上,这种算法叫作 DOM diff ,它能够极大提升网页的性能表现。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> <body> <div id="example"></div> <script src="../build/react.js"></script> <script src="../build/react-dom.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.24/browser.min.js"></script> <script type="text/babel"> var MyComponent = React.createClass({ handleClick: function() { if (this.myTextInput !== null) { this.refs.myText.focus(); } }, render: function() { return ( <div> <input type="text" ref="myText" /> <input type="button" value="Focus the text input" onClick={this.handleClick} /> </div> ); } }); ReactDOM.render( <MyComponent />, document.getElementById('example') ); </script> </body> </html>
要点:组件 MyComponent 的子节点有一个文本输入框,用于获取用户的输入。这时就必须获取真实的 DOM 节点,虚拟 DOM 是拿不到用户
输入的。为了作到这一点,文本输入框必须有一个 ref 属性,而后 this.refs.[refName] 就会返回这个真实的 DOM 节点。须要注意的
是,因为 this.refs.[refName] 属性获取的是真实 DOM ,因此必须等到虚拟 DOM 插入文档之后,才能使用这个属性,不然会报错。上
面代码中,经过为组件指定 Click 事件的回调函数,确保了只有等到真实 DOM 发生 Click 事件以后,才会读取 this.refs.[refName]
属性。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> <body> <div id="example"></div> <script src="../build/react.js"></script> <script src="../build/react-dom.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.24/browser.min.js"></script> <script type="text/babel"> class Input extends React.Component { constructor(props) { super(props); this.state = {value:'Hello!'} } handleChange(event) { this.setState({value:event.target.value}); } render() { var value = this.state.value; return ( <div> <input type="text" value={value} onChange={this.handleChange.bind(this)}/> <p>{value}</p> </div> ); } } ReactDOM.render( <Input/>, document.getElementById("example") ); </script> </body> </html>
要点:文本输入框的值,不能用 this.props.value 读取,而要定义一个 onChange 事件的回调函数,经过
event.target.value 读取用户输入的值。textarea 元素、select元素、radio元素都属于这种状况
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> <body> <div id="example"></div> <script src="../build/react.js"></script> <script src="../build/react-dom.js"></script> <script src="../node_modules/jquery/dist/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.24/browser.min.js"></script> <script type="text/babel"> function get(source,callback) { var request = new Request(source); fetch(request) .then(res => res.json()) .then(arr => callback(arr[0])) } class UserGist extends React.Component { constructor(props) { super(props); this.state = {username: '',lastGistUrl: ''}; } componentDidMount() { var usr = get(this.props.source,(usr) => { this.setState({ username: usr.owner.login, lastGistUrl: usr.html_url }); }); } render() { var value = this.state.value; return ( <div> {this.state.username}'s last gist is <a href={this.state.lastGistUrl}>here</a>. </div> ); } } ReactDOM.render( <UserGist source="https://api.github.com/users/octocat/gists" />, document.getElementById("example") ); </script> </body> </html>
要点:该实例代码使用了Fetch API来进行数据获取,Fetch API的具体如何使用在接下来的博客文章会介绍。
github仓库连接:https://github.com/lgybetter/ReactDemo