前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >React学习笔记(四)—— 组件通信与状态管理、Hooks、Redux、Mobe

React学习笔记(四)—— 组件通信与状态管理、Hooks、Redux、Mobe

作者头像
张果
发布2023-03-24 11:53:07
4.6K0
发布2023-03-24 11:53:07
举报
文章被收录于专栏:软件开发软件开发

react管理状态的工具:

1、利用hooks进行状态管理;

2、利用Redux进行状态管理,这种方式的配套工具比较齐全,可以自定义各种中间件;

3、利用Mobx进行状态管理,它通过透明的函数响应式编程使得状态管理变得简单和可扩展。

2013 年 5 月 React 诞生。但 2015 年之前,大概都是 jQuery 的天下。2015 年 3 月 React 0.13.0 发布,带来了 class 组件写法。

在 React class 组件时代,状态就是 this.state,使用 this.setState 更新。

为避免一团乱麻,React 引入了 "组件" 和 "单向数据流" 的理念。有了状态与组件,自然就有了状态在组件间的传递,一般称为 "通信"。

父子通信较简单,而深层级、远距离组件的通信,则依赖于 "状态提升" + props 层层传递。

于是,React 引入了 Context,一个用于解决组件 "跨级" 通信的官方方案。

但 Context 其实相当于 "状态提升",并没有额外的性能优化,且写起来比较啰嗦。

为优化性能,一般会添加多个 Context,写起来就更啰嗦。在项目没那么复杂时,还不如层层传递简单。

Context 没那么好用,React 官方也没什么最佳实践,于是一个个社区库就诞生了。

目前比较常用的状态管理方式有hooks、redux、mobx三种。

一、组件通信

(1).组件的特点

组件是独立且封闭的单元,默认情况下,只能使用组件自己的数据

在组件化过程中,通常会将一个完整的功能拆分成多个组件,以更好的完成整个应用的功能

(2).知道组件通讯意义

而在这个过程中,多个组件之间不可避免的要共享某些数据

为了实现这些功能,就需要打破组件的独立封闭性,让其与外界沟通、这个过程就是组件通讯

1.1、父传子

父组件向子组件通信是通过父组件的props传递数据完成。

UserList.jsx接收父组件的数据,展示用户信息,子组件:

代码语言:javascript
复制
import React, { Component } from 'react'

export default class UserList extends Component {
  render() {
    return (
      <div>
        <ul>
          {this.props.users.map(user =><li key={user.id}>
            {user.name}
          </li>)}
        </ul>
      </div>
    )
  }
}

UserListContainer.jsx向子组件传递数据,父组件:

代码语言:javascript
复制
import React, { Component } from 'react'
import UserList from './UserList'

export default class UserListContainer extends Component {
    state={users:[]}
    componentDidMount(){
        const users=[
            {id:"1001",name:"Jone"},
            {id:"1002",name:"Mali"},
            {id:"1003",name:"Locy"},
            {id:"1004",name:"Rose"},
            {id:"1005",name:"Jack"}
        ]
        this.setState({users:users});
    }
  render() {
    return (
      <div><div>用户信息列表</div>
      <UserList users={this.state.users}/>
      </div>
    )
  }
}

运行结果:

 解释:数据users在父组件中通过属性传递给子组件UserList,在UserList中通过props接收父组件传入的数据,完成父传子,这是最简单,最基本的一个状态的传递方法,推荐常用。

1.2、子传父

子传父依然使用props,父组件先给子组件传递一个回调函数,子组件调用父组件的回调函数传入数据,父组件处理数据即可。

在UserList中添加新增加功能:

代码语言:javascript
复制
import React, { Component } from 'react'

export default class UserList extends Component {
  state={newUser:""}
  handleChange=e=>{
    this.setState({newUser:e.target.value});
  }
  handleClick=e=>{
    if(this.state.newUser&&this.state.newUser.length>0){
      this.props.onAddUser(this.state.newUser);
    }
  }
  render() {
    return (
      <div>
        <ul>
          {this.props.users.map(user =><li key={user.id}>
            {user.name}
          </li>)}
        </ul>
        <div>
          姓名:<input type="text" onChange={this.handleChange} value={this.state.newUser}></input>
        <button onClick={this.handleClick} type="submit">新增</button>
        </div>
      </div>
    )
  }
}

在UserListContainer中添加onAddUser参数与函数:

代码语言:javascript
复制
import React, { Component } from 'react'
import UserList from './UserList'

export default class UserListContainer extends Component {
    state={users:[]}
    componentDidMount(){
        const users=[
            {id:"1001",name:"Jone"},
            {id:"1002",name:"Mali"},
            {id:"1003",name:"Locy"},
            {id:"1004",name:"Rose"},
            {id:"1005",name:"Jack"}
        ]
        this.setState({users:users});
    }

    onAddUser(newUser){
        let users=this.state.users;
        this.setState({users:users.concat({
            id:parseInt((users[users.length-1].id)+1)+"",
            name:newUser
        })});
    }
  render() {
    return (
      <div><div>用户信息列表</div>
      <UserList users={this.state.users} onAddUser={this.onAddUser.bind(this)}/>
      </div>
    )
  }
}

运行:

 解释:在子组件中用户输入了一个新的姓名,调用props.addUser方法将新添加的用户信息发送给父组件完成添加功能,所以这里实现了子传父功能。

 * UserListContainer中包含UserList组件,所以UserListContainer是父组件,而UserList是子组件

 * 子组件通过调用父组件中的onAddUser方法将输入的用户添加到集合中,完成子传父功能

1.3、兄弟组件间通信

兄弟组件不能直接相互传送数据,需要通过状态提升的方式实现兄弟组件的通信,即把组件之间需要共享的状态保存到距离它们最近的共同父组件内,任意一个兄弟组件都可以通过父组件传递的回调函数来修改共享状态,父组件中共享状态的变化也会通过props向下传递给所有兄弟组件,从而完成兄弟组件之间的通信。

 我们在UserListContainer中新增一个子组件UserDetail,用于显示当前选中用户的详细信息,比如用户的年龄、联系方式、家庭地址等。这时,UserList 和 UserDetail 就成了兄弟组件,UserListContainer是它们的共同父组件。当用户在 UserList中点击一条用户信息时,UserDetail需要同步显示该用户的详细信息,因此,可以把当前选中的用户 currentUser保存到UserListContainer的状态中。

UserList.jsx

代码语言:javascript
复制
import React, { Component } from 'react'
import "./css/userList.css"

/**
 * 用户列表组件
 */
export default class UserList extends Component {
  /**
   * 构造函数
   * @param {*} props 
   */
  constructor(props) {
    super(props);
    this.state = { newUser: ""};
  }

  /**
   * 输入框内容变化事件
   * @param {*} e 
   */
  handleChange = e => {
    this.setState({ newUser: e.target.value });
  }

  /**
   * 新增用户按钮点击事件
   * @param {*} e 
   */
  handleClick = e => {
    if (this.state.newUser && this.state.newUser.length > 0) {
      this.props.onAddUser(this.state.newUser);
    }
  }

  /**
   * 用户列表项点击事件
   * @param {*} userId 
   */
  handleSelect(userId) {
    this.props.onSetCurrentUser(userId);
  }
  /**
   * 渲染函数
   */
  render() {
    return (
      <div>
        <ul>
          {this.props.users.map(user => <li key={user.id} className={user.id === this.props.currentUserId ? "active" : ""} onClick={this.handleSelect.bind(this, user.id)}>
            {user.name}
          </li>)}
        </ul>
        <div>
          姓名:<input type="text" onChange={this.handleChange} value={this.state.newUser}></input>
          <button onClick={this.handleClick} type="submit">新增</button>
        </div>
      </div>
    )
  }
}

UserDetails.jsx

代码语言:javascript
复制
import React, { Component } from 'react'

export default class UserDetails extends Component {
  render() {
    return (
        this.props.currentUser?
        <div>
        <h2>详细信息</h2>
        <fieldset>
            <legend>用户</legend>
            <p>
                {/* 用户编号 */}
                编号:{this.props.currentUser.id}
            </p>
            <p>
                {/* 用户姓名 */}
                姓名:{this.props.currentUser.name}
            </p>
        </fieldset>
      </div>:""   )
  }
}

UserListContainer.jsx

代码语言:javascript
复制
import React, { Component } from 'react'
import UserList from './UserList'
import UserDetails from './UserDetails'

export default class UserListContainer extends Component {
    state={users:[],currentUserId:null}
    componentDidMount(){
        const users=[
            {id:"1001",name:"Jone"},
            {id:"1002",name:"Mali"},
            {id:"1003",name:"Locy"},
            {id:"1004",name:"Rose"},
            {id:"1005",name:"Jack"}
        ]
        this.setState({users:users});
    }

    // 添加用户
    onAddUser(username){
        let users=this.state.users;
        let newUser={
            id:(parseInt(users[users.length-1].id)+1)+"",
            name:username
        };
        this.setState({users:users.concat(newUser),currentUserId:newUser.id});
    }

    // 设置当前用户
    onSetCurrentUser(userId){
        this.setState({currentUserId:userId});
    }

  render() {
    const users=this.state.users.filter(user=>user.id===this.state.currentUserId);
    const currentUser=users&&users.length>0&&users[0];
    return (
      <div><div>用户信息列表</div>
      <UserList users={this.state.users} onAddUser={this.onAddUser.bind(this)} onSetCurrentUser={this.onSetCurrentUser.bind(this)} currentUserId={this.state.currentUserId}/>
      <UserDetails currentUser={currentUser} />
      </div>
    )
  }
}

运行效果:

解释:在子组件UserList中添加一个username,通过onAddUser将username传入父组件UserListContainer中,这里完成了状态提升,在UserListContainer中再将新添加的用户传入给UserDetail组件,实现从父传给子组件,整个过程实现了兄弟之间的数据传递功能。

UserListPro.jsx

代码语言:javascript
复制
import React, { Component } from 'react'
import "./css/userListPro.css"

export default class UserListPro extends Component {
    state={username:""}
    usernameChange=(e)=>{
        this.setState({username:e.target.value})
    }
    handleSubmit=e=>{
        const {username} = this.state;
        if(username&&username.length>0){
            //调用父组件的onAddUser方法将值username传递给父组件
            this.props.onAddUser(this.state.username);
        }
        e.preventDefault();
    };

    selectHandle=(e)=>{
        //将当前选择的用户编号传给父组件
        this.props.onSetCurrentId(e.target.id);
    };

  render() {
    console.log(this);
    return (
      <div>
        <ul className='userDetail'>
        {this.props.users.map(user=><li 
        key={user.id} 
        id={user.id} 
        onClick={this.selectHandle}
        className={user.id===this.props.currentId?"active":""}
        >{user.id} - {user.name}</li>)}
        </ul>
        <div>
            <form onSubmit={this.handleSubmit}>
                <p>
                <label>姓名:</label>
                <input type="text" value={this.state.username} onChange={this.usernameChange}/>
                <button>添加</button>
                </p>
            </form>
        </div>
      </div>
    )
  }
}

UserListContainer.jsx

代码语言:javascript
复制
import React, { Component } from 'react'

import UserListPro from './UserListPro';
import UserDetail from './UserDetail';

/**
 * UserListContainer中包含UserList组件,所以UserListContainer是父组件,而UserList是子组件
 * 子组件通过调用父组件中的onAddUser方法将输入的用户添加到集合中,完成子传父功能
 */
export default class UserListContainer extends Component {
    //currentId用于记录当前用户的编号
    state={users:[],currentId:null}
    componentDidMount(){
        const users=[
            {id:"1001",name:"Jone"},
            {id:"1002",name:"Mali"},
            {id:"1003",name:"Locy"},
            {id:"1004",name:"Rose"},
            {id:"1005",name:"Jack"}
        ];
        this.setState({users:users});
    }

    //新添加用户
    onAddUser(username){
        //生成新的编号
        //let id=parseInt(this.state.users[this.state.users.length-1].id)+1;
        let id=this.state.users[this.state.users.length-1].id*1+1;
        //将添加的新用户
        const user={id,name:username};
        //将新用户添加到users状态中
        this.setState({users:this.state.users.concat(user),currentId:id});
    }

    //子组件通过该方法设置当前用户的编号
    onSetCurrentId=(id)=>{
        this.setState({currentId:id});
    }

  render() {
    //根据用户编号从用户集合中获取用户集合
    const users=this.state.users.filter(user => user.id === this.state.currentId);
    //当前用户
    let currentUser=null;
    //如果查找了
    if(users&&users.length>0){
        //设置当前用户
        currentUser=users[0];
    }
    return (
      <div>
        <h2>用户列表</h2>
        <UserListPro 
        users={this.state.users} 
        onAddUser={this.onAddUser.bind(this)}
        currentId={this.state.currentId}
        onSetCurrentId={this.onSetCurrentId}
        />
        <div>
            <UserDetail currentUser={currentUser}></UserDetail>
        </div>
      </div>
    )
  }
}

UserDetail.jsx

代码语言:javascript
复制
import React, { Component } from 'react'

export default class UserDetail extends Component {
  render() {
    return (
        this.props.currentUser?
      <div>
        <h2>用户详情</h2>
        <fieldset>
            <legend>详细</legend>
            <p>
                编号:{this.props.currentUser.id}
            </p>
            <p>
                姓名:{this.props.currentUser.name}
            </p>
        </fieldset>
      </div>
      :""
    )
  }
}

css/userListPro.css

代码语言:javascript
复制
.userDetail li{
    cursor: pointer;
}
.userDetail li:hover{
    background: lightyellow;
}
.active{
    background: lightyellow;
}

运行结果:

1.4、多级组件通信

当组件所处层级太深时,往往需要经过很层的props传递才能将所需的数据或者回调函数传递给使用组件,所以props作为桥梁通信便会显得很麻烦。React提供了一个context上下文,让任意层级的子组件都可以获取父组件中的状态和方法。

Parent.jsx 父

代码语言:javascript
复制
import React, { Component } from 'react'
import Sub1 from './Sub1';

export default class Parent extends Component {
    state={
        n:100
    }

    setN(n){
        this.setState({n});
    }

  render() {
    return (
     <div style={{backgroundColor:"lightblue"}}>
        <ul>
            <li>
            <div>
            <h2>父组件 n={this.state.n}</h2>
            </div>
            <Sub1 onSetN={this.setN.bind(this)}></Sub1>
            </li>
        </ul>
      </div>
    )
  }
}

Sub1.jsx 子

代码语言:javascript
复制
import React, { Component } from 'react'
import Sub11 from './Sub11';

export default class Sub1 extends Component {

   setNumber() {
        let n=parseInt(this.txtInput.value);
        this.props.onSetN(n);
    }
  render() {
    return (
      <div style={{background:"lightred"}}>
        <ul>
            <li>
            <h2>子组件:Sub1</h2>
            <p>
                <input ref={input=>this.txtInput=input} type="text" />
                <button onClick={this.setNumber.bind(this)}>设置N的值</button>
            </p>
            <Sub11 onSetN={this.props.onSetN}/>
            </li>
        </ul>
      </div>
    )
  }
}

Sub11.jsx 孙

代码语言:javascript
复制
import React, { Component } from 'react'

export default class Sub11 extends Component {

   setNumber() {
        let n=parseInt(this.txtInput.value);
        this.props.onSetN(n);
    }
  render() {
    return (
      <div style={{background:"lightred"}}>
        <ul>
          <li>
          <h2>孙组件:Sub11</h2>
          <p>
              <select ref={input=>this.txtInput=input} type="text">
                <option value={300}>300</option>
                <option value={600}>600</option>
                <option value={900}>900</option>
              </select>
              <button onClick={this.setNumber.bind(this)}>设置N的值</button>
          </p>
          </li>
        </ul>
      </div>
    )
  }
}

结果:

 解释:

1.5、Context

当组件所处层级太深时,往往需要经过很层的props传递才能将所需的数据或者回调函数传递给使用组件,所以props作为桥梁通信便会显得很麻烦。React提供了一个context上下文,让任意层级的子组件都可以获取父组件中的状态和方法。

每个组件都拥有context属性,可以查看到:

getChildContext:与访问context属性需要通过contextTypes指定可访问的属性一样,getChildContext指定的传递给子组件的属性需要先通过childContextTypes来执行,不然会报错。

使用context改进后的示例如下:

Parent.jsx 父

代码语言:javascript
复制
import React, { Component } from 'react'
import {PropTypes} from 'prop-types'
import Sub1 from './Sub1';

class Parent extends Component {
    state={
        n:100
    }

    setN=(n)=>{
        this.setState({n});
    }
    getChildContext(){
        return {onSetN: this.setN}
    }

  render() {
    return (
     <div style={{backgroundColor:"lightblue"}}>
        <ul>
            <li>
            <div>
            <h2>父组件 n={this.state.n}</h2>
            </div>
            <Sub1></Sub1>
            </li>
        </ul>
      </div>
    )
  }
}

//声明context的属性的类型信息
Parent.childContextTypes = {
    onSetN:PropTypes.func
}

export default Parent;

Sub1.jsx 子

代码语言:javascript
复制
import React, { Component } from 'react'
import Sub11 from './Sub11';
import {PropTypes} from 'prop-types'

class Sub1 extends Component {

   setNumber() {
        let n=parseInt(this.txtInput.value);
        this.context.onSetN(n);
    }
  render() {
    return (
      <div style={{background:"lightred"}}>
        <ul>
            <li>
            <h2>子组件:Sub1</h2>
            <p>
                <input ref={input=>this.txtInput=input} type="text" />
                <button onClick={this.setNumber.bind(this)}>设置N的值</button>
            </p>
            <Sub11/>
            </li>
        </ul>
      </div>
    )
  }
}
//声明要使用的context属性的类型信息
Sub1.contextTypes={
    onSetN: PropTypes.func
}

export default Sub1;

Sub11.jsx 孙

代码语言:javascript
复制
import React, { Component } from 'react'
import {PropTypes} from 'prop-types'

class Sub11 extends Component {

   setNumber() {
        let n=parseInt(this.txtInput.value);
        this.context.onSetN(n);
        console.log(this);
    }
  render() {
    return (
      <div style={{background:"lightred"}}>
        <ul>
          <li>
          <h2>孙组件:Sub11</h2>
          <p>
              <select ref={input=>this.txtInput=input} type="text">
                <option value={300}>300</option>
                <option value={600}>600</option>
                <option value={900}>900</option>
              </select>
              <button onClick={this.setNumber.bind(this)}>设置N的值</button>
          </p>
          </li>
        </ul>
      </div>
    )
  }
}

//声明要使用的context属性的类型信息
Sub11.contextTypes={
  onSetN: PropTypes.func
}

export default Sub11;

结果:

二、Hooks

 2.1、解构

1、数组解构就是能快速提取数组中的指定成员(数组的某一项值或所有的值)

例如:

解构赋值都是一一对应的,按照顺序。

代码语言:javascript
复制
const arr = [200,300,400]
const [a,b,c] = arr
console.log(a,b,c) // 200,300,400

也可以取数组的某一项值(结构必须保持一致)

代码语言:javascript
复制
const arr = [200,300,400]
const [, , c] = arr
console.log(c) // 400

还可在用“...”的方式提取所有的成员(注意的是这种...的写法只能在解构成员的最后一个成员使用)代码如下

代码语言:javascript
复制
const arr = [200,300,400]
const [a,...all] = arr
console.log(all) // [300,400] 会返回得到一个最后所有的数组

如果提取的解构成员小于数组的长度,就会从前到后的顺序来提取,代码如

代码语言:javascript
复制
const arr = [200,300,400]
const [a] = arr
console.log(a) // 200 按顺序提取第一个

如果提取成员大于数组长度,那么最后的提取的最后是undefined,代码如下

代码语言:javascript
复制
const arr = [200,300,400]
const [a,b,c,d] = arr
console.log(d) // undefined

2、对象解构和数组解构基本类似,只不过对象解构的取值方式是根据对象的属性名来取值

例如:

代码语言:javascript
复制
const obj = {name:'100',age:'30',size:'M'}
const { name } = obj
console.log(name) // 100

顺便说一下,对象里面的属性名和其他自定义的变量名称如果重名的时候要怎么解决,一旦重名就会报错,看代码:

代码语言:javascript
复制
const obj = {name:'100',age:'30',size:'M'}
const name = 'lucy'
const {name} = obj
console.log(name) // 会报错

// 要么重新命名,要么可以按照下面的写法来避免

代码语言:javascript
复制
const obj = {name:'100',age:'30',size:'M'}
const name = 'lucy'
const {name:nameObj} = obj // 对象属性名称的重新指定
console.log(nameObj) // 100

思考题:

请问下面的代码是什么意思?控制台输出什么?

代码语言:javascript
复制
    <script>
      function useBook() {
        return ["ES6高级编程", (bookname) => console.log(bookname + "!")];
      }
      const [name, showBook] = useBook();
      showBook(name);
    </script>

答案:

代码语言:javascript
复制
ES6高级编程!

 2.2、Hooks基础

Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state,一般搭配函数式组件使用。

在React 16.8之前,函数式组件只能作为无状态组件(只读组件),即不能进行状态管理。

函数式创建组件通常是无状态组件,这种方式没有办法在内部对状态统一管理,如果我们非要添加状态管理呢,那就只能借助redux啦~或者我们自己利用观察者模式实现一个发布订阅。

那么如果我们非要这么做,React版本在16.8.X以后增添了一个新特性就是hooks。

hooks涉及API有useState、 useEffect、 useCallback、 useRef、 useMemo、 React.memo、 useReducer等,具体可以参考官方文档。

2.2.1、useState() hooks状态钩子

搭配函数式组件,主要是可以进行组件的状态管理,好处是不像传统state需要注意this指向(函数式组件中没有this)。

一般用法 const [ a , setA ] = useState(初始值)

a表示组件需要声明的变量a,setA允许你在组件其它的位置对a的数据进行改变setA(2),即a的值将为2

一个组件中可以声明多个useState()

Counter3.jsx

代码语言:javascript
复制
import React,{useState} from 'react';
export default function Counter3(props){
    let [count,setCount]=useState(0);
    return (<div>
        <h2>{props.name}</h2>
        <p>
            <button onClick={()=>setCount(count+1)}>{count}</button>
        </p>
    </div>);
}

调用

代码语言:javascript
复制
const vnode = (
  <div>
    <Counter3 name="函数式组件使用状态的计数器" />
  </div>
);

结果:

三、Redux

四、Mobe

五、ref基础知识

不管在Vue中还是React,如果我们想使用一个元素的DOM,不需要通过JS中操纵DOM的方法,它们提供了一个专属的API就是ref。

而Vue中的ref可能比较简单,这一篇主要讲一下如何在React中使用ref,以及使用ref的场景。

5.1、ref的挂载

在React中,ref可以挂载到html元素上,同时也可以挂载在React元素上,看下面的代码:

代码语言:javascript
复制
import React, { Component } from 'react'
// import { findDOMNode } from 'react-dom'
import Child from './Child'

export default class Father extends Component {

  componentDidMount(){
    console.log(this.refs.refElement);
    console.log(this.refs.child);
  }

  render() {
    return (
      <div>
        <input ref={ 'refElement' }></input>
        <Child ref={ 'child' }/>
        <button onClick={this.fn}>123</button>
      </div>
    )
  }
}

控制台的打印为:

可以看到,在React中,ref是可以挂载到HTML元素和React元素上的。

(1)挂载HTML元素,返回真实的DOM

(2)挂载React元素,返回render后的实例对象

同时React也提供了一个方法findDOMNode可以将React元素的ref返回变成真实的DOM元素。

代码语言:javascript
复制
    import { findDOMNode } from 'react-dom'
    console.log(findDOMNode(this.refs.child));

同时在上面的代码我们也可以看出来,ref的挂载是在componentDidMount等生命周期之前执行的。

5.2、使用ref的三种方式

5.2.1、字符串的方式

代码语言:javascript
复制
import React, { Component } from 'react'

export default class Father extends Component {

  componentDidMount(){
    console.log(this.refs.refElement);
  }

  render() {
    return (
      <div>
        <input ref={ 'refElement' }></input>
        <button onClick={this.fn}>123</button>
      </div>
    )
  }
}

这种方式和Vue的ref比较相似,但是官方目前已经不推荐使用该方式,后续可能还会废弃。

5.2.2、函数的方式

代码语言:javascript
复制
import React, { Component } from 'react'

export default class Father extends Component {

  componentDidMount(){
    console.log(this.refElement);
  }

  render() {
    return (
      <div>
        <input ref={ ref => this.refElement = ref }></input>
        <button onClick={this.fn}>获取元素</button>
      </div>
    )
  }
}

5.2.3、react.CreateRef的方式

代码语言:javascript
复制
import React, { Component } from 'react'

export default class Father extends Component {

  refElement = React.createRef();

  componentDidMount(){
    console.log(this.refElement.current);
  }

  render() {
    return (
      <div>
        <input ref={this.refElement}></input>
        <button onClick={this.fn}>123</button>
      </div>
    )
  }
}

住这里面通过refElement中的current,获取真实的DOM元素。

六、作业

6.1、使用多种方法实现页面加载完成时让搜索文本框获取焦点,侧重练习ref的使用。

6.2、完成所有的上课示例。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2023-03-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、组件通信
    • 1.1、父传子
      • 1.2、子传父
        • 1.3、兄弟组件间通信
          • 1.4、多级组件通信
            • 1.5、Context
            • 二、Hooks
              •  2.1、解构
                •  2.2、Hooks基础
                • 三、Redux
                • 四、Mobe
                • 五、ref基础知识
                  • 5.1、ref的挂载
                    • 5.2、使用ref的三种方式
                      • 5.2.1、字符串的方式
                      • 5.2.2、函数的方式
                      • 5.2.3、react.CreateRef的方式
                  • 六、作业
                  相关产品与服务
                  消息队列 TDMQ
                  消息队列 TDMQ (Tencent Distributed Message Queue)是腾讯基于 Apache Pulsar 自研的一个云原生消息中间件系列,其中包含兼容Pulsar、RabbitMQ、RocketMQ 等协议的消息队列子产品,得益于其底层计算与存储分离的架构,TDMQ 具备良好的弹性伸缩以及故障恢复能力。
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档