React学习笔记三——组件三大属性state、props和refs详解

state

1.类中方法this的指向

  • constructor和render里的this指向类组件的实例对象
  • 在类组件内部定义的普通函数,作为onClick的回调,不是通过实例调用的,是直接调用,并且类组件内部默认开启了局部严格模式,所以this指向undefind

2.将类组件内部定义的函数内部this指向类组件的实例对象

  • 利用箭头函数
  • 在构造器中通过bind改变函数this指向,赋值于实例对象的新定义的方法

3.初始化状态写法

  • 初始化状态写在构造器中 this.state = {}
  • 如果类组件省略构造器了,初始化状态也可以直接以 state= {}写在组件内

4.读取状态

  • this.state.状态名

5.更改状态

  • this.setState()
  • 不能直接修改或更新

以上知识点和详解可以参照下面代码和注释

<head>
  <div id="test"></div>
</head>

//引入一些react核心库和babel
<script type="text/javascript"  src="..."></script>

<script type="text/babel">
 
 //1.创建一个类式组件
  class Demo extends React.Component {
      constructor(props){
         super(props)
         this.state = { // 初始化状态
           isHappy:true, 
           isWeather:true 
         }
         this.changeWeather= this.changeWeather.bind(this) 
         //实例上没有changeWeather方法,但是可以通过原型对象上访问到,然后通过bind改变了函数的this,并赋值给了实例对象上的changeWeather
      }
      
     // 如果类组件省略构造器了,初始化状态也可以直接以 state= {}写在组件内
     // state = { 
     //    isHappy:true, 
     //    isWeather:true 
     //}
      
      click = () => { // 利用箭头函数
        this.setState({
          isHappy:!isHappy
        })
      }
      
      changeWeather(){
      //changeWeather放到了Demo的原型对象上,供实例使用
      //changeWeather是作为onClick的回调,所以不是通过实例调用的,是直接调用
      //类中的方法默认开启了局部严格模式,所以changeWeather的this指向undefind
        this.setState({
          isWeather:!isWeather
        })
      }
	  render() {  
	    const {isHappy,isWeather} = this.state
	    return (
	      <div>
	        <h2 onClick={this.click}>今天我很{ isHappy ? '开心' : '伤心'}</h2>  
	        <h2 onClick={this.changeWeather}>今天天气{ isWeather ? '很好' : '很坏'}</h2>  
	      </div>
	    )
	  }
  } 
 //2.渲染虚拟DOM到页面
 ReactDOM.render(<Demo/> ,document.getElementById('test'))
</ script>

props

1.props一般用于父组件向子组件传值

  • 父组件通过标签属性把值传给子组件
  • 子组件可以通过this.props.属性名去取

2.子组件需要引入prop-types插件来定义props

  • 定义props传入值的类型
  • 定义props传入值是否必传
  • 定义props传入值的默认格式

3.读取props

  • this.props.属性名

4.更改传入的props值

  • 在子组件内不能通过 “ this.props.属性名= ”的方式直接修改
  • 需要在父组件取定义修改方法,传给子组件,子组件调用修改方法取修改值

以上知识点和详解可以参照下面代码和注释

<head>
  <div id="test"></div>
</head>

//引入一些react核心库和babel
<script type="text/javascript"  src="..."></script>
//引入prop-types插件
<script type="text/javascript"  src="..."></script>

<script type="text/babel">
 
 //父组件
  class Info extends React.Component {
      state = {
        infomation:[
         {name:'张三',sex:'男'},
         {name:'李四',sex:'女'}
        ]
      }
	  render() {  
	    const {infomation} = this.state
	    return (
	      <div>
	         <Person info={infomation}></Person>
	      </div?
	    )
	  }
  } 
  
  //子组件
  class Person extends React.Component {
      static propTypes = { //定义props的类型,isRequired表示是否必传 
        info: PropTypes.Array.isRequired
      }
      static defaultProps = { //定义info的默认展示数据
        info:[{name:'xxx',sex:'xxx'}]
      }
	  render() { 
	    const {info} = this.props 
	    return (
	      <ul>
	        {info.map(item => {
	          return <li>{name}:{sex}</li>
	         })
	        }
	      </ul>
	    )
	  }
   } 
 //2.渲染虚拟DOM到页面
 ReactDOM.render(<Person/> ,document.getElementById('test'))
