zoukankan      html  css  js  c++  java
  • React 之 组件实例的三大核心属性 (state props ref)

    扩展:

      在React中,构造函数仅用于以下两种情况

      1)通过给this.state 赋值对象来初始化内部 state

      2)为事件处理函数绑定实例

    在构造函数中注意事项:

    在为ReactComponent子类实现构造函数时,应该其他语句之前调用super(props).否则this.props在构造函数中会出现未定义的bug

    说人话(翻译)即:传不传props,就看你要不要使用props

    // constructor(props){
          //   super(props)
          //   console.log(props)     // props和this.props数据是一样的
          //   console.log(this.props)
          // }
          // constructor()
          // {
          //   super()
          //   console.log(this.props);  //undefined
          // }
          constructor(props)
          {
            super()
            console.log(this.props)  //undefined
          }

    一.初识 state

    1)state是组件对象醉重要的属性,值是对象(可以包含多个键值对数据)

    2)组件被称为"状态机",通过更新组件的state来更新对应的页面显示(重新渲染组件)

    强烈注意:

    1)组件中render方法中的this为组件实例对象

    2)组件自定义的方法中,this为undefined,如何解决?

         a.强制绑定this,通过函数对象的bind()

         b.箭头函数

    3)状态数据,不能直接修改或更新

    初始化state状态 案例 (绑定事件) 

    class Weather extends React.Component{
          constructor(){
            super()
            this.state = {isHot:true,wind:'大风'}
    
          }
          render(){
            console.log(this)
            return <h1 onClick={demo}>今天天气很 {this.state.isHot?'炎热':'凉爽'}</h1>
          }
        }
        ReactDOM.render(<Weather/>,document.getElementById('test'))
    
        function demo(){
    console.log(this) // undefined console.log(
    '标题被点击了'); } 如何事件绑定,如上代码

    扩展: 原生js有哪几种事件绑定方式
    1)节点.addEventListener('click',()=>{ alert('点击了')})
    2)节点.onclick = ()=>{}
    3)<button onclick="demo()">

    变更类中this的指向问题

    // 创建组件
        class Weather extends React.Component{
          constructor(){
            super()
            this.state = {isHot:true,wind:'大风'}  //通过给state赋值对象来初始化内部state
            this.changeWeather = this.changeWeather.bind(this)   //为事件处理函数绑定实例
    
          }
          render(){
            console.log(this);
            this.changeWeather()
            return <h1 onClick={this.changeWeather}>今天天气很 {this.state.isHot?'炎热':'凉爽'}</h1>
          }
          changeWeather(){
            console.log(this);
          }
        }
        ReactDOM.render(<Weather/>,document.getElementById('test'))

    如何修改 state的数据? 通过setState

    class Weather extends React.Component{
          constructor(props){
            /* constructor 调用了几次
              只有组件实例化时,才会执行一次,这里只有一次
            */
            console.log('constructor') 
            super(props)
            this.state = {isHot:false}
            this.changeWeather = this.changeWeather.bind(this)
    
          }
          render(){
            /* render 调用了几次?
              执行了1+n次   实例化执行了一次,然后状态发生变化时就会执行
            */
            console.log('render')
            return <h1 onClick={this.changeWeather}>今天天气很 {this.state.isHot?'炎热':'凉爽'}</h1>
          }
          changeWeather(){
            console.log('changeWeather')
            const {isHot} = this.state
            this.setState({isHot:!isHot})
            // console.log(this);
          }
        }
        ReactDOM.render(<Weather/>,document.getElementById('test'))

    简化写法

    // 创建组件
        class Weather extends React.Component{
          // 初始化状态
          state = {isHot:false}
    
          render(){
            const {isHot} = this.state
            return <h1 onClick={this.changeWeather}>今天天气很 {isHot?'炎热':'凉爽'}</h1>
          }
          //自定义方法
          changeWeather = ()=>{
            const {isHot} = this.state
            this.setState({isHot:!isHot})
          }
        }
        // 渲染组件到页面上
        ReactDOM.render(<Weather/>,document.getElementById('test'))

    二.初始props   是只读的

    class Person extends React.Component {
          render() {
            return (
              <ul>
                <li>姓名:{this.props.name}</li>
                <li>性别:男</li>
                <li>年龄:{this.props.age}</li>
              </ul>
            )
          }
        }
    const p = {name:'张三',}
    ReactDOM.render(<Person name="tom" age="20"/>,document.getElementById('test1'))
    ReactDOM.render(<Person name="Jon" age="18"/>,document.getElementById('test1'))
    
    

    优化写法

    class Person extends React.Component {
          render() {
            let {name,age,gender} =this.props
            return (
              <ul>
                <li>姓名:{this.props.name}</li>
                <li>性别:{this.props.gender}</li>
                <li>年龄:{this.props.age}</li>
              </ul>
            )
          }
        }
        const p = {name:'张三',age:20,gender:''}
        // ReactDOM.render(<Person name="tom" age="20"/>,document.getElementById('test1'))
        ReactDOM.render(<Person {...p}/>,document.getElementById('test1'))

    对props进行限制

    注意:需要引用 prop-types.js  因为在15.几的时候这样使用的,但是16.几之后,React.PropTypes.string.isRequired就被修改了

    具体原因看下面代码块中的(tip)

    class Person extends React.Component {
          render() {
            let {name,age,gender} =this.props
            return (
              <ul>
                <li>姓名:{this.props.name}</li>
                <li>性别:{this.props.gender}</li>
                <li>年龄:{this.props.age}</li>
              </ul>
            )
          }
        }
        Person.propTypes = {   //propTypes 小写 react就会识别是要进行prop限制
       //name:React.PropTypes.string.isRequired, // tips:版本15.几的时候把这种功能添加到了react.development.js上,变的笨重 name:PropTypes.
    string.isRequired, //PropTypes 大写 即:数据类型 gender:PropTypes.string } Person.defaultProps = { //默认值 gender:'不难不女', name:'李四' } const p = {name:'张三',age:20} // ReactDOM.render(<Person name="tom" age="20"/>,document.getElementById('test1')) ReactDOM.render(<Person {...p}/>,document.getElementById('test1'))

    props的简写方式

    class Person extends React.Component {
          static propTypes = {
            name:PropTypes.string.isRequired,
            gender:PropTypes.string,
            age:PropTypes.number
          }
          static defaultProps = {
            gender:'',
            age:18
          }
          render(){
            console.log(this)
            const {name,age,gender} = this.props
            return (
              <ul>
                <li>名字:{name}</li>
                <li>年纪:{age}</li>
                <li>性别:{gender}</li>
              </ul>
            )
          }
        }
        const p= {name:'李四',age:20,gender:''}
        ReactDOM.render(<Person name="张三"  gender=""/>,document.getElementById('test1'))
        ReactDOM.render(<Person {...p }/>,document.getElementById('test2'))

    类组件中 构造器和props

     注:看扩展内容

    函数组件使用 props (函数组件只能玩转props)

    三.初始ref   最推荐第三种 React.createRef()

    第一种:String 类型的Refs ,在未来会被移除  简单案例(了解即可)

    原因:string类型refs存在一些问题,太多了就会效率不高问题

    class Demo extends React.Component {
            render(){
              return (
                <div>
                  <input type="text" ref="input1" placeholder="点击按钮提示数据"/> &nbsp;
                  <button onClick={this.handleClick}>点我提示左侧的数据</button>&nbsp;
                  <input type="text" ref="input2" placeholder="失去焦点提示数据"  onBlur={this.handleBlur}/>
                </div>
              )
            }
            handleClick= () => {
              console.log(this,1111)
              console.log(this.refs.input1.value)
            }
            handleBlur=() => {
              const {input2} = this.refs
              console.log(input2.value)
            }
        }
        ReactDOM.render(<Demo/>,document.getElementById('test1'))

    第二种: 回调函数形式的ref   

    内联的回调函数会在state发生变化时,执行两次,怎么解决,但是并不影响开发,也经常会用到这种

    class Demo extends React.Component {
          state={ isHot:false }
          render() {
            return (
              <div>
                <h2 onClick={this.handleHot}>今天的天气怎么?{this.state.isHot?'凉爽':'炎热'}</h2>
                /* 内联方式,这里的回调函数执行了几次  2次   是要state发生变化,先清空currentNode,然后在去执行第二次
    通过内联形式,每次去执行时就相当于是一个新的函数,所以currentNode就是空的
    */ <input ref={currentNode => {this.input1 = currentNode;console.log('@',currentNode) } } type="text"/> <button onClick={this.handleClick}>点击</button> </div> ) } handleClick=()=>{ const {input1} = this console.log(input1.value) } handleHot=()=>{ const {isHot} = this.state this.setState({isHot:!isHot}) } } ReactDOM.render(<Demo/>,document.getElementById('test1'))

    外联回调

    class Demo extends React.Component {
          state={ isHot:false }
          callback = (currentNode) => {
            this.input1 = currentNode
            console.log(currentNode)
          }
          render() {
            return (
              <div>
                <h2 onClick={this.handleHot}>今天的天气怎么?{this.state.isHot?'凉爽':'炎热'}</h2>
                /* 内联方式,这里的回调函数执行了几次  2次   是要state发生变化,先清空currentNode,然后在去执行第二次
                之所以会清空currentNode是因为执行第一次是,去执行时,内联函数是一个新的函数
                */
                <input ref={ this.callback } type="text"/>
                <button onClick={this.handleClick}>点击</button>
              </div>
            )
          }
          handleClick=()=>{
            const {input1} = this
            console.log(input1.value)
          }
          handleHot=()=>{
            const {isHot} = this.state
            this.setState({isHot:!isHot})
          }
        }
        ReactDOM.render(<Demo/>,document.getElementById('test1'))

    第三种:createRef的使用 (最推荐)

    /* 
            react.create调用后可以返回一个容器,该容器可以存储被ref所标识的节点,该容器是"专人专用"的
          */
          myRef = React.createRef()
          myRef2 = React.createRef()
          showData = ()=>{
            console.log(this.myRef.current.value)
            console.log(this.myRef2.current.value)
            console.log('哈哈')
          }
          render(){
            return (
              <div>
                  <input type="text" ref={this.myRef} placeholder="点击提交按钮"/>&nbsp;
                  <button onClick={this.showData }>点我输出左边信息</button>
                  <input type="text" ref={this.myRef2} placeholder="点击提交按钮"/>&nbsp;
              </div>
            )
          }
        }
        ReactDOM.render(<Demo/>,document.getElementById('test1'))
  • 相关阅读:
    如何进行shell脚本正确性测试
    linux 重命名文件和文件夹
    linux 下 `dirname $0`
    五句话搞定JavaScript作用域
    Javascrpt
    css
    HTML
    python之sqlalchemy
    Python之路【第九篇】:Python操作 RabbitMQ、Redis、Memcache、SQLAlchemy
    Python之路【第八篇】:堡垒机实例以及数据库操作
  • 原文地址:https://www.cnblogs.com/zmztya/p/14629592.html
Copyright © 2011-2022 走看看