React组件 (二)

组件实例的三大属性 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"))

posted @ 2021-03-08 11:27  流年瓦解我们的记忆  阅读(68)  评论(0编辑  收藏  举报