第六节:Refs①

120 阅读1分钟

Refs

允许访问真实的DOM

  • React数据流 -> 通过 props来实现父子组件的交互
  • Refs允许我们用于强制修改子组件

管理input

通过一个按钮清空input的value,并聚焦

import React, { Component, createRef } from 'react'

class MyInput extends Component {
  constructor(props) {
    super(props)
    this.inputRef = createRef()
  }
  inputClear() {
    // => input的dom元素
    const inputDom = this.inputRef.current
    inputDom.value = ''
    inputDom.focus()
  }

  render() {
    return (
      <div>
        <input type="text" ref={ this.inputRef }/>
        <button onClick={ this.inputClear.bind(this) }>操控</button>
      </div>
    )
  }
}

export default class App extends Component {
  render() {
    return (
      <div>
        <MyInput />
      </div>
    )
  }
}

image.png 点击操作按钮后

image.png

  • 媒体管理 播放暂停等
  • 强制动画
import React, { Component, createRef } from 'react'

class MyBox extends Component {
  constructor(props) {
    super(props)
    this.boxRef = createRef()
  }
  boxExtend(w, h) {
    const oBox = this.boxRef.current

    oBox.style.width = w +'px'
    oBox.style.height = h +'px'
  }

  render() {
    return (
      <>
        <div 
        ref={this.boxRef}
        style={{
          marginLeft: '100px',
          width: 200 + 'px',
          height: 200 + 'px',
          background: 'orange',
          transition: 'all 1s'
        }}></div>
        <button onClick={ this.boxExtend.bind(this, 500, 500) }>big</button>
        <button onClick={ this.boxExtend.bind(this, 200, 200) }>init</button>
      </>
    )
  }
}


export default class App extends Component {
  render() {
    return (
      <div>
        <MyBox />
      </div>
    )
  }
}

image.png

image.png

  • 集成第三方dom库 如jq
    • 在index.html引入jq的cdn地址
import React, { Component, createRef } from 'react'

class MyBox extends Component {
  constructor(props) {
    super(props)
    this.boxRef = createRef()
  }
  boxExtend(w, h) {
    // => dom节点变成jq对象
    const $box = $(this.boxRef.current)
    
    $box.animate({
        width: w + 'px',
        height: h + 'px'
    })
  }

  render() {
    return (
      <>
        <div 
        ref={this.boxRef}
        style={{
          marginLeft: '100px',
          width: 200 + 'px',
          height: 200 + 'px',
          background: 'orange'
        }}></div>
        <button onClick={ this.boxExtend.bind(this, 500, 500) }>big</button>
        <button onClick={ this.boxExtend.bind(this, 200, 200) }>init</button>
      </>
    )
  }
}


export default class App extends Component {
  render() {
    return (
      <div>
        <MyBox />
      </div>
    )
  }
}

效果如上面的类似

  • model框展示

下面这种方式操作起来多余了一点

import React, { Component, createRef } from 'react'

class Models extends Component {
  constructor(props) {
    super(props)
    this.modelRef = createRef()

    if(props.onRef) {
      props.onRef(this)
    }
  }
  // 打开模态框
  open() {
    this.modelRef.current.style.display = 'block'
  }
  // 关闭模态框
  close() {
    this.modelRef.current.style.display = 'none'
  }
  render() {
    return (
      <div 
      ref={this.modelRef}
      style={{
        width: '500px',
        border: '1px solid #000',
        display: 'none'
      }}>
        <h1>This is a Model</h1>
        <p>this is a super Model</p>  
      </div>
    )
  }
}

export default class App extends Component {
  model=null
  modelOpen(status) {
    switch(status) {
      case 'open':
        this.model.open();
        break;
      case 'close':
        this.model.close();
        break;
      default:
        break;
    }
  }
  render() {
    return (
      <div>
        {/* <MyInput /> */}
        <Models onRef={ (instance) => this.model = instance }/>
        <button onClick={ () => this.modelOpen('open') }>open</button>
        <button onClick={ () => this.modelOpen('close') }>close</button>
      </div>
    )
  }
}

image.png

  • 合理处理方式

利用状态提升能不使用ref的尽量不要区使用ref,违背react的初衷,而且组件的可配置性变强了

import React, { Component } from 'react'

class Models extends Component {
  render() {
    console.log(this.props.isOpen)
    return (
      <div 
      style={{
        width: '500px',
        border: '1px solid #000',
        display: this.props.isOpen ? 'block' : 'none'
      }}>
        <h1>This is a Model</h1>
        <p>this is a super Model</p>  
      </div>
    )
  }
}

export default class App extends Component {
  state = {
    isOpen: false
  }
  modelOpen(status) {
    this.setState({ isOpen: status === 'open' ? true : false })
  }
  render() {
    return (
      <div>
        <Models isOpen={ this.state.isOpen }/>
        <button onClick={ () => this.modelOpen('open') }>open</button>
        <button onClick={ () => this.modelOpen('close') }>close</button>
      </div>
    )
  }
}