</ script>

refs

1.定义

  • 组件内的标签可以定义ref来表示自己,获取其节点数据

2.ref的类型

  • 字符串ref; 例如:"ref=“input1"” (官方不推荐使用,如果使用量大会存在效率问题)
  • 回调函数ref;例如:“ref={c => this.input2= c}”(在更新过程中会执行两次,第一次传入参数是null,第二次会传入参数DOM元素,但无关紧要,推荐使用)
  • createRef

3.避免过度得使用ref

  • 发生事件的元素正是你要操作的元素,可以使用onClick合成事件,通过event.target去获取操作元素的节点信息

(以上知识点和详解可以参照下面代码和注释)

字符串ref案例组件

<head>
  <div id="test"></div>
</head>

//引入一些react核心库和babel
<script type="text/javascript"  src="..."></script>

<script type="text/babel">
 
 //字符串ref案例组件
  class Demo extends React.Component {
      click = () => {
        console.log(this.refs.input1) //真实DOM的input节点
        const {input1} = this.refs
        alert(input1.value) //弹出input输入框的内容
      }
        
	  render() {  
	    return(
	      <div>
	         <input ref="input1" type="text" placeholder="点击按钮提示数据">
	         <button onClick={this.click}>点击按钮显示左侧数据</button>
	      </div>
	    )
	  }
  }  
 //渲染虚拟DOM到页面
 ReactDOM.render(<Demo/> ,document.getElementById('test'))
</ script>

回调函数ref案例组件

 //回调函数ref案例组件
  ...
  class Demo1 extends React.Component {
      showData= () => {
        const {input2} = this
        alert(input2.value) //弹出input输入框的内容
      }
      
      saveInput = (c)=> { 
       this.input3 = c
       console.log(this.input3,c) //真实DOM的input节点
       alert(this.input3.value) //弹出input输入框的内容
      }
     
	  render() {  
	    return(
	      <div>    
	         {/*1.ref={c => {console.log(c)}} 此时打印的c就是input节点,然后把节点赋值给this上新属性input2,故可以通过this.input2获取其DOM节点;
	            2.每次渲染时会创建一个新的函数实例,所以React清空了旧的ref并设置成新的,所以此方法会有在更新过程中会执行两次,第一次传入参数是null,第二次会传入参数DOM元素的问题;
	            3.但是上面问题无关紧要,推荐使用*/}
	         <input ref={c => this.input2= c} onBlur={this.showData}  type="text" placeholder="失去焦点提示数据">
	         
	           {/*通过将ref的回调函数定义成class的绑定函数的方式来避免上面的问题*/}
	          <input ref={this.saveInput} onBlur={this.showData}  type="text" placeholder="失去焦点提示数据">
	      </div>
	    )
	  }
  } 
 
 //渲染虚拟DOM到页面
 ReactDOM.render(<Demo1/> ,document.getElementById('test'))

createRef案例组件

  //createRef案例组件
  ...
  class Demo2 extends React.Component {
    //React.createRef()调用后可以返回一个容器,该容器用来存储ref所标识的节点
    //该容器是专用的,每个节点需要各自的容器,如果过多的节点使用fef,会比较繁琐。但是官方推荐使用
     myRef = React.createRef()
     myRef2 = React.createRef()
     
     click = () => {
        console.log(this.myRef.current) //真实DOM的input节点
        const {current} = this.myRef
        alert(current.value) //弹出input输入框的内容
     }
     
     showData= () => {
        const {current} = this.myRef2
        alert(current.value) //弹出input输入框的内容
    }
      
	 render() {  
	    return(
	      <div>    
	         <input ref={this.myRef} type="text" placeholder="点击按钮提示数据">
	         <button onClick={this.click}>点击按钮显示左侧数据</button>
	         <input ref={this.myRef2} onBlur={this.showData}  type="text" placeholder="失去焦点提示数据">
	      </div>
	    )
	  }
  } 
 //渲染虚拟DOM到页面
 ReactDOM.render(<Demo2/> ,document.getElementById('test'))
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

前端探险家

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值