- React组件采用ES6 class的写法:
import React, {Component} from 'react';
class Children extends Component{
constructor(props){
super(props); //调用父类的构造函数,固定写法,继承父组件属性
this.state = {
value:'',
list:[]
}
}
render(){
return ();
}
}
- 标签添加样式类名,不能用''class",要用"className"
- 利用props继承父组件的属性(单向数据流);
- 利用state声明响应式变量;
- React事件的钩子命名采用小驼峰写法:onClick 、 onChange等;
- 要在constructor函数里面为事件绑定this,写法:
this.inputChange=this.inputChange.bind(this);
这种在组件里面可以直接使用:
onChange={this.inputChange};
如果不使用这种方式,则可以在声明函数时采用“箭头函数”的写法:
inputChange = (e) =>{
this.setState({
inputValue : e.target.value
})
}
- 利用循环生成节点时,要记得为item设置'key':
<ul>
{
this.state.list.map((item,index) =>{
return <li
key={index+item}
onClick={this.deleteItem.bind(this,index)}
>
{item}
</li>
})
}
</ul>
- 在React里面不允许直接操作state.例如要删除state里面一个数组的某一项,应该先拷贝一份要操作的那个数组,然后对拷贝的数组进行操作,操作完成之后,将state里面那个数组更新为操作之后的数组:
let list = this.state.list; //先拷贝一份
list.splice(index,1); //对拷贝这个数组进行操作
this.setState({
list:list //操作之后更新
})
也就是说不能像这样:
this.state.list.splice(index,1) //直接操作state
this.setState({
list:this.state.list
})
- JSX写注释的方法:
{/* 这是注释 */}
- React 通过preventDefault()来阻止默认行为:
function handleClick(e) {
e.preventDefault();
console.log('The link was clicked.');
}
- label使用'for'属性,实现点击label即可启用输入框的光标,在React里面for要设置为'htmlFor':
<div>
<label htmlFor="haha">增加选项:</label>
<input id="haha" className="input" value={this.state.inputValue} onChange={this.inputChange.bind(this)} />
<button onClick={this.addList.bind(this)}> 确定 </button>
</div>
- React父组件向子组件传值:属性名 = {变量}
<Children content={item}></Children>
在子组件中使用:
<div>{this.props.content}}</div>
- 子组件调用父组件的方法,将父组件的方法作为参数传递过去:
<XuanXiangKaItem
key={index+item}
content={item}
index={index}
deleteItem = {this.deleteItem.bind(this)}
/>
子组件调用:
handleDelete(){
console.log(this.props.index);
this.props.deleteItem(this.props.index);
}
- 在子组件里面,不能直接去修改props传递过来的值,因为react是单向数据流。如果要在子组件里面更改父组件的值,应当将父组件里面的方法通过props一起传递到子组件,然后在子组件里面调用父组件传递过来的方法。
- 子组件里面校验父组件传递过来的值,使用PropTypes进行校验:
import PropTypes from 'prop-types';
XuanXiangkaItem.propTypes= { //写在class之后
content:PropTypes.string.isRequired //isRequired表示这个参数必须传
index:PropTypes.number,
deleteItem:PropTypes.func
}
- 指定props参数的默认值,使用defaultProps:
XuanXiangkaItem.defaultProps = {
content:'默认值'
}
17.ref的基本使用: //在组件里面
ref={(input)=>(this.input = input)} //利用箭头函数来绑定
在函数操作中使用:
this.setState({
// inputValue : e.target.value
inputValue : this.input.value //取代e.target.value
})
- ref和setState一起使用的一个坑:
<ul ref={(ul) => (this.ul = ul)}>
{
this.state.list.map((item,index) =>{
return (
<XuanXiangKaItem
key={index+item}
content={item}
index={index}
deleteItem = {this.deleteItem.bind(this)}
/>
)
})
}
</ul>
在调用setState之后打印ul数组的长度:
addItem = ()=>{
this.setState({
list:[...this.state.list,this.state.inputValue],
inputValue:''
})
console.log(console.log(this.ul.querySelectorAll('div').length)); // 在这里调用
}
打印结果会少一个,因为setState是异步的,我们虚拟Dom还没更新就去调用console.log了。 解决方法,利用setState的回调函数:
addItem = ()=>{
this.setState({
list:[...this.state.list,this.state.inputValue],
inputValue:''
},()=>{ //这里调用setState的回调
console.log(this.ul.querySelectorAll('div').length);
})
}
适用场景:我们在进行了一些数据更新之后,我们想要立即拿到变化之后的虚拟Dom,我们就应当用setState的回调函数。 19. React的生命周期主要分为四大阶段:
Initialization:初始化阶段。
Mounting: 挂载阶段。
Updation: 更新阶段。
Unmounting: 销毁阶段
可以看出,render函数是一个生命周期函数,当props、state变化时,都会自动进行调用.
constructor不能称为是生命周期函数,他仅仅是ES6的语法,虽然它和生命周期函数的性质一样,但不能认为是生命周期函数。应该把它看成是React的Initialization阶段,定义属性(props)和状态(state)。
Mounting: 挂载阶段
Mounting阶段,即是挂载阶段,伴随着整个虚拟Dom的生成,这个周期里面有三个生命周期函数:
- componentWillMount:在组件即将被挂载到页面的时刻执行,
- render:页面props和state发生变化时执行,
- componentDidMount:组件挂载(插入dom树中)完成之后执行。
需要注意的问题:componentWillMount和componentDidMount,这两个周期函数,只会在页面刷新时执行一次,但是render则不同,只要页面props和state发生变化时就会执行。所以我们可以将异步请求写在componentWillMount和componentDidMount钩子函数里面,但是在使用RN时,使用componentWillMount钩子会有冲突。所以建议在componentDidMount函数里作异步请求。
Updation: 更新阶段
Updation阶段主要是更新阶段,有两个部分组成,一个是props属性的改变,另一个是state状态的改变。
- shouldComponentUpdate:它要求返回一个布尔类型的结果,必须有返回值,简单点说,就是返回true,就同意组件更新;返回false,就反对组件更新,
- componentWillUpdate:在组件更新之前,但shouldComponenUpdate之后被执行。但是如果shouldComponentUpdate返回false,这个函数就不会被执行了,
- componentDidUpdate:组件更新完成之后执行。
Unmounting: 销毁阶段
Unmounting是指组件的销毁阶段
- componentWillUnmount:组件从页面中删除的时候执行
还有一个特殊的生命周期函数:componentWillReceiveProps 函数。
componentWillReceiveProps:子组件接收到父组件传递过来的参数,父组件render函数重新被执行,这个生命周期就会被执行。
- 可以利用生命周期函数的一些特性对程序的性能进行优化: 例如父组件有个输入框,输入框的值传递props到子组件,引起子组件重新调用render函数,即是重新渲染,但是我们不希望我们输入时,子组件就在不停的调用render,这样会引起性能损耗,我们只是希望当我们输入完成之后,子组件的render调用就行了,在这种情况下面,我们就可以利用生命周期来实现性能优化。我们监听子组件的更新周期,对传递的props进行前后比较:
shouldComponentUpdate(nextProps,nextState){
if(nextProps.content !== this.props.content){
return true
}else{
return false
}
}//shouldComponentUpdate有两个参数:nextProps:变化后的属性;nextState:变化后的状态;
未完待续...
参考自React官网和技术胖博客