react 踩坑第一天
1 搭建项目
- 安装node.js环境
- npm install -g create-react-app
- create-react-app my-project
- cd my-project
- npm start
2 创建子组件的几种方式
1)函数式定义
- 函数式定义的
无状态组件(负责根据传入的
props
来展示,不涉及到要state
状态的操作) - 特点
- 组件不会被实例化,整体渲染性能得到提升
因为组件被精简成一个render方法的函数来实现的,由于是无状态组件,所以无状态组件就不会在有组件实例化的过程,无实例化过程也就不需要分配多余的内存,从而性能得到一定的提升。 - 组件不能访问
this
对象
无状态组件由于没有实例化过程,所以无法访问组件this中的对象,例如:this.ref
、this.state
等均不能访问。若想访问就不能使用这种形式来创建组件 - 组件无法访问生命周期的方法
因为无状态组件是不需要组件生命周期管理和状态管理,所以底层实现这种形式的组件时是不会实现组件的生命周期方法。所以无状态组件是不能参与组件的各个生命周期管理的。 - 无状态组件只能访问输入的props,同样的props会得到同样的渲染结果,不会有副作用
例子:app.js
function App(props) {
function showList() {
return (
<div>
<p>{props.name}</p>//直接访问props
<Ha />
</div>
)
};
return (
<div className="App">
{showList()}
</div>
);
}
export default App;
2 ) es5原生方式React.createClass
定义的组件
特点:React.createClass
创建的组件,其每一个成员函数的this都有React自动绑定,任何时候使用,直接使用this.method
即可,函数中的this
会被正确设置。
例子:
import React from 'react';
import ReactDOM from 'react-dom';
var InputControlES5 = React.createClass({
propTypes: {//定义传入props中的属性各种类型
initialValue: React.PropTypes.string
},
defaultProps: { //组件默认的props对象
initialValue: ''
},
// 设置 initial state
getInitialState: function() {//组件相关的状态对象
return {
text: this.props.initialValue || 'placeholder'
};
},
handleChange: function(event) {
this.setState({ //this represents react component instance
text: event.target.value
});
},
render: function() {
return (
<div>
Type something:
<input onChange={this.handleChange} value={this.state.text} />
</div>
);
}
});
export default InputControlES5;
3 )es6形式的extends React.Component
定义的组件
特点:创建的组件,其成员函数不会自动绑定this,需要开发者手动绑定,否则this不能获取当前组件实例对象。
React.Component
有三种手动绑定方法:可以在构造函数中完成绑定,也可以在调用时使用method.bind(this)
来完成绑定,
还可以使用arrow function来绑定。拿上例的handleClick
函数来说,其绑定可以有:
1 constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this); //构造函数中绑定
}
2 <div onClick={this.handleClick.bind(this)}></div> //使用bind来绑定
3 <div onClick={()=>this.handleClick()}></div> //使用arrow function来绑定
例子:
import React from 'react';
import ReactDOM from 'react-dom';
import './App.css';
class Ha extends React.Component {
constructor(props) {
super(props);//必须存在super,否则你无法在构造函数中使用 this
// 设置 initial state
this.state = {
moves:0,
imgs:['./logo192.png','./logo192.png','./logo192.png','./logo192.png','./logo192.png','./logo192.png']
};
}
option(flag){
console.log(this); // React Component instance
if(flag>0){
this.setState({moves:this.state.moves+200})
}else{
this.setState({moves:this.state.moves-200})
}
}
showList() {
return (
<div className='box'>
<span className='icon1' onClick={this.option.bind(this,-1)}>left</span>
<ul className='list' style={{left:this.state.moves+'px'}}>
{
this.state.imgs.map((item, index) => {
return (
<li key={index} >
<img src={item}/>
</li>
)
})
}
</ul>
<span className='icon1' onClick={this.option.bind(this,-1)}>right</span>
</div>
)
}
render() {
return (
<div>
{this.showList()}
</div>
);
}
}
export default Ha;
3 解决onClick立即执行几种的方法+原理
原始写法:
onClick={this.某方法(某参数)}
正确写法:
onClick={() => this.某方法(某参数)}//用箭头函数定义一个新函数,返回结果是个函数
onClick={this.某方法.bind(this, 某参数)}//利用了bind的特性,不会立即调用,而是生成一个新的函数,你想什么时候调就什么时候调
例子:
function add(a, b){
return a+b;
}
var foo1 = add.bind(add, 5,3);
foo1(); //8
var foo1 = add.bind(add, 5,3);
foo1(); //8
问题点:
前者在声明时就直接执行了(因而加载页面自动执行),刚好在事件函数中也有setState操作,这样就会陷入到死循环
中,不停的改变state,render()又不停的被执行。执行后的返回值赋给了onClick属性(返回值必然不会是个函数,因而再点击没有作用)
解决方案:只是声明阻止立即执行
4 react遍历数据,生成列表的几种方式(map,for )
注意:一定要返回,&返回的一定是dom结构
var arr = ['aaa', 'bbb', 'cccc']
var lesson = ['json', 'pp', 'll']
function showList(arr) {
return (
<ul>
{
arr.map((item, index) => {
return <li key={index} >
{item}
</li>
})
}
</ul>
)
}
function a2(arr){
var tem = []
for(var i=0;i<arr.length;i++){
tem.push(<li key={i}>{arr[i]}</li>)
}
return <ul>{tem}</ul>
}