组件实例的三大属性 2 : props
一个demo(props的基本使用)
需求:自定义用来展示一个人员信息的组件(姓名、性别、年龄)
<div id="test"></div>
<div id="test2"></div>
<script src="../../../js/react.development.js"></script>
<script src="../../../js/react-dom.development.js"></script>
<script src="../../../js/babel.js"></script>
<script type="text/babel">
class Person extends React.Component {
render(){
const {name,age,sex} = this.props
return (
<ul>
<li>姓名:{name}</li>
<li>性别:{sex}</li>
<li>年龄:{age}</li>
</ul>
)
}
}
ReactDOM.render(<Person name="Tom" sex="男" age="18"/> , document.getElementById('test'))
// ReactDOM.render(<Person name="Marry" sex="女" age="20"/> , document.getElementById('test2'))
const p = {name:"Marry",sex:"女",age:"20"}
// ReactDOM.render(<Person name={p.name} sex={p.sex} age={p.age}/> , document.getElementById('test2'))
// 批量传递props
ReactDOM.render(<Person {...p}/> , document.getElementById('test2')) // 展开运算符的使用
</script>
对props进行限制
需求:
1、姓名必须指定,且为字符串类型;
2、性别为字符串类型,如果性别没有指定,默认为男
3、年龄为字符串类型,且为数字类型,默认值为18
<div id="test"></div>
<div id="test2"></div>
<script src="../../../js/react.development.js"></script>
<script src="../../../js/react-dom.development.js"></script>
<script src="../../../js/babel.js"></script>
<!-- 引入prop-types,用于对组件标签属性进行限制 -->
<script src="../../../js/prop-types.js"></script>
<script type="text/babel">
class Person extends React.Component {
render(){
const {name,age,sex} = this.props
// props是只读的
// this.props.name = 'jack' //此行代码会报错,因为props是只读的
return (
<ul>
<li>姓名:{name}</li>
<li>性别:{sex}</li>
<li>年龄:{age}</li>
</ul>
)
}
}
//对标签属性进行类型、必要性的限制
Person.propTypes = {
name:PropTypes.string.isRequired, //限制name必传,且为字符串
sex:PropTypes.string,//限制sex为字符串
age:PropTypes.number,//限制age为数值
}
//指定默认标签属性值
Person.defaultProps = {
sex:'男',//sex默认值为男
age:18 //age默认值为18
}
ReactDOM.render(<Person name="Tom" age={18}/> , document.getElementById('test'))
const p = {name:"Marry",sex:"女",age:20}
ReactDOM.render(<Person {...p}/> , document.getElementById('test2'))
</script>
props的简写方式
class Person extends React.Component {
render(){
const {name,age,sex} = this.props
return (
<ul>
<li>姓名:{name}</li>
<li>性别:{sex}</li>
<li>年龄:{age}</li>
</ul>
)
}
//对标签属性进行类型、必要性的限制
static propTypes = {
name:PropTypes.string.isRequired, //限制name必传,且为字符串
sex:PropTypes.string,//限制sex为字符串
age:PropTypes.number,//限制age为数值
}
//指定默认标签属性值
static defaultProps = {
sex:'男',//sex默认值为男
age:18 //age默认值为18
}
}
ReactDOM.render(<Person name="Tom" age={18}/> , document.getElementById('test'))
const p = {name:"Marry",sex:"女",age:10}
ReactDOM.render(<Person {...p}/> , document.getElementById('test2'))
类式组件与props
//构造器是否接收props,是否传递给super,取决于:是否希望在构造器中通过this访问props
constructor(props){
super(props);
console.log(this.props)
}
constructor 构造器中props传与不传有啥区别呢?
-
构造器是否接收props,是否传递给super,取决于:是否希望在构造器中通过this访问props
-
在 React 组件挂载之前,会调用它的构造函数。 在为 React.Component 子类实现构造函数时, 应在其他语句之前前调用 super(props)。 否则,this.props 在构造函数中可能会出现未定义的 bug。
类中的构造器有啥作用呢?
-
通常,在 React 中,构造函数仅用于以下两种情况:
-
通过给 this.state 赋值对象来初始化内部 state。
-
为事件处理函数绑定实例
constructor(props){
super(props)
this.state = {
isHot : true,
wind:"大风"
}
this.changeWether = this.changeWether.bind(this);
}
函数式组件与props
function Person(props){
const {name,age,sex} = props;
return (
<ul>
<li>姓名:{name}</li>
<li>年龄:{age}</li>
<li>性别:{sex}</li>
</ul>
)
}
//对标签属性进行类型、必要性的限制
Person.propTypes = {
name:PropTypes.string.isRequired, //限制name必传,且为字符串
sex:PropTypes.string,//限制sex为字符串
age:PropTypes.number,//限制age为数值
}
//指定默认标签属性值
Person.defaultProps = {
sex:'男',//sex默认值为男
age:18 //age默认值为18
}
const p = {name:"Marry",sex:"女",age:10}
ReactDOM.render(<Person {...p}/> , document.getElementById('test'))
理解
-
每个组件对象都会有props(properties的简写)属性
-
组件标签的所有属性都保存在props中
作用
-
通过标签属性从组件外向组件内传递变化的数据
-
注意: 组件内部不要修改props数据
编码操作
内部读取某个属性值
this.props.name
对props中的属性值进行类型限制和必要性限制
使用prop-types库进限制(需要引入prop-types库)
Person.propTypes = {
name: PropTypes.string.isRequired,
age: PropTypes.number.
}
更多验证器说明如下:
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!');
}
}
}
}
扩展属性: 将对象的所有属性通过props传递
<Person {...person}/>
默认属性值
Person.defaultProps = {
age: 18,
sex:'男'
}
组件类的构造函数
constructor(props){
super(props)
console.log(props)//打印所有属性
}
请区别一下组件的props和state属性
-
state:组件自身内部可变化的数据,可以根据与用户交互来改变。
-
props:从组件外部向组件内部传递数据,组件内部只读不修改
组件通信
父组件传值给子组件
-
在引用子组件的时候传递,相当于一个属性,例如:在子组件内通过porps.param获取到这个param的值。
-
父组件向子组件传值,通过props,将父组件的state传递给了子组件。
// 父组件
class Parent extends React.Component{
constructor(props){
super(props);
}
state = {
name:"张三"
}
render(){
return (
<div>
<h1>我是父组件</h1>
{/*渲染子组件,并向子组件传递name属性*/}
<Child name={this.state.name}/>
</div>
)
}
}
// 子组件
class Child extends React.Component{
constructor(props){
super(props);
console.log(props);
}
render(){
return (
<div>
<h2>我是子组件</h2>
{/*使用props属性接收父组件传递过来的参数*/}
<div>接收来子父组件的name:{this.props.name}</div>
</div>
)
}
}
ReactDOM.render(<Parent />,document.getElementById("test"))
子组件传值父组件
- 子组件通过调用父组件传递到子组件的方法向父组件传递消息的。
// 父组件
class Parent extends React.Component{
constructor(props){
super(props);
}
state = {
message:""
}
getChildData = (message) => {
this.setState({
message:message
})
}
render(){
return (
<div>
<h1>我是父组件</h1>
<div>
接收来自子组件的值{this.state.message}
</div>
{/* 渲染子组件,设置子组件访问的方法,
getdata属性名为子组件中调用的父组件方法名 */}
<Child getdata={this.getChildData}/>
</div>
)
}
}
// 子组件
class Child extends React.Component{
state = {
inputValue:''
}
//按钮点击事件
handleClick = () => {
console.log(this.props)
//通过props属性获取父组件的getdata方法,并将this.state值传递过去
this.props.getdata(this.state.inputValue);
}
//输入框事件,用于为this.state赋值
handleChange = (e) => {
this.setState({
inputValue: e.target.value
});
}
render(){
return (
<div>
<h2>我是子组件</h2>
<input onChange={this.handleChange}></input>
<button onClick={this.handleClick}>点击获取数据</button>
</div>
)
}
}
ReactDOM.render(<Parent />,document.getElementById("test"))
兄弟组件传值
兄弟组件之间的传值,是通过父组件做的中转 ,流程为:
组件A -- 传值 --> 父组件 -- 传值 --> 组件B
// 父组件
class Parent extends React.Component{
constructor(props){
super(props);
}
state = {
message:""
}
getChildData = (message) => {
this.setState({
message:message
})
}
render(){
return (
<div>
<h1>我是父组件</h1>
<div>
接收来自子组件的值{this.state.message}
</div>
{/* 渲染子组件,设置子组件访问的方法,
getdata属性名为子组件中调用的父组件方法名 */}
<Child getdata={this.getChildData}/>
<DemoB value={this.state.message}/>
</div>
)
}
}
// 子组件(组件A)
class Child extends React.Component{
state = {
inputValue:''
}
//按钮点击事件
handleClick = () => {
console.log(this.props)
//通过props属性获取父组件的getdata方法,并将this.state值传递过去
this.props.getdata(this.state.inputValue);
}
//输入框事件,用于为this.state赋值
handleChange = (e) => {
this.setState({
inputValue: e.target.value
});
}
render(){
return (
<div>
<h2>我是子组件(A组件)</h2>
<input onChange={this.handleChange}></input>
<button onClick={this.handleClick}>点击获取数据</button>
</div>
)
}
}
// 子组件(B组件)
class DemoB extends React.Component{
render(){
return (
<div>
<h1>我是B组件</h1>
<div>展示来自A组件的值:{this.props.value}</div>
</div>
)
}
}
ReactDOM.render(<Parent />,document.getElementById("test"))