[React18]1.5-props细节详解及注意事项
1、this.props在构造器中使用时,需要用super(props)
props是我们React父子组件之间通信的对象,this.props在构造器中使用时,需要用super(props)进行传递。
举例说明,下面这个构造器constructor
中是获取不到this.props.msg
的值的。
class Welcome extends React.Component {
constructor(){
super();
console.log( this.props.msg ) // undefined
}
render(){
return (
<div>hello world, {this.props.msg}</div>
);
}
}
let element = (
<Welcome msg="hi react" />
);
可以通过给super()
传递props参数是可以做到的,代码如下:
constructor(props){
super(props);
console.log( this.props.msg ) // hi react
}
结合起来,也就是这样写:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../react.development.js"></script>
<script src="../react-dom.development.js"></script>
<script src="../babel.min.js"></script>
</head>
<body>
<div id="app"></div>
<script type="text/babel">
let app = document.querySelector('#app');
let root = ReactDOM.createRoot(app);
class Welcome extends React.Component {
constructor(props){
super(props);
console.log( this.props.msg )
}
render(){
return (
<div>hello world, {this.props.msg}</div>
);
}
}
let element = (
<Welcome msg="hi react" />
);
root.render(element);
</script>
</body>
</html>
那么React类组件是如何设计的呢?就要对面向对象非常的熟悉,原理分析如下:
// 父类
class Foo {
constructor(props){
this.props = props;
}
}
// 子类
class Bar extends Foo {
constructor(props){
super(props);
console.log(this.props);
}
render(){
console.log(this.props);
return '';
}
}
let props = {
msg: 'hello world'
};
let b = new Bar(props);
b.props = props;
b.render();
创建Bar的对象b时,就要将props
传进去,这样才能通过super(props)
传递到父类的构造器,
上面两行console.log才能正常打印出this.props
对象。
2、多属性传递可通过扩展运算符实现
当有非常多的属性要传递的时候,那么会比较麻烦,比如这样时:
let element = (
<Welcome msg="hi react" username="xiaoming" age={20} />
);
所以可通过扩展运算形式进行简写:
class Welcome extends React.Component {
render(){
// 解构
let { msg, username, age } = this.props;
return (
<div>hello world, {msg}, {username}, {age}</div>
);
}
}
// 以对象的形式传递
let info = {
msg: 'hi react',
username: 'xiaoming',
age: 20
};
// 使用...扩展运算符来展开info对象的属性和值
let element = (
<Welcome {...info} />
);
3、props是单向数据流,不能直接修改
像下面这样在render中改props的属性值,会报错:
class Welcome extends React.Component {
render(){
// 不能对props下的属性进行修改,因为数据是单向流动的
this.props.msg = 'hello world';
let { msg, username, age } = this.props;
console.log( isChecked );
return (
<div>hello world, {msg}, {username}, {age}</div>
);
}
}
let info = {
msg: 'hi react',
username: 'xiaoming',
age: 20
};
let element = (
<Welcome {...info} />
);
4、给属性限定类型与添加默认值
- 可以添加一个static对象,添加默认属性值:
class Welcome extends React.Component {
//给属性添加默认值
static defaultProps = {
age: 0
}
render(){
let { msg, username, age } = this.props;
return (
<div>hello world, {msg}, {username}, {age}</div>
);
}
}
let info = {
msg: 'hi react',
username: 'xiaoming',
// 如果age的值没有设置,会显示默认值
//age: 20
};
let element = (
<Welcome {...info} />
);
-
对属性的类型进行限制
需要添加一个
prop-types
库
import PropTypes from 'prop-types'
class Welcome extends React.Component {
//添加默认值
static defaultProps = {
age: 0
}
static propTypes = {
// 限定为number(如果是字符串则是PropTypes.string)
age: PropTypes.number
}
...
}
这里的类型需要引入第三方模块才可以生效。
注意,这里是运行时进行限定,不是在编译时进行限定。
5、只有属性名没有值时,默认值为true
当父子通信的时候,如果只写属性,不写值的话,那么对应的值就是布尔值true。
class Welcome extends React.Component {
render(){
// 解构
let { msg, username, age, isChecked } = this.props;
// isChecked打印出来是:true
console.log( isChecked );
return (
<div>hello world, {msg}, {username}, {age}</div>
);
}
}
// 以对象的形式传递
let info = {
msg: 'hi react',
username: 'xiaoming',
age: 20
};
// 使用...扩展运算符来展开info对象的属性和值
let element = (
// isChecked没有给值
<Welcome {...info} isChecked />
);
上面的isChecked属性没有给值,那么打印出来就是布尔值true。