React学习笔记
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)最后一个 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 等事件,与原生 HTML 不同,on 之后第一个字母是大写的! 其中,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;
PropTypesProps 验证使用 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.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添加库依赖: 具体的调用如下: 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.52php.cn/article/p-rkowmlmt-bnx.html (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |