当前位置: 首页 > news >正文

React(8)-组件ref

目录

1.组件form

受控组件及其特点

非受控组件及其特点

模拟:简单受控组件表单

        input两个方向绑定数据:

模拟:复杂(真实)受控组件表单(form里面有多种数据输入)

注意:handleChange1~5 中代码重复率高。

降低代码重复写法降低代码重复写法

模拟:非受控组件

受控组件形式自动时钟

非受控组件形式自动时钟

2.ref-函数类型实现

3.createRef实现

createRef实现自动化时钟

2.业务场景(登录)=>ref模拟form表单收集

三种非受控表单解决方式

方式一:ref="key"  原理:this.refs={} => this.refs={key:真实DOM}

方式二:ref={e=>this.key=e} =>直接赋值this.key=真实DOM

方式三:直接调用react提供的方法createRef();this.key=React.createRef()

事件绑定受控表单方式

3.业务衍生场景=>按钮触发事件

4.业务衍生场景=>表单自动获取焦点


1.组件form

受控组件及其特点

组件受状态和属性变化控制,称为受控组件。

特点:数据驱动,组件不直接操作DOM,而是由ReactDOM自动同步

非受控组件及其特点

组件不受状态和属性变化控制,称为非受控组件。

特点:可以直接操作DOM,类似于传统的html表单操作,通过ref获取真实DOM。

模拟:简单受控组件表单

(数据传递) =>数据源state+属性绑定value+事件监听onChange

class App extends React.Component{

        state = {name:"",age:18}

        handleClick = () ={

                console.log("form data:",this.state)

        }

        handleChange = (e) ={

                console.log(e.target.value) //获取到input输入内容

                this.setState({

                        name:e.target.value      

                })

        }

        input两个方向绑定数据:

        1.通过value,同步state=>input (属性绑定)

        2.通过onChange,同步input输入输入内容=>state  (事件绑定)

        render(){

                return(

                        <div>

                                name:

                                //受控组件收集表单

                                <input type:"text" value = {this.state.name} // input属性绑定

                                        onChange={this.handleCHange}> //input事件绑定

                                <button onClick={this.handleClick}>commit 提交</button>

                        </div>

                )

        }

}

ReactDOM.render(<App />,document.getElementById("app"))

模拟:复杂(真实)受控组件表单(form里面有多种数据输入)

class App extends React.Component{

        state = {

                name:"user",

                age:18,

                single:false,

                desc:"intoduction",

                hobby:"playing"

        }

        handleSubmit=()={

                //获取收集表单数据

                console.log("form data:",this.state)

                //提交数据

                //阻止默认行为

                e.preventDefault()

        }

        handleChange1 = (e) ={

                this.setState({

                        name:e.target.value

                })

        }

        handleChange2 = (e) ={

                this.setState({

                        age:e.target.value

                })

        }

        handleChange3 = (e) ={

                console.log(e.target.checked) //点击,在true和false之间来回切换

                //将表单中内容同步到数据中

                this.setState({

                        single:e.target.checked

                })

        }

        handleChange4 = (e) ={

                this.setState({

                        desc.target.value

                })

        }

        handleChange5 = (e) ={

                this.setState({

                        hobby:e.target.value

                })

        }

        render(){

                return(

                        <form onSubmit = {this.handleSubmit}>

                                name:

                                <input type:"text" value = {this.state.name} // input属性绑定

                                        onChange={this.handleChange1} /> //input事件绑定

                                age:

                                <input type:"number" value = {this.state.age

                                        onChange={this.handleChange2} /> 

                                single:

                                <input type:"checkbox" value = {this.state.single

                                        onChange={this.handleChange3} /> 

                                desc:

                                <textarea value = {this.state.desc}

                                        onChange={this.handleChange4}/>

                                hobby:

                                <select name:"" value={this.state.hobby}

                                        onChange={this.handleChange5}>

                                        <option value:"eatting">吃</option>

                                        <option value:"palying">玩</option>

                                        <option value:"sleeping">睡</option>

                                </select>

                                <input type="submit" value="commit" />

                        </form>

                )

        }

}

ReactDOM.render(<App />,document.getElementById("app"))

注意:handleChange1~5 中代码重复率高。

this.setState({key:value}),key动态,value:r.target.value,注意:e.target.checked不同

降低代码重复写法降低代码重复写法

class App extends React.Component{

        state = {

                name:"user",

                age:18,

                single:false,

                desc:"intoduction",

                hobby:"playing"

        }

        handleSubmit=()={

                //获取收集表单数据

                console.log("form data:",this.state)

                //提交数据

                //阻止默认行为

                e.preventDefault()

        }

        handleChange = (e) ={

                console.dir(e.target)

                let target = e.target

                let key = target.name

                //注意:checkedbox情况不同value = target.checked,追加判断

                let type = target.type

                let value = type==checkedbox?target.checked:target.value

                this.setState({

                       [key]:value //动态追加key

                })

        }

   

        render(){

                return(

                        <form onSubmit = {this.handleSubmit}>

                                name:

                                <input type:"text" name="name" 

                                        value = {this.state.name}

                                        onChange={this.handleChange} /> 

                                age:

                                <input type:"number" name="age" 

                                        value = {this.state.age

                                        onChange={this.handleChange} /> 

                                single:

                                <input type:"checkbox" name="single" 

                                        value = {this.state.single

                                        onChange={this.handleChange} /> 

                                desc:

                                <textarea name="desc" 

                                        value = {this.state.desc}

                                        onChange={this.handleChange}/>

                                hobby:

                                <select name:"hobby" value={this.state.hobby}

                                        onChange={this.handleChange}>

                                        <option value:"eatting">吃</option>

                                        <option value:"palying">玩</option>

                                        <option value:"sleeping">睡</option>

                                </select>

                                <input type="submit" value="commit" />

                        </form>

                )

        }

}

ReactDOM.render(<App />,document.getElementById("app"))

模拟:非受控组件

受控组件形式自动时钟

class Clock extends React.Components{

        state = {time:new Date().toLocalTimeString()}

        render(){

                return(

                        <div>

                                <h2>{this.state.time}</h2>

                        </div>

                )

        }

        componentDidMount(){ //第一次挂载完毕生命周期的钩子函数自动执行

                setInterval(()=>{

                        this.setState({

                                time:new Date().toLocalTimeString()

                        })

                },1000)

        }

}

ReactDOM.render(<Clock />,document.getElementById("app"))

非受控组件形式自动时钟

1.真实DOM容器ref-string类型实现

组件实例属性:this.ref = {},这个对象容器用来存储真实DOM的引用

class Clock extends React.Component{

        render(){

                return(

                        <div>

                                2.将真实DOM放在this.ref容器中

通过creatElement创建虚拟DOM,新增ref属性

通过ReactDOM.render同步渲染虚拟DOM=>真实DOM=>判断是否有ref属性

==>有ref:将ref属性对应的虚拟DOM转化成真实DOM=>放在this.ref={}容器中

[ 将ref属性对应的值作为key,将真实DOM作为value ]

                                <h2 ref="timeRef">{new Date().toLocalTimeString()}</h2>

                                //ref容器中存放:{timeRef:真实DOM<h2>}

                        </div>

                )

        }

        componentDidMount(){ //已经渲染完毕,可以拿到真实DOM

                console.log(this.refs

                setInterval(()=>{

                        3.this.ref中获取操作真实DOM=>给<h2>重新赋值

                        this.refs.timeRef.innerHTML = new Date().toLocaleTimeString()

                },1000)

        }

}

ReactDOM.render(<Clock />,document.getElementById("app"))

组件实例.refs = {key:真实DOM} ; key是ref属性对应的值

组件实例直接挂载key,组件实例.key=真实DOM => 自动化时钟

2.ref-函数类型实现

class Clock extends React.Component{

        render(){

                return(

                         <div>

                                2.将真实DOM放在this.ref容器中

通过creatElement创建虚拟DOM,新增ref属性

通过ReactDOM.render同步渲染虚拟DOM=>真实DOM=>判断是否有ref属性

==>有ref:ref属性对应的值是否是一个函数

==>是函数,直接执行这个函数,并将真实DOM作为参数传递。[组件实例.key=真实DOM]

                                <h2 ref = {e=>this.timeRef=e}>{new Dare().oLocaleTimeString()}</h2>

                                <h2 ref = {(element)=>{this.timeRef2=element}}>

                                        {new Date().toLocalTimeString()}

                        </div>       

                )

        }

        //组建挂载完毕:组件第一次渲染完毕执行=>虚拟DOM已经完全转化为真实DOM

        compomentDidMount(){

                console.loh(this)//组件实例

                console.loh(this.ref)//组件ref容器

                setInterval(()=>{

                        //this.key = 真实DOM{对应此处的<h2>标签}

                        this.refs.timeRef.innerHTML = new Date().toLoacleTimeString();

                        this.refs.timeRef.innerHTML = new Date().toLoacleTimeString();

                })

        }

}

ReactDOM.render(<Clock />,document.getElementById("app"))

3.createRef实现

React中creatRef源码:

//a immutable object(不可改变的对象) with single mutable value

function creatRef(){

        var refObject={

                current:null;

        };

        {

                Object.seal(refObject );

                //seal封装,对参数对象进行封闭,不能添加新的属性,只能有一个属性

        }

        return refObject;

}

注意:

执行React.creatRef()=>返回{ current:null }对象容器,但是这个返回值源码没有挂载到组件实例上.

所以我们需要进行手动挂载this.key = React.createRef()上

createRef实现自动化时钟

class Clock extends React.Component{

        constructor(props){

                super(props)

                this.timeRef=React.createRef() //{current:null}

        }

        render(){

                return(

                        <div>

通过createElement创建虚拟DOM,新增ref属性,

ReactDOM.render把虚拟DOM同步渲染成真实DOM=>判断是否有ref存在

如果有ref,会把ref对应的值,即{current:null}容器,将真实DOM<h2>赋值给容器current属性

和2的区别:

不需要给引用容器提供key

                                <h2 ref={e=>}>{new Date().toLocalTimeString()}</h2>

                        </div>

                )

        }

        componentDidMount(){

                console.log(this)

                console.log(this.ref)

                setInterval(()=>{

                        //this.key.current=真实DOM<h2>

                        this.timeRef,current.innerHTML = new Date().toLocalTimeString()

                },1000)

        }

}

2.业务场景(登录)=>ref模拟form表单收集

三种非受控表单解决方式

方式一:ref="key"  原理:this.refs={} => this.refs={key:真实DOM}

方式二:ref={e=>this.key=e} =>直接赋值this.key=真实DOM

方式三:直接调用react提供的方法createRef();this.key=React.createRef():{current:nulll}=>{current:真实DOM}

方式一:ref="key"  原理:this.refs={} => this.refs={key:真实DOM}

class Form extends React.Component{

        console.log(this)

        console.log(this.refs.inputRef) //真实DOM

        console.log(this.refs.inputRef.value)

        render(){

                return(

                        <div>

                                <input type="text" ref="inputRef" />

                                <button onClick={this.handleClick}>commit</button>

                        </div>

                )

        }

}

方式二:ref={e=>this.key=e} =>直接赋值this.key=真实DOM

 class Form extends React.Component{

        console.log(this.inputRef2) //真实DOM

         console.log(this.inputRef2.value) //获取input输入内容

        render(){

                return(

                        <div>

                                <input type="text" ref={e=>this.inputRefs2=e}/>

                                <button onClick={this.handleClick}>commit</button>

                        </div>

                )

        }

}

方式三:直接调用react提供的方法createRef();this.key=React.createRef()

 class Form extends React.Component{

        console.log(this.inputRef3) //非真实DOM,是个对象容器

         console.log(this.inputRef3.current) //真实DOM

         console.log(this.inputRef3.current.value) //获取input输入内容

        constructor(){

                super()

                this.inputRef3=React.createRef()

        }

        render(){

                return(

                        <div>

                                <input type="text" ref={this.inputRefs3}/>

                                <button onClick={this.handleClick}>commit</button>

                        </div>

                )

        }

}

事件绑定受控表单方式

  class Form extends React.Component{

        handleChange=>(e)=>{

                console.log("onChange") //input输入框中每输入一个触发一次onChange

                console.log(e.targrt.value)

        }

        render(){

                return(

                        <div>

                                <input type="text" onChange={this.handleChange}/>

                                <button onClick={this.handleClick}>commit</button>

                        </div>

                )

        }

}

3.业务衍生场景=>按钮触发事件

class Form extends React.Component{

        constructor(){

                super();

                this.inputRef = React.createRef()

        }

        handleClick=()=>{

                alert( this.inputRef.current.value)

        }

       handleBlur=(e)={

                console.log(e.target) //真实DOM

                console.log(e.target.value) //输入框内容

                 alert(e.target.value);

        }

        render(){

                return(

                        <div>

                                <input type="text" onBlur={this.handleBlur}/>

                                <input type="text" ref={this.inputRef}/>

                                <button onClick={this.handleClick}>commit</button>

                        </div>

                )

        }

}

ReactDOM.render(<Form />,document.getElementById("app"))

4.业务衍生场景=>表单自动获取焦点

class Form extends React.Component{

        constructor(){

                super();

                this.inputRef = React.createRef()

        }

        handleClick=()=>{

                this.inputRef.current.focus() 

        }

        render(){

                return(

                        <div>

                                <input type="text" ref={this.inputRef}/>

                                <button onClick={this.handleClick}>commit</button>

                        </div>

                )

        }

        //已经渲染完毕,可以直接直接使用真实DOM

        componentDidMount(){

                this.inputRef.current.focus()

        }

}

ReactDOM.render(<Form />,document.getElementById("app"))

相关文章:

  • 2022/8/30
  • picoCTF - Day 1 - Warm up
  • 前端面试题之组件
  • 自己动手写编译器:词法解析的系统化研究
  • 【程序员面试金典】01.02. 判定是否互为字符重排
  • go实现剑指offer
  • 【Go-Lua】Golang嵌入Lua代码——gopher-lua
  • yolov5+shufflenet轻量化目标检测
  • 【BurpSuite】插件开发学习之J2EEScan(上)-被动扫描
  • java计算机毕业设计企业公开招聘系统源码+数据库+系统+lw文档+mybatis+运行部署
  • 赛事开源Baseline参考目录格式
  • C++设计模式之Bridge桥模式
  • Kibana-8.4.0-Linux安装
  • @hook扩展分析
  • 利用 zabbix 监控服务端口
  • echarts的各种常用效果展示
  • es6
  • Facebook AccountKit 接入的坑点
  • HTML5新特性总结
  • js中的正则表达式入门
  • JWT究竟是什么呢?
  • magento 货币换算
  • mysql 数据库四种事务隔离级别
  • PaddlePaddle-GitHub的正确打开姿势
  • React-生命周期杂记
  • Spark RDD学习: aggregate函数
  • 彻底搞懂浏览器Event-loop
  • 机器学习 vs. 深度学习
  • 基于 Ueditor 的现代化编辑器 Neditor 1.5.4 发布
  • 如何使用 OAuth 2.0 将 LinkedIn 集成入 iOS 应用
  • 什么软件可以剪辑音乐?
  • 使用putty远程连接linux
  • 使用前端开发工具包WijmoJS - 创建自定义DropDownTree控件(包含源代码)
  • ionic入门之数据绑定显示-1
  • 回归生活:清理微信公众号
  • # Python csv、xlsx、json、二进制(MP3) 文件读写基本使用
  • #NOIP 2014# day.2 T2 寻找道路
  • $.ajax()
  • (2)关于RabbitMq 的 Topic Exchange 主题交换机
  • (2009.11版)《网络管理员考试 考前冲刺预测卷及考点解析》复习重点
  • (java版)排序算法----【冒泡,选择,插入,希尔,快速排序,归并排序,基数排序】超详细~~
  • (附源码)ssm基于jsp的在线点餐系统 毕业设计 111016
  • (推荐)叮当——中文语音对话机器人
  • (原)Matlab的svmtrain和svmclassify
  • (转) 深度模型优化性能 调参
  • 、写入Shellcode到注册表上线
  • .aanva
  • .equal()和==的区别 怎样判断字符串为空问题: Illegal invoke-super to void nio.file.AccessDeniedException
  • .NET Core SkiaSharp 替代 System.Drawing.Common 的一些用法
  • .NET Core 将实体类转换为 SQL(ORM 映射)
  • .NET 材料检测系统崩溃分析
  • .net 简单实现MD5
  • .net(C#)中String.Format如何使用
  • /dev下添加设备节点的方法步骤(通过device_create)
  • /etc/sudoers (root权限管理)