通过 Props 传递数据 / 接受父组件传过来的值
Props传过来的值是只读的不能改变
- 父组件
import React, {PureComponent} from 'react';
import ReactDOM from 'react-dom';
import Test from './test'; // 子组件
const tags = ['恐龙', '足球小子']
class App extends PureComponent {
render() {
return (
<Test name='帅子' number={1234567890} isHuman tags={tags} />
);
}
}
export default App;
-
子组件
- 类组件
import React, {PureComponent} from 'react'; class Test extends PureComponent { render() { constructor(props){ super(props) const {name, number, isHuman, tags} = props } return ( <div> <li>{name}</li> <li>电话:{number}</li> <li>{isHuman ? '人类':'外星生物'}</li> { tags.map((tag, index) => ( <li key={index}>{tag}</li> )) } </div> ); } } export default Test;
1:创建类组件继承React.Component / React.PureComponent =>渲染的时候发现type是一个类,则会创建当前类的实例 => 同样会把解析出来的props传递给当前类,react会把props挂载到当前类的实例上(this.props即可操作属性),但是默认情况下是执行完constructor才把props挂载到实例上所以在constructor中无法基于this.props获取
- 函数组件
import React, {PureComponent} from 'react'; const Test = (props) => { const {name, number, isHuman, tags} = props return ( <div> <li>{name}</li> <li>电话:{number}</li> <li>{isHuman ? '人类':'外星生物'}</li> { tags.map((tag, index) => ( <li key={index}>{tag}</li> )) } </div> ); } export default Test;
1: 单笔闭合
2: 双闭合可以像vue的插槽一样使用
function Clock(props){ let children = props.children, FOOT = null, HEAD = null; if(children){ if(!Array.isArray(children)){ children = [children] } HEAD = children.find(item => item,props.name === 'HEAD') FOOT = children.find(item => item,props.name === 'FOOT') } return ( {HEAD} <br /> {new Date().toLocaleString()} {FOOT} ) } ReactDOM.render(<> <Clock index={1}> <span name="FOOT">哈哈哈</span> <span name="HEAD">珠峰培训</span> </Clock> </>,document.getElementById('root') );
3:函数式组件是静态组件,调取组件渲染出一个结果,后续除非重新渲染组件,否则一次渲染的内容不会改变 (react-hooks可以帮我们解决这个问题)
- React.PureComponent组件
export default class Test extends React.PureComponent { } //PureComponent默认会给当前组件设置shouldComponentUpdate周期函数(前提是用户自己没有设置,自己设置已自己为主)
State / 组件更新数据
import React from 'react';
class LikesButton extends React.component{
constructor(props){
super(props)
// 1:初始化状态 (把后续需要用到的状态都初始化)
this.state = {
likes: 0
};
// 为了在回调中使用 `this`,这个绑定是必不可少的
//this.addList = this.addList.bind(this);
}
render(){
// 2:在渲染的时候使用的状态
return (
<span> {this.state.likes} </span>
<button onClick={this.addList.bind(this)}>点赞</button>
)
}
addList() {
// 3:修改状态并更新视图
// setState(partialState, callback)部分状态,当状态更新视图重新渲染触发的回调函数(类似于vue中的$nextTick)
this.setState({
likes: this.state.likes++
});
}
}
export default LikesButton;
受控组件: 基于数据驱动视图渲染(类组件也是动态组件)
=> 组件状态
非受控组件: 直接操作DOM的节点
=> ref
<button
ref = {x => {
// 真实项目中ref经常这样玩,写成函数表达式
// x => 当前操作的元素
this.btn = x
// 直接把元素挂载到实例上,不走refs
}}
>按钮</button>
// this.btn的
使用
this.btn.addEventListener('click), _ => {
// 业务代码
}
Forms / 表单
- 受控组件
import React from 'react';
class LikesButton extends React.component{
constructor(props){
super(props)
this.state = {
inputeValue: ''
};
}
render(){
return (
<input value={this.state.inputeValue} onChange={this.handleChange.bind(this)}/>
)
}
handleChange(event){
this.setState({
inputeValue: event.target.value
});
}
}
export default LikesButton;
prop-types 给属性设置规则
import React from 'react';
import PropTypes from 'prop-types'
class Hello extends React.Component {
// 设置默认值
static defaultProps = {
supNum: 0,
oopNum: 0,
title: 'xiaozhang'
}
// => 初始化状态: ES7中规定下述写法
state = {
// 把传递的属性值赋值状态,目的是后续可以修改这些值
supNum: this.props.supNum,
oopNum: this.props.oopNum,
title: this.props.title
}
render() {
let { title, supNum, oopNum } = this.state
return (
<div>
<i>{title}</i>
<br />
<i>{supNum}</i>
<br />
<i>{oopNum}</i>
</div>
)
}
}
// 设置规则验证
Hello.propTypes = {
title: PropTypes.string.isRequired, // 必传
supNum: PropTypes.number,
oppNum: PropTypes.number
}
export default Hello;