React学习笔记
来源:互联网 发布:java时区转换 编辑:程序博客网 时间:2024/06/16 14:38
React学习笔记
跟着参考资料一路实践了下,终于算是对React有一定的了解了,这篇博文就是相关的一些记录。
1、使用create-react-app快速构建React开发环境
create-react-app是来自于Facebook,通过该命令我们无需配置就能快速构建React开发环境。
create-react-app自动创建的项目是基于Webpack+ES6.
首先切换到相应的目录,然后在命令行执行以下命令创建项目:
$ npm install -g create-react-app $ create-react-app my-app $ cd my-app/ $ npm start
简单的例子
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title> React 实例</title> <script src="https://cdn.bootcss.com/react/15.4.2/react.min.js"></script> <script src="https://cdn.bootcss.com/react/15.4.2/react-dom.min.js"></script> <script src="https://cdn.bootcss.com/babel-standalone/6.22.1/babel.min.js"></script> </head> <body> <div id="example"></div> <script type="text/babel"> ReactDOM.render( <div> <h1>heihei</h1> <h2>欢迎学习 React</h2> </div> , document.getElementById('example') ); </script> </body> </html>
以上的代码有两点需要注意:
1)最后一个<script>
标签的 type 属性为 text/babel
。这是因为 React 独有的 JSX 语法,跟 JavaScript 不兼容。凡是使用 JSX 的地方,都要加上 type="text/babel"
。
2)ReactDOM.render方法是将模版转换为html并插入到指定的节点中。例子中就是插入到id=“example” 的dom节点中。
注意:以上代码中ReactDOM.render的第一个参数中嵌套多个 HTML 标签,需要使用一个 div 元素包裹它,否则报错。
即如下的代码是不正确的:
ReactDOM.render( <h1>这是错误的例子</h1> <span>假设这里是标题下面的内容</span>, document.getElementById("example") );
JavaScript 表达式
我们可以在 JSX 中使用 JavaScript 表达式。表达式写在花括号 {} 中。
实例如下:
ReactDOM.render( <div> <h1>{1+1}</h1> </div> , document.getElementById('example') );
在 JSX 中不能使用 if else 语句,但可以使用 conditional (三元运算) 表达式来替代。以下实例中如果变量 i 等于 1 浏览器将输出 true, 如果修改 i 的值,则会输出 false.
ReactDOM.render( <div> <h1>{i == 1 ? 'True!' : 'False'}</h1> </div> , document.getElementById('example') );
注释
1、在标签内部的注释写在花括号{}中
2、在标签外部的注释不需要使用花括号{}.
ReactDOM.render( /*注释 */ //注释 <h1>wojiushimogui {/*注释*/}</h1>, document.getElementById('example'));
HTML 标签 vs. React 组件
React 可以渲染 HTML 标签 (strings) 或 React 组件 (classes)。
要渲染 HTML 标签,只需在 JSX 里使用小写字母的标签名。
var myDivElement = <div className="foo" />;ReactDOM.render(myDivElement, document.getElementById('example'));
要渲染 React 组件,只需创建一个大写字母开头的本地变量。
var MyComponent = React.createClass({/*...*/});var myElement = <MyComponent someProperty={true} />;ReactDOM.render(myElement, document.getElementById('example'));
React 的 JSX 使用大、小写的约定来区分本地组件的类和 HTML 标签。
JSX 的基本语法规则:遇到 HTML 标签(以 < 开头),就用 HTML 规则解析;遇到代码块(以 { 开头),就用 JavaScript 规则解析。
注意:
由于 JSX 就是 JavaScript,一些标识符像 class 和 for 不建议作为 XML 属性名。作为替代,React DOM 使用 className 和 htmlFor 来做对应的属性。
state
先看一个例子,这里和前面的例子不同,这里将组件单独写在一个文件中了。定义组件的方式有很多中,通过React.createClass()是一种方式,下面通过extends Component是另外一种方式,如果想了解更多,可以参考这篇博文.
import React,{Component} from 'react'; class LikeButton extends Component { constructor(props) { super(props); this.state = { like: false, }; } clickHandler() { this.setState({like: !this.state.like}); } render() { var like = this.state.like ? '喜欢':'不喜欢'; return (<div> <button onClick={this.clickHandler.bind(this)}>你{like}我</button> </div>); } } export default LikeButton;
该组件的state中有一个like字段,初始化为false,当我们点击button按钮时,会调用clickHandler方法来对state进行改变,当state改变之后,然后根据新的 state 重新渲染界面。
值得注意的是:一定要这样写onClick={this.clickHandler.bind(this)}
,如果写成onClick={this.clickHandler}
会报:TypeError: Cannot read property ‘setState’ of undefined错误。
还有一点需要注意:onClick 等事件,与原生 HTML 不同,on 之后第一个字母是大写的!
比如本章实例中,如果将 onClick={this.clickHandler.bind(this)}
换成 onclick={this.clickHandler.bind(this)}
则点击事件不再生效。
其中,clickHandler方法也可以这么写,两者的效果一样。
clickHandler() { this.setState(function (state) { return {like:!state.like} }) }
在容器中这样调用就可以了
ReactDOM.render(<div> <LikeButton/> </div>, document.getElementById('root'));
state和props的区别
上一节通过一个例子介绍了state如何来使用,这一节来介绍state和props的区别。
state 和 props 主要的区别在于 props 是不可变的,而 state 可以根据与用户交互来改变。这就是为什么有些容器组件需要定义 state 来更新和修改数据。 props相当于组件的数据流,它总是会从父组件向下传递至所有的子组件中。
看如下的例子,就是state和props结合使用的一个实例
ReactDOM.render(<div> <Website name="wojiushimogui" link="www.baidu.com"/> </div>, document.getElementById('root'));
组件Website定义如下:
import React,{Component} from 'react'; import Name from './Name'; import Link from './Link'; class Website extends Component { constructor(props){ super(props); this.state={ name:this.props.name, link:this.props.link }; } changeNameAndLink() { this.setState({name:this.state.name+'1',link:this.state.link+'2'}); } render() { return ( <div> <button onClick={this.changeNameAndLink.bind(this)}>点我改变name 和 link</button> <Name name={this.state.name}/> <Link link={this.state.link}/> </div> ); } } export default Website;
组件Website首先在构造函数中利用props中的属性来初始化state中的属性,然后将state中的属性值传给子组件Name和Link。
子组件Name和Link的定义如下:Name组件和Link组件将props中相应的属性值显示出来。
//Name.js import React,{Component} from 'react'; class Name extends Component { render() { return (<p>{this.props.name}</p>); } } export default Name; //Link.js import React,{Component} from 'react'; class Link extends Component { render() { return <a href={this.props.link}>{this.props.link}</a>; } } export default Link;
PropTypes
Props 验证使用 propTypes,它可以保证我们的应用组件被正确使用,PropTypes 提供很多验证器 (validator) 来验证传入数据是否有效。当向 props 传入无效数据时,JavaScript 控制台会抛出警告。
在现在很多参考资料中,都是使用React.PropTypes下提供的验证器来验证传入的数据是否有效,写法如下:
PropsTypeExamp.propTypes = { //title: PropTypes.string.isRequired, title:React.PropTypes.string.isRequired,};
如果你使用的react的版本在15.5.0以上,则如果使用如上的语句,则会报如下的错误:React.PropTypes is deprecated since React 15.5.0, use the npm module prop-types instead 。
错误提示的意思告诉了我们要干什么,修正该错误的方法为:
1、安装prop-types这个包
2、具体写法如下:
import React,{Component} from 'react'; import PropTypes from 'prop-types' class PropsTypeExamp extends Component { render() { return ( <div> <p>{this.props.title}</p> </div> ); } } PropsTypeExamp.propTypes = { title: PropTypes.string.isRequired, };
关于PropTypes,更多可以看这里。
组件的生命周期
借用慕课网上关于React课上的一张图,很好的描述了组件的生命周期。
下面看一个componentDidMount的例子
即在挂载之后定时的变化opacity,然后会触发重新渲染。
import React,{Component} from 'react'; class OpacityExample extends Component { constructor(props){ super(props); this.state={ opacity: 1, }; } componentDidMount() { this.timer = setInterval(function () { var opacity = this.state.opacity; opacity -=0.1; if(opacity<=0.1){ opacity = 1; } this.setState({opacity:opacity}); }.bind(this),100); } render() { return ( <div style={{opacity : this.state.opacity}}> hello,{this.state.opacity} </div> ); } } export default OpacityExample;
再看一个例子来理解Component的生命周期。
import React,{Component} from 'react'; class Name extends Component { componentWillMount() { alert("component will mount!"); } componentDidMount() { alert("component did mount!"); } componentWillReceiveProps(newProps){ alert("component will receiver props"); } /* * //明确的要返回true,则后面才依次执行 componentWillUpdate render componentDidUpdate,三个方法, * 如果返回的是false或者是省略return语句,则后面的三个方法都不能被执行。 } * */ shouldComponentUpdate(newProps, newState) { alert("should component update!"); return true; } componentWillUpdate(nextProps, nextState) { alert("component will update"); } componentDidUpdate(prevProps, prevState) { alert("component did update"); } render() { alert("component render") return (<p>{this.props.name}</p>); } } export default Name;
Name组件在Website组件的子组件,如下:
class Website extends Component { constructor(props){ super(props); this.state={ name:this.props.name, link:this.props.link }; } changeNameAndLink() { this.setState({name:this.state.name+'1',link:this.state.link+'2'}); } render() { return ( <div> <button onClick={this.changeNameAndLink.bind(this)}>点我改变name 和 link</button> <Name name={this.state.name}/> <Link link={this.state.link}/> </div> ); } }
Website被如下的方式调用即可:
ReactDOM.render(<div> <Website name="wojiushimogui" link="www.baidu.com"/> </div>, document.getElementById('root'));
在第一次渲染的时候:会依次调用Name中的componentWillMount、 render、componentDidMount 这三个方法。当我们点击Website中的按钮而改变state的值后会触发更新,则会依次调用Name中的componentWillReceiveProps、 shouldComponentUpdate、 componentWillUpdate、 render、 componentDidUpdate 方法。
在实践过程中,有一点需要注意:shouldComponentUpdate方法如果返回的ture,则执行后面的方法,如果返回的false或者省略return语句则不执行后面的几个方法,这与生命周期图上表述的一致。
React ajax请求
通过AJAX加载数据是一个很普遍的场景。在React组件中如何通过AJAX请求来加载数据呢?首先,AJAX请求的源URL应该通过props传入;其次,最好在componentDidMount函数中加载数据。加载成功,将数据存储在state中后,通过调用setState来触发渲染更新界面。
例子
import React,{Component} from 'react'; import $ from 'jquery' class UserGist extends Component { constructor(props) { super(props); this.state={ username:'', lastGistUrl:'', }; } componentDidMount() { this.serverRequest = $.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> <p>username:{this.state.username}</p> <a href={this.state.lastGistUrl}>{this.state.lastGistUrl}</a> </div> ); } } export default UserGist;
会遇到如下的错误:Module not found: Can’t resolve ‘jquery’
解决方法:在package.json添加库依赖:"jquery": "^3.2.1"
,然后在使用的Component中import $ from 'jquery'
即可。
具体的调用如下:
ReactDOM.render(<div> <UserGist source="https://api.github.com/users/octocat/gists"/> </div>, document.getElementById('root'));
表单与事件
假设有这样一个需求:有个输入框、一个显示框,实时的将输入框中的内容显示在显示框中,即将用户在输入框中输入的内容实时的显示在显示框中。
这里写了一个组件,代码如下:
import React,{Component} from 'react'; class InputAndDisplay extends Component { constructor(props) { super(props); this.state={ content:'', }; } changeHandler(event) { this.setState({content:event.target.value}); } render(){ return ( <div> <input type="text" value={this.state.content} onChange={this.changeHandler.bind(this)}/> <p>{this.state.content}</p> </div> ); } } export default InputAndDisplay;
在前不久,遇到过这样一个问题:需要在子组件中调用父组件的方法来改变父组件的state,应该如何来做呢?
解决方法:需要在父组件通过创建事件句柄 (handleChange) ,并作为 props 传递到你的子组件上。
还是以上面的例子为例来做。
import React,{Component} from 'react'; import Content from './Content' class ContentContainer extends Component { constructor(props) { super(props); this.state={ value :'username', }; } changeHandler(event) { this.setState({value:event.target.value}); } render() { return ( <div> <Content value={this.state.value} changeHandler={this.changeHandler.bind(this)}/> </div> ); } } export default ContentContainer;
自组件Content.js的内容如下:
import React,{Component} from 'react'; class Content extends Component { render() { return ( <div> <input type="text" value={this.props.value} onChange={this.props.changeHandler}/> <p>用户输入的内容为:{this.props.value}</p> </div> ); } } export default Content;
这样,在自组件的onChange 方法将触发 state 的更新并将更新的值传递到子组件的输入框的 value 上来重新渲染界面。
总之:当你需要从子组件中更新父组件的 state 时,你需要在父组件通过创建事件句柄 (handleChange) ,并作为 prop (updateStateProp) 传递到你的子组件上.
React refs
获取真实的Dom节点。
import React,{Component} from 'react'; class GetDomNode extends Component { clickHandler() { this.refs.textInput.focus(); } render() { return ( <div> <button onClick={this.clickHandler.bind(this)}>focus the input text</button> <input type="text" ref="textInput"/> </div> ); } } export default GetDomNode;
参考资料
1、 http://www.runoob.com/react/react-refs.html
2、 http://www.ruanyifeng.com/blog/2015/03/react.html
- React学习学习笔记
- REACT学习笔记
- React.js学习笔记
- react学习笔记
- react 学习笔记1
- React学习笔记
- React-Native 学习笔记
- React学习笔记
- React学习笔记
- REACT学习笔记
- react native学习笔记
- react学习笔记
- react-redux 学习笔记
- React学习笔记
- React学习笔记(1)
- React学习笔记(2)
- React学习笔记(3)
- React学习笔记
- 好玩的动画加载和自定义ProgressBar
- 【算法】【Dynamic Programming】Unique Paths
- Leetcode:Recover Binary Search Tree
- HDFS冗余数据块的自动删除
- 线性表_顺序存储
- React学习笔记
- 常见加密算法
- Ubuntu16.04下通过ngrok实现内网穿透
- 面向对象程序设计上机练习五(类和对象)
- Java Hashmap Key/Value均可为null, HashTable均不能为null
- 威佐夫博弈常见题型和理解
- duilib的CWindowWnd构造函数传递的参数::DefWindowProc
- 这些只有程序员才秒懂...
- 第一次全国程序员人口普查