- 模块化语法——es6和commonjs a.js: b.js: common.js: index.js:
在JSX
中,类名不是class而是className
:
组件
组件分门别类: Nav.js: Card.js: Cardwrap.js: index.js:ReactDom.render
中的JSX
,本质上是 React.createElement
,所以需要引入React。
props
props:用来传递数据
组件使用props逐级传递消息:属性验证
在终端输入npm i -S prop-types
安装proptypes。Proptypes,检测是否是字符串、数字等属性。可以用来验证后端传过来的数据。
在上面讲述组件逐级向下传递信息的例子中,index.js中的data数据还是那些,在Card组件中验证这些得到的数据:
数据合法,则能正确显示。如果数据不符合要求,比如name传的是数字类型,likeNum传的是字符串类型,这些情况就会报错。isRequired
,必须传过来的:(表示那个属性值要传过来,哪怕是空字符串也是合法的,必须传过来而已)
proptypes
提供了非常全的数据验证:
只要可以被渲染的,就是一个node,node包括element。
props传递数据只能逐级往下传递,不能跨组件式传递数据。context可以跨组件传递数据。
示例,app组件向下传递数据,card组件越过Cardwrap直接接收数据:
警告:使用context会破坏组件的封装性,让组件变得难以复用,而且会让组件的数据流向变得不再那么清晰。除非对Redux或Mobx很熟悉。
state
- state,组件的内部状态
- 初始化一个组件的内部状态需要在类的constructor中进行。
- 更新state:调用
setState()
方法 render方法是组件去调用的,所以render里面的this就是组件的实例。箭头函数里的this是函数所处的上下文环境,所以箭头函数里的this就是render里的this,而如果把箭头函数改为普通函数,普通函数里的this是i那个元素,可是那是真实dom情况下,然而这里是虚拟dom,所以普通函数里使用this会有问题,使用bind来修正这个this指向。react推荐在constructor中来使用bind修正this指向。在constructor中使用bind修正指向:
state是浅合并
示例:实现点击增加数量
setState 异步,react为了保证性能,会将setState批量进行更新。(具体可查阅官方文档)
事件
event.nativeEvent
,浏览器提供的那个事件对象
组件的生命周期
生命周期钩子 react如何运行 第一次渲染:至此第一次渲染结束。接下来是组件的更新:然后react使用diff算法去比较新的虚拟dom和旧的虚拟dom来进行更新:- 每一次state的改变都会触发一次render重新渲染
props
属性只读- react没有模板语法,插值表达式中只支持表达式,不支持语句for if
写一个todolist,每一条todo都是一个对象,将这些todo放在一个数组里
在React中,组件的状态受props和state的控制,这种组件叫做受控组件。如果一个组件改变状态时不受React控制,那么这种组件就叫做非受控组件。比如原生的input输入框,在输入框中可以输入文字,这种是这个元素与生俱来的,并不是react能控制的,这种就是非受控组件,如果在上面约束了value属性,那么就成了受控组件。
无状态函数式组件,没有生命周期,只是用来显示数据而已。React建议使用这种无状态函数式组件,子组件只接受从上向下传递的数据。
input,设置初始值且能编辑:
defaultValue
,但是这样input是不受控的 要让input有初始值且受控,设置value值,这个value值不是直接写在input的属性中,而是从组件的state中拿到,比如在初始化state中时就设置这个初始值。
使用迭代器时每个元素就要有一个key的属性作为主键,以此提供给diff算法使用。
checkbox
——ev.target.checked
在需要拿到真实dom的元素上设置属性
ref
ref={(input)=>{this.pwd = input;}}
state是异步更新的,所以。。。写在setState
的回调函数中
组件挂载完成才能从获取到
refs
尽量让底层组件变成无状态函数式组件
示例:
class Ut extends React.Component{
constructor(props){
super(props);
this.state = {
sex: '',
name: ''
}
this.selectBySex = this.selectBySex.bind(this);
}
selectBySex(ev){
this.setState({
sex: ev.target.value
})
}
render(){
let data = this.props.data;
let {sex} = this.state;
let tbodyItems = null;
if(sex){
tbodyItems = data.map((elt,i)=>{
if(elt.gender==sex){
return <Tr data={elt} key={i}/>
}
})
}
else {
tbodyItems = data.map((elt,i)=>{
return <Tr data={elt} key={i}/>
})
}
return (
<div>
按性别筛选
<select onChange={this.selectBySex}>
<option value="">全部</option>
<option value="男">男</option>
<option value="女">女</option>
</select>
<div>
<table>
<thead>
<tr>
<td>姓名</td>
<td>性别</td>
<td>年龄</td>
<td>身高</td>
<td>体重</td>
<td>操作</td>
</tr>
</thead>
<tbody>
{tbodyItems}
</tbody>
</table>
</div>
</div>
)
}
}
class Tr extends React.Component{
constructor(props){
super(props);
}
render(){
let {stName,gender,age,height,weight} = this.props.data;
return (
<tr>
<td>{stName}</td>
<td>{gender}</td>
<td>{age}</td>
<td>{height}</td>
<td>{weight}</td>
</tr>
)
}
}
ReactDom.render(
<Ut data={dataList}/>,
document.getElementById("root")
);
react-transition-group
1、在终端安装transition-group
:npm i -S react-transition-group
。
2、导入transition
库:import {Transition,TransitionGroup,CSSTransition} from ‘react-transition-group';