我们希望构建一个名为companyprofile的组件,该组件可以重用到任何地方。CompanyProfile组件里有两个变量ticker和companyprofileinfo。那么,如果我们不在组件内部对这两个变量的值进行硬编码,那么我们如何将这些值传递给这个组件呢?
这时候props属性登场了。在react中父组件将props属性传递给子组件。您可以将任何内容作为props属性传递-函数、对象、布尔值、字符串、数字等。下面是一个将props属性传递给其子组件示例。
function Children(props) {
return (
<div>{props.textToDisplay}</div>
)
}
function Parent(props) {
return (
<Children textToDisplay={'Hello'}></Children>
)
}
这里需要说明的:
- 组件可以嵌套组件,我们可以任意组合我们的组件,上例代码中就是父组件在其return返回使用子组件;
- 上面父组件使用子组件(内部返回)时,它还传递了一个名为texttodisplay的字符串值hello。我们称之为“传递props属性”。
子组件如何使用父组件传递给它的值呢?
用函数创建的组件
那么它的父组件传递的所有props属性都可以通过参数访问。
React.component创建的组件
那么所有的props都可以作为this.props使用。
class Children extends React.Component {
render(){
return (
<div>{this.props.textToDisplay}</div>
)
}
}
关于props,你必须记住一件事,那就是你不应该改变props值!
function Children(props) {
//千万不要这样做
props.textToDisplay = 'I want to mutate props'
return (
<div>{props.textToDisplay}</div>
)
}
propTypes属性校验
在许多情况下,对于组件来说,最好明确定义props属性类型(数据类型、数据结构、是否需要属性等)。这有两个明显的好处:
- React可以强制执行类型检查,以避免由于父组件传递给子组件的数据类型不是子组件期望的类型(例如,当子组件需要对象时,父组件传递
- 字符串)的属性而导致的许多错误。
- 如果您编写的组件将由不同人员使用,那么对于那些用户来说,了解他们可以传递哪些属性、属性的预期结构等总是很有用的。
要定义这个契约,首先需要将prop类型添加为项目依赖项(由react团队提供),并且需要在组件中定义一个称为prop types的特殊属性。
import React from 'react';
import PropTypes from 'prop-types';
class SoftwareEngineer extends React.Component {
render(){
return (...)
}
}
//defines "propTypes" property in this component
//在组件中定义“proptypes”
SoftwareEngineer.propTypes = {
name: PropTypes.string.isRequired, //需要字符串,并且是必需的
hobbies: PropTypes.arrayOf(PropTypes.string), //需要字符串数组
address: PropTypes.shape({
street: PropTypes.string,
city: PropTypes.string
}) //必须是具有“Street”和“City”字段的对象
}
在这里,我们定义了PropTypes属性并分配了一个对象。此对象中的每个键表示此组件的用户可以传递的属性的名称。该值定义了props的“类型”-字符串、数字、数组等。所有props都是可选的(组件的用户不必传递它们),但具有.isRequired的除外。
Default Props默认props在某些情况下,您可能希望为props定义一个默认值,以防止父组件没有传递任何值进来。这时候您可以使用DefaultProps属性定义默认值。
import React from 'react';
import PropTypes from 'prop-types';
class SoftwareEngineer extends React.Component {
render(){
//如果不传递此属性,它将打印由'default props'定义的默认值['Writing React code']
console.log(this.props.hobbies);
//如果不传递此属性,它将打印“undefined”,因为我们没有为此属性定义任何默认值。
console.log(this.props.address);
return (...)
}
}
//在组件中定义"defaultProps"
SoftwareEngineer.defaultProps = {
hobbies: ['Writing React code']
}
延伸:
多个props值的传递
父组件
//定义一个属性的对象
var infoData = {
name:"网页3剑客",
url:"www.xinran001.com",
copy:"2009"
}
//添加一个测试方法
function outMethod(param){
//把传递过来的参数重新拼接成一个新的字符串
let Result = param.concat("money") ;
console.log(Result);
}
class App extends Component {
render() {
return (
<div className="App">
<Children data={infoData} author={"不愿透露姓名的网友"} out={outMethod} />
</div>
);
}
}
export default App;
子组件
class Children extends React.Component {
//测试方法点击事件
handlerClick(){
{this.props.out("你懂得!")}
}
render(){
return (
<ul>
<li>网站名称:{this.props.data.name}</li>
<li>网址:{this.props.data.url}</li>
<li>版权:{this.props.data.copy}</li>
<li>作者:{this.props.author}</li>
<li><button onClick={this.handlerClick.bind(this)}>撩我</button></li>
</ul>
)
}
}
子组件如何调用父组件的方法,见上。
this.props.children
this.props对象的属性与组件的属性一一对应,但是有一个例外,就是this.props.children属性,它代表组件的所有子节点,举一个官方的例子:
var NotesList = React.createClass({
render: function() {
return (
<ol>{
React.Children.map(this.props.children, function (child) {
return <li>{child}</li>;
})
}</ol>
);
}
});
ReactDOM.render(
<NotesList><span>hello</span><span>world</span></NotesList>,
document.body
);
NotesList组件的两个span子节点,都可以通过this.props.children获取,这里需要注意, this.props.children 的值有三种可能:如果当前组件没有子节点,它就是 undefined ;如果有一个子节点,数据类型是 object ;如果有多个子节点,数据类型就是 array 。所以,处理 this.props.children 的时候要小心。还有就是NotesList组件里的一个回车也算一个子节点。