P17:React高级-ref 的用法和 ref 中的坑

Posted wgchen~

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P17:React高级-ref 的用法和 ref 中的坑相关的知识,希望对你有一定的参考价值。

阐述

在编写组件中的方法时,经常会遇到语义化很模糊的代码,这对于团队开发是一个很大的问题。因为 review 代码或者合作时都会影响开发效率。或者核心成员离开,项目倒闭的严重影响。所以我们必须重视react代码当中的语义化。

ref 是个不错的工具,快来学习一下吧。

代替原来的 e.target.value

以前的案例中,我们写了下面的代码,使用了 e.target,这并不直观,也不好看。这种情况我们可以使用 ref 来进行解决。

inputChange(e)
    this.setState(
        inputValue:e.target.value
    )

如果要使用 ref 来进行,需要先在JSX中进行绑定, 绑定时最好使用ES6语法中的箭头函数,这样可以简洁明了的绑定DOM元素。

<input 
    id="willem" 
    className="input" 
    value=this.state.inputValue 
    onChange=this.inputChange.bind(this)
    //关键代码——----------start
    ref=(input)=>this.input=input
    //关键代码------------end
    />

绑定后可以把上边的类改写成如下代码:

inputChange()
    this.setState(
        inputValue:this.input.value
    )

这就使我们的代码变得语义化和优雅的多。

但是就我个人的经验来讲,我是不建议用 ref 这样操作的,因为React的是数据驱动的,所以用 ref 会出现各种问题。

import React,Component,Fragment  from 'react'
import BeautyItem from './BeautyItem'

class Beauty extends Component
//js的构造函数,由于其他任何函数执行
constructor(props)
    super(props) //调用父类的构造函数,固定写法
    this.state=
        inputValue:'' , // input中的值
        list:['基础按摩','精油推背']    //服务列表
    


render()
    return  (
        <Fragment>
            /* 正确注释的写法 */
            <div>
                <label htmlFor="willem">加入服务:</label>
                <input 
                id="willem" 
                className="input" 
                value=this.state.inputValue 
                onChange=this.inputChange.bind(this)
                //关键代码——----------start
                ref=(input)=>this.input=input
                //关键代码------------end
                />
                <button onClick=this.addList.bind(this)> 增加服务 </button>
            </div>
            <ul>
                
                    this.state.list.map((item,index)=>
                        return (
                            <BeautyItem 
                            key=index+item  
                            content=item
                            index=index
                            deleteItem=this.deleteItem.bind(this)
                            />
                        )
                    )
                
            </ul>
        </Fragment>
    )


    // inputChange(e)
    //     // console.log(e.target.value);
    //     // this.state.inputValue=e.target.value;
    //     this.setState(
    //         inputValue:e.target.value
    //     )
    // 

    inputChange()
        console.log(this.input.value);
        this.setState(
            inputValue:this.input.value
        )
    
    
    //增加服务的按钮响应方法
    addList()
        this.setState(
            list:[...this.state.list,this.state.inputValue],
            inputValue:''
        )

    
   //删除单项服务
   deleteItem(index)
    let list = this.state.list
    list.splice(index,1)
    this.setState(
        list:list
    )



export default Beauty

ref 使用中的坑

比如现在我们要用 ref 绑定取得要服务的数量,可以先用 ref 进行绑定。

<ul ref=(ul)=>this.ul=ul>
    
        this.state.list.map((item,index)=>
            return (
                <BeautyItem 
                key=index+item  
                content=item
                index=index
                deleteItem=this.deleteItem.bind(this)
                />
            )
        )
    
</ul>

绑定后可以在 addList() 方法中,获取当前 <li> 的值.

ddList()
    this.setState(
        list:[...this.state.list,this.state.inputValue],
        inputValue:''
    )
    //关键代码--------------start
    console.log(this.ul.querySelectorAll('li').length)
    //关键代码--------------end

这时候你打开控制台,点击添加服务按钮,你会发现数量怎么少一个?
(就是这个坑)如下图,


其实这个坑是因为React中更多 setState 是一个异步函数所造成的。

也就是这个 setState,代码执行是有一个时间的,如果你真的想了解清楚,你需要对什么是虚拟DOM有一个了解。简单的说,就是因为是异步,还没等虚拟Dom渲染,我们的console.log就已经执行了。

那这个代码怎么编写才会完全正常那,其实setState方法提供了一个回调函数,也就是它的第二个函数。

下面这样写就可以实现我们想要的方法了。

addList()
    this.setState(
        list:[...this.state.list,this.state.inputValue],
        inputValue:''
        //关键代码--------------start
    ,()=>
        console.log(this.ul.querySelectorAll('li').length)
    )
    //关键代码--------------end

现在到浏览器中查看代码,就完全正常了。

总结

本文主要学习了 ref 的用法和 ref 中的坑。
学完后练习一下吧,代码这东西,不练习你是学不会的。

以上是关于P17:React高级-ref 的用法和 ref 中的坑的主要内容,如果未能解决你的问题,请参考以下文章

Ref用法

vue中ref($refs)用法和作用

c#中的ref用法

vue里ref ($refs)用法

Vue里ref ($refs)用法

Vue里ref ($refs)用法