React Props
state 和 props 主要的区别在于 props 是不可变的,而 state 可以根据与用户交互来改变。这就是为什么有些容器组件需要定义 state 来更新和修改数据。 而子组件只能通过 props 来传递数据。
使用 Props
以下实例演示了如何在组件中使用 props:
React 实例
function HelloMessage(props) {
return <h1>Hello {props.name}!</h1>;
}
const element = <HelloMessage name="Runoob"/>;
ReactDOM.render(
element,
document.getElementById('example')
);
尝试一下 »
实例中 name 属性通过 props.name 来获取。
默认 Props
你可以通过组件类的 defaultProps 属性为 props 设置默认值,实例如下:
React 实例
class HelloMessage extends React.Component {
render() {
return (
<h1>Hello, {this.props.name}</h1>
);
}
}
HelloMessage.defaultProps = {
name: 'Runoob'
};
const element = <HelloMessage/>;
ReactDOM.render(
element,
document.getElementById('example')
);
尝试一下 »
State 和 Props
以下实例演示了如何在应用中组合使用 state 和 props 。我们可以在父组件中设置 state, 并通过在子组件上使用 props 将其传递到子组件上。在 render 函数中, 我们设置 name 和 site 来获取父组件传递过来的数据。
React 实例
class WebSite extends React.Component {
constructor() {
super();
this.state = {
name: "菜鸟教程",
site: "https://www.runoob.com"
}
}
render() {
return (
<div>
<Name name={this.state.name} />
<Link site={this.state.site} />
</div>
);
}
}
class Name extends React.Component {
render() {
return (
<h1>{this.props.name}</h1>
);
}
}
class Link extends React.Component {
render() {
return (
<a href={this.props.site}>
{this.props.site}
</a>
);
}
}
ReactDOM.render(
<WebSite />,
document.getElementById('example')
);
尝试一下 »
Props 验证
React.PropTypes 在 React v15.5 版本后已经移到了 prop-types 库。
<script src="https://cdn.bootcss.com/prop-types/15.6.1/prop-types.js"></script>
Props 验证使用 propTypes,它可以保证我们的应用组件被正确使用,React.PropTypes 提供很多验证器 (validator) 来验证传入数据是否有效。当向 props 传入无效数据时,JavaScript 控制台会抛出警告。
以下实例创建一个 Mytitle 组件,属性 title 是必须的且是字符串,非字符串类型会自动转换为字符串 :
React 16.4 实例
var title = "菜鸟教程";
// var title = 123;
class MyTitle extends React.Component {
render() {
return (
<h1>Hello, {this.props.title}</h1>
);
}
}
MyTitle.propTypes = {
title: PropTypes.string
};
ReactDOM.render(
<MyTitle title={title} />,
document.getElementById('example')
);
尝试一下 »
React 15.4 实例
var title = "菜鸟教程";
// var title = 123;
var MyTitle = React.createClass({
propTypes: {
title: React.PropTypes.string.isRequired,
},
render: function() {
return <h1> {this.props.title} </h1>;
}
});
ReactDOM.render(
<MyTitle title={title} />,
document.getElementById('example')
);
尝试一下 »
更多验证器说明如下:
MyComponent.propTypes = {
// 可以声明 prop 为指定的 JS 基本数据类型,默认情况,这些数据是可选的
optionalArray: React.PropTypes.array,
optionalBool: React.PropTypes.bool,
optionalFunc: React.PropTypes.func,
optionalNumber: React.PropTypes.number,
optionalObject: React.PropTypes.object,
optionalString: React.PropTypes.string,
// 可以被渲染的对象 numbers, strings, elements 或 array
optionalNode: React.PropTypes.node,
// React 元素
optionalElement: React.PropTypes.element,
// 用 JS 的 instanceof 操作符声明 prop 为类的实例。
optionalMessage: React.PropTypes.instanceOf(Message),
// 用 enum 来限制 prop 只接受指定的值。
optionalEnum: React.PropTypes.oneOf(['News', 'Photos']),
// 可以是多个对象类型中的一个
optionalUnion: React.PropTypes.oneOfType([
React.PropTypes.string,
React.PropTypes.number,
React.PropTypes.instanceOf(Message)
]),
// 指定类型组成的数组
optionalArrayOf: React.PropTypes.arrayOf(React.PropTypes.number),
// 指定类型的属性构成的对象
optionalObjectOf: React.PropTypes.objectOf(React.PropTypes.number),
// 特定 shape 参数的对象
optionalObjectWithShape: React.PropTypes.shape({
color: React.PropTypes.string,
fontSize: React.PropTypes.number
}),
// 任意类型加上 `isRequired` 来使 prop 不可空。
requiredFunc: React.PropTypes.func.isRequired,
// 不可空的任意类型
requiredAny: React.PropTypes.any.isRequired,
// 自定义验证器。如果验证失败需要返回一个 Error 对象。不要直接使用 `console.warn` 或抛异常,因为这样 `oneOfType` 会失效。
customProp: function(props, propName, componentName) {
if (!/matchme/.test(props[propName])) {
return new Error('Validation failed!');
}
}
}
}
年轻的C同学
tco***ence@gmail.com
上次在 React 组件看到这篇笔记没看懂,原来是这里的,现在贴过来分享一下。但是自己现在还是不太懂,希望过几天再来看的时候能够明白。
对创建多个组件的代码,做了点小修改,帮助大家理解。
<WebSite name="菜鸟教程" site=" http://www.runoob.com" />,这种形式传入的 name 和 url 值,只能在 WebSit 组件中用 this.props.xxx 来使用。虽然原来的代码中,Name 和 Site 组件中也是以同样的形式使用的,但并不是因为这条语句的作用,而是因为 <Name name={this.props.name} /> <Link site={this.props.site} /> 。所以我特意将这几行代码做了修改,方便大家感受感受!
WebSite 组件中:
Name 组件中:
Site 组件中:<a href={this.props.site}>{this.props.site}</a>
年轻的C同学
tco***ence@gmail.com
xjjuser
xjj***r@yeah.net
来补充一下上面那位同学所说的。很多情况下,子控件需要父控件所有的 props 参数,这个时候我们一个一个参数的写会很麻烦,比如:
那么我们怎么样吧父属性直接赋值给子组件的props参数呢?如下写法即可:
这样写就非常简洁了,也就子控件和父控件都有了同样数据结构的 props 参数。
很多情况下我们调试页面时,看到的参数名在父控件和子控件中部一样,但是表示的值是同一个,写这段代码的人可能还记得这个参数是转译的,但是其他人阅读时就会摸不着头脑,在效率上是处于弱势的,所以我们一般建议引用父组件参数尽量保持名称不变,以便以后维护。
xjjuser
xjj***r@yeah.net
doo0301@qq.com
doo***1@qq.com
Props 实现父与子通信:
如果想实现“父级”同步“子级”的数据,则需要在子级数据发生改变的时候,调用执行父级props传来的回调,从而达到父级同步更新的效果。
doo0301@qq.com
doo***1@qq.com
独孤尚良
yut***hanlin@qq.com
借助楼上的代码,做了个改良,下面的父子模块互相传递参数。
尝试一下 »
BodyChild 组件的 render 函数返回值 jsx 中 <p> 的 value 是从父组件获取的 getname 这个变量值,onChange 获取的是 changeUsername 这个函数,所以如果文本框中的值改变了,改变值这个事件会触发 changeUsername 这个函数,这个函数会获得事件的值,即我们文本框修改后的值,并将其赋值给父组件的 state.username 这个变量。而父组件的这个变量改变后,state 随之改变,这时候,render 会重新启动,所以我们会看到修改后的值。
父组件的 jsx 中有一个箭头函数,有一个 bind 函数,这两者有什么区别吗?经验证,这两者是可以互换的。
onClick={this.changeAge.bind(this)} 和 onClick={()=>this.changeAge()} 可以互换。
独孤尚良
yut***hanlin@qq.com