zoukankan      html  css  js  c++  java
  • 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"))
    
    
  • 相关阅读:
    数据库锁表处理汇总
    2021,顺其自然
    NetCore中跨域策略的一个坑
    Furion框架亮点之-动态WebAPI
    sql中where in的数量限制
    动态规划学习笔记
    用Go编写Web应用程序
    Asp.net Core AutoFac根据程序集实现依赖注入
    Linux+Docker+Gitee+Jenkins自动化部署.NET Core服务
    CentOS8.0安装Nacos
  • 原文地址:https://www.cnblogs.com/jing428/p/14480619.html
Copyright © 2011-2022 走看看