此文章是本人在学习React的时候,写下的学习笔记,在此纪录和分享。此为第五篇,主要介绍react中的props。
目录
1.props的基本使用
2.props的批量传递
2.1展开运算符的复习
2.1.1数组中的展开运算符
2.1.2函数中的展开运算符
2.1.3构造字面量对象时使用展开语法
2.2展开运算符与props
3.对props进行限制
4.props的简写方式
5.类式组件中构造器和props
6.函数式组件与props
6.1函数式组件中使用props
6.2函数式组件内限制props
7.props的总结
1.props的基本使用
我们先来写一个小案例,将一个人的姓名,性别和年龄分别以li的形式渲染到页面上,要渲染多个人的。
这时候我先写好类式组件,在render函数内写上const {name,age,sex} = this.props,将实例中的props解构赋值,方便我们构建虚拟dom时候渲染props内的name,age和sex。
最后在ReactDOM.render内,我们写组件名字的时候,在组件内把name,age和sex传进去。
就像是<Person name='张三' sex='男' age='18'/>的形式。如此我们组件创建的实例中的props属性内就存在了name,sex和age三个数据,在render函数生成虚拟dom时会直接拿取props内的数据。
代码如下:
<!-- 准备好容器 -->
<div id="test1"></div>
<div id="test2"></div>
<div id="test3"></div>
<script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
<script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
<script type="text/babel">
class Person extends React.Component {
render(){
console.log(this);//打印this指向的实例对象,查看props属性
const {name,age,sex} = this.props//解构赋值
return(//构建虚拟dom
<ul>
<li>姓名:{name}</li>
<li>性别:{sex}</li>
<li>年龄:{age}</li>
</ul>
)
}
}
//分别渲染dom到三个容器内
ReactDOM.render(<Person name='张三' sex='男' age='18'/>, document.getElementById('test1'))
ReactDOM.render(<Person name='李四' sex='女' age='19'/>, document.getElementById('test2'))
ReactDOM.render(<Person name='王五' sex='男' age='20'/>, document.getElementById('test3'))
</script>
效果如下:
2.props的批量传递
2.1展开运算符的复习
在学习props的批量转递的时候,我们要先复习一下展开运算符,也就是三点运算符。
2.1.1数组中的展开运算符
如下两个数组,展开运算符可以将一个数组中的每一项展开显示,也可以将两个数组拼接在一起成为一个新的数组。
代码如下:
let arr1 = [1, 3, 5, 7, 9]
let arr2 = [2, 4, 6, 8, 10]
console.log(...arr1);//展开数组
let arr3 = [...arr1, ...arr2]
console.log(arr3);//拼接数组
效果如下:
2.1.2函数中的展开运算符
我们写一个求和函数,在传参的时候使用展开运算符。首先打印一下参数,发现用展开运算符传承的时候,传递的参数会变成一个数组。然后我们正常运行函数,输出结果保证函数求和功能没有问题。
代码如下:
function sum(...numbers) {
console.log(numbers);
return numbers.reduce((preValue, currentValue) => {
return preValue + currentValue
})
}
console.log(sum(1, 2, 3, 4));
效果如下:
2.1.3构造字面量对象时使用展开语法
我们先写这样的代码:
let person = {name:'tom', age:18}
console.log(...person);//报错。展开运算符不可以展开对象
效果如下:
所以,展开运算符不可以展开对象。
但是看下面的代码:
let person = {name:'tom', age:18}
let person2 = {...person}
console.log(person2);
效果如下:
我们使用展开运算符展开了person,并赋值给person2,实现了深拷贝。即使我们再去更改person里的内容,person2的内容也不会改变。
代码如下:我们再写一个person3.
let person3 = {...person,name:'jack',address:'地球'}
console.log(person3);
效果如下:person3是person和新的属性产生了合并,一致的属性产生了覆盖。
2.2展开运算符与props
还是上面的案例,我们尝试使用展开运算符在ReactDOM.render内的组件内使用。
代码如下:我们直接写一个对象存储name,sex和age,并赋值给p。在ReactDOM.render内的组件props内,我们使用了展开运算符,把name,sex和age三个数据一次性批量传入,简单快捷。
ReactDOM.render(<Person name='李四' sex='女' age={19} />, document.getElementById('test2'))
const p = { name:'王五', sex:'男', age:19 }
ReactDOM.render(<Person {...p}/>, document.getElementById('test3'))
3.对props进行限制
上面基本使用的案例,如果我们对name,sex和age的类型分别限定为string,string和number,并且规定name属性不可为空,sex和age都有默认值,那该怎么办呢?
代码如下:
先引入propTypes库,这个依赖包就是限定props需要的包。
<!-- 新引入的库,用于限定props传入值的类型,propTypes -->
<script src="https://cdn.bootcss.com/prop-types/15.6.1/prop-types.js"></script>
然后我们使用Person.propTypes为Person内的各种属性设置类型限定和不可为空。
使用Person.defaultProps为Person内的属性设置默认值。
注意,设置属性的时候,string,number这些类型都是小写的,function类型写为func。
//在引入相应的依赖包后,才能使用本代码对数据类型进行限定
Person.propTypes = {//为Person的数据设置类型限定
name:PropTypes.string.isRequired,//限定name必须为string类型,并且不得为空
sex:PropTypes.string,//限制sex为string类型
age:PropTypes.number,//限定age为number类型
speak:PropTypes.func//限定speak为function类型
}
Person.defaultProps = {//为Person的数据设置默认数据
sex:'性别未知',//为sex设置默认值
age:18//设置age默认值为18
}
//分别渲染dom到三个容器内
ReactDOM.render(<Person name='张三' sex='男' age={18} speak={speak}/>, document.getElementById('test1'))
ReactDOM.render(<Person name='李四' sex='女' age={19}/>, document.getElementById('test2'))
ReactDOM.render(<Person name='王五' sex='男' age={19}/>, document.getElementById('test3'))
function speak() {
console.log('我说话了');
}
写完后,可以尝试违反类型限制为属性传入不同类型的值,这时候在控制台会清楚的指出因为数据类型不同的报错。
4.props的简写方式
代码如下:我们把对数据设置类型限定和设置默认数据的代码,加上static关键字,转移到创建组件的类里面。注意不要写到render函数内。这样props代码部分,放在组件内,比较简洁规范。
//创建组件
class Person extends React.Component {
static propTypes = {//为Person的数据设置类型限定
name: PropTypes.string.isRequired,//限定name必须为string类型,并且不得为空
sex: PropTypes.string,//限制sex为string类型
age: PropTypes.number,//限定age为number类型
speak: PropTypes.func//限定speak为function类型
}
//指定默认标签属性值
static defaultProps = {//为Person的数据设置默认数据
sex: '性别未知',//为sex设置默认值
age: 18//设置age默认值为18
}
render() {
console.log(this);//打印this指向的实例对象,查看props属性
const { name, age, sex } = this.props//解构赋值
return (//构建虚拟dom
<ul>
<li>姓名:{name}</li>
<li>性别:{sex}</li>
<li>年龄:{age}</li>
</ul>
)
}
}
5.类式组件中构造器和props
constructor在类式组件的作用是什么?我们来看react官网的解释:
通常,在React中,构造函数仅用于以下两种情况:
1.通过给this.state赋值对象来初始化内部state
2.为事件处理函数绑定实例。
其实在书写类式组件的时候,可以不写构造器。如果写了构造器,也可以不接收props这个参数,super()内也可以不写,但如果如此,console.log('constructor',this.props);这行代码就会打印undefined,就是在构造器中没有办法通过实例.props去取得值。
代码如下:
constructor(props){
console.log(props);
super(props)
console.log('constructor',this.props);
}
结果:
不接收props的情况:
constructor(){
super()
console.log('constructor',this.props);
}
结果:
所以,构造器是否接收props,是否传递props给super关键字,这就取决于:是否希望在构造器中通过this,访问props。但这个场景及其罕见,如果没有这个需求,构造器都可以直接省略,能省就省。
6.函数式组件与props
对于实例三大属性,函数式组件不可以使用state和ref,但可以使用props,因为它可以接收参数。
6.1函数式组件中使用props
我们在函数式组件内直接接收参数props,在ReactDOM.render(<Person name='张三' sex='男' age={18} />, document.getElementById('test1'))渲染组件到界面时接收参数,name='张三' sex='男' age={18} 这三条传入的数据会自动保存到函数式组件内的props里面,以对象的形式存在。我们使用解构赋值对props解构后,直接拿到虚拟dom里面使用。
代码如下:
function Person(props) {
const { name, age, sex } = props
return (//构建虚拟dom
<ul>
<li>姓名:{name}</li>
<li>性别:{sex}</li>
<li>年龄:{age}</li>
</ul>
)
}
//渲染组件到界面
ReactDOM.render(<Person name='张三' sex='男' age={18} />, document.getElementById('test1'))
效果如下:
6.2函数式组件内限制props
与类式组件类似,我们写 组件名.propTypes和组件名.defaultProps来限制props的数据类型和设置默认数据。写完后可以传入任意类型数据,或者不写数据,看看控制台的输出,发现限制和默认设置没有问题。
代码如下:
function Person(props) {
const { name, age, sex } = props
return (//构建虚拟dom
<ul>
<li>姓名:{name}</li>
<li>性别:{sex}</li>
<li>年龄:{age}</li>
</ul>
)
}
Person.propTypes = {//为Person的数据设置类型限定
name: PropTypes.string.isRequired,//限定name必须为string类型,并且不得为空
sex: PropTypes.string,//限制sex为string类型
age: PropTypes.number,//限定age为number类型
}
Person.defaultProps = {//为Person的数据设置默认数据
sex: '性别未知',//为sex设置默认值
age: 18//设置age默认值为18
}
//渲染组件到界面
ReactDOM.render(<Person name='张三'/>, document.getElementById('test1'))
7.props的总结
理解:
1.每个组件对象都会有props属性。
2.组件标签的所有属性都报存到props属性中。
作用:
1.通过标签属性从组件外向组件内传递变化的数据。
2.注意:组件内部不要修改props数据。