阮一峰老师的github地址:React Demos
<!DOCTYPE html> <html> <head> // react 核心库 <script src="../build/react.js"></script> // react 操作 DOM 库 <script src="../build/react-dom.js"></script> // 将 JSX 语法转化为 js 语法 <script src="../build/browser.min.js"></script> </head> <body> <div id="example"></div> // 使用 balel 解析jsx 语法 <script type="text/babel"> // ** Our code goes here! ** </script> </body> </html>
- 参数一:被渲染的标签
- 参数而:被插入的父元素
// ReactDOM.render() 将模板转化为 HTML 语言 ReactDOM.render( <h1>Hello, world!</h1>, document.getElementById('example') );
var names = ['Alice', 'Emily', 'Kate']; ReactDOM.render( <div> { names.map(function (name) { return <div>Hello, {name}!</div> }) } </div>, document.getElementById('example') );
在参数一中,{}
中可以键入javascript
代码,可以用来遍历数组,对象等;在其中可以使用return
来返回标签。
JSX 的基本语法规则:遇到 HTML 标签(以 <
开头),就用 HTML 规则解析;遇到代码块(以 {
开头),就用 JavaScript 规则解析。
数组直接写在{}
中就能遍历,如下:数组直接就遍历了,展开这个数组的所有成员。
var arr = [ <h1 key="1">Hello world!</h1>, <h2 key="2">React is awesome</h2>, ]; ReactDOM.render( <div>{arr}</div>, document.getElementById('example') );
<div id="example"></div> <script type="text/babel"> class HelloMessage extends React.Component { render() { return <h1>Hello {this.props.name}</h1>; } } // 使用 this.props 接收组件标签的属性 是一个对象 ReactDOM.render( <HelloMessage name="John" />, document.getElementById('example') ); </script>
- // 组件类只能包含一个顶层标签
- // 组件类必须有 / 结尾
- // 所有组件类都必须有自己的 render 方法,用于输出组件
把NotesList
下的所有子节点渲染到 ol li
中
<div id="example"></div> <script type="text/babel"> class NotesList extends React.Component { render() { return ( <ol> { React.Children.map(this.props.children, function (child) { return <li>{child}</li>; }) } </ol> ); } } // this.props.children 表示组件上的子节点 ReactDOM.render( <NotesList> <span>45645</span> <span>hello</span> <span>world</span> </NotesList>, document.getElementById('example') ); </script>
指定组件中的属性类型
<div id="example"></div> <script type="text/babel"> var data = 123; class MyTitle extends React.Component { static propTypes = { title: PropTypes.string.isRequired, } render() { return <h1> {this.props.title} </h1>; } } ReactDOM.render( <MyTitle title={data} />, document.getElementById('example') ); </script>
2、组件 MyComponent
的子节点有一个文本输入框,用于用户输入,这时就必须获取真实的DOM节点,虚拟DOM是拿不到用户输入的数据的
为了做到这一点,文本输入框必须有一个ref
属性,然后this.ref.[refName]
就会返回这个真实的DOM节点。
需要注意的是,由于 this.refs.[refName]
属性获取的是真实 DOM ,所以必须等到虚拟 DOM 插入文档以后,才能使用这个属性,否则会报错。
代码中,通过为组件指定 Click
事件的回调函数,确保了只有等到真实 DOM 发生 Click
事件之后,才会读取 this.refs.[refName]
属性。
<div id="example"></div> <script type="text/babel"> class MyComponent extends React.Component { constructor(props) { super(props); this.myTextInput = React.createRef(); this.handleClick = this.handleClick.bind(this) } handleClick() { console.log('object'); this.myTextInput.current.focus(); } render() { return ( <div> <input type="text" ref={this.myTextInput} /> <input type="button" value="Focus the text input" onClick={this.handleClick} /> </div> ); } } ReactDOM.render( <MyComponent />, document.getElementById('example') ); </script>
8、this.state
<div id="example"></div> <script type="text/babel"> class LikeButton extends React.Component { // 构造器创建 state constructor(props) { super(props) this.state = { liked: false } // p标签上的 方法 this.handleClick = this.handleClick.bind(this) } handleClick(event) { // state 下的 liked 状态改变 this.setState({ liked: !this.state.liked }); } render() { var text = this.state.liked ? 'like' : 'haven\'t liked'; return ( <p onClick={this.handleClick}> You {text} this. Click to toggle. </p> ); } } ReactDOM.render( <LikeButton />, document.getElementById('example') ); </script>
上面代码是一个
LikeButton
组件,构造器函数定义 state 状态,这是一个对象,可以通过this.state属性读取,当用户点击组件时,状态改变,this.setState() 方法就修改状态值,每次修改以后,自动调用this.render方法,再次渲染组件。
由于 this.props
和 this.state
都用于描述组件的特性,可能会产生混淆。
一个简单的区分方法是,this.props
表示那些一旦定义,就不再改变的特性,而 this.state
是会随着用户互动而产生变化的特性。
<div id="example"></div> <script type="text/babel"> class Input extends React.Component { constructor(props) { super(props) this.state = { value: 'Hello!' } this.handleChange = this.handleChange.bind(this) } handleChange(event) { // 设置 input 的值 this.setState({ value: event.target.value }); } render() { var value = this.state.value; return ( <div> <input type="text" value={value} onChange={this.handleChange} /> <p>{value}</p> </div> ); } } ReactDOM.render(<Input/>, document.getElementById('example')); </script>
组件的生命周期分为三个状态:
Mounting: 一插入真实的DOM
Updating: 正在被重新渲染
Unmounting: 以移除真实 DOM
componentWillMount() 组件挂载之前调用,render()之前调用
componentDidMount() DOM渲染完成后调用,可以用于加载后台数据
componentWillUpdate(object nextProps, object nextState)
componentDidUpdate(object prevProps, object prevState) 组件更新时触发该方法,初始渲染不调用
componentWillUnmount() 组件被销毁之前一般用于清理工作(定时器timer、网络请求、订阅事件)
此外,React 还提供两种特殊状态的处理函数。
componentWillReceiveProps(object nextProps):已加载组件收到新的参数时调用
shouldComponentUpdate(object nextProps, object nextState):组件判断是否重新渲染时调用
<div id="example"></div> <script type="text/babel"> class Hello extends React.Component { constructor(props) { super(props) this.state = { opacity: 1.0 }; } // 已插入真实 DOM 函数在进入状态之后调用 componentDidMount() { this.timer = setInterval(function () { // 将状态机的变量赋值给 opacity var opacity = this.state.opacity; // 定时 -0.05 opacity -= .05; if (opacity < 0.1) { opacity = 1.0; } // 重新赋值给 state this.setState({ opacity: opacity }); }.bind(this), 100); } render() { return ( <div style={{opacity: this.state.opacity}}> Hello {this.props.name} </div> ); } } // 添加到 DOM 中 ReactDOM.render( <Hello name="world"/>, document.getElementById('example') ); </script>
使用 jQuery 完成 Ajax 请求
<div id="example"></div> <script type="text/babel"> class UserGist extends React.Component { constructor(props) { super(props) this.state = { username: '', lastGistUrl: '' } } componentDidMount() { $.get(this.props.source, function(result) { var lastGist = result[0]; this.setState({ username: lastGist.owner.login, lastGistUrl: lastGist.html_url }); }.bind(this)); } render() { 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>