React入门(二)之有(无)状态组件

本文详细介绍了React中的事件处理,包括无状态组件和有状态组件的区别,事件处理的特点,如事件语法、事件对象的获取以及如何阻止浏览器默认行为。此外,还探讨了如何在组件中使用refs进行DOM操作,并提供了不同方式解决事件处理函数中this的问题。
摘要由CSDN通过智能技术生成

一、无状态组件

无状态组件就是组件内部没有(或不需要)state,无状态组件也可以理解为展示组件,仅做展示用。

函数组件其实就是无状态组件。

<script src="../js/react.js"></script>
<script src="../js/react-dom.js"></script>
<script src="../js/babel.min.js"></script>
<script type="text/babel">

//函数组件(就是无状态组件) ,内部没有state
function Vie(props){
    return (
        <div>
            <p>
                姓名:{props.name}
            </p>
            <p>
                年龄:{props.age}
            </p>
            <p>
                评价:{props.desc}
            </p>
        </div>
    )
}

let obj = {
    name:'晓晓',
    age:19,
    desc:'努力刻苦又善良!'
}

ReactDOM.render(
   <Vie {...obj}></Vie>,
    document.getElementById('box')
)

</script>

就是这么简单!

二、有状态组件

有状态组件就是不但外部可以传入props,内部也可以有state。

有状态组件也可以理解为容器组件,用来容纳展示组件,在容器组件里处理数据的逻辑,把结果在展示组件里呈现。

//有状态组件(容器组件)  内部有state,还可以外部传入props
class Viv extends React.Component{
    constructor(){
        super();
        this.state = {
           desc:'个人信息'
        }
    }
    render=()=>{
        return (
            <div>
                <h2>{this.state.desc}</h2>
                {/* 容纳展示组件 */}
                <Vie {...obj}></Vie>
            </div>
        )
    }
}

 //无状态组件  内部没有state
 function Vie(props){
    return (
        <div>
            <p>
                姓名:{props.name}
            </p>
            <p>
                年龄:{props.age}
            </p>
            <p>
                评价:{props.desc}
            </p>
        </div>
    )
}

let obj = {
    name:'晓晓',
    age:19,
    desc:'努力刻苦又善良!'
}

ReactDOM.render(
   <Viv {...obj}></Viv>,
    document.getElementById('box')
)

三、事件处理

3.1、特点

在此之前,我们先看看react事件的特点

1、React 事件绑定属性的命名采用驼峰式写法,而不是小写。如:onClick。

<input type="button" onClick={fn}/>//此处onClick,驼峰命名法

2、如果采用 JSX 的语法你需要传入一个函数作为事件处理函数,而不是一个字符串(DOM 元素的写法)

<input type="button" onClick={fn}/>//此处不加引号
  • 错误示例:
<input type="button" onClick="fn"/>

3、在 React 中另一个不同是你不能使用return false 的方式阻止默认行为, 你必须明确的使用 preventDefault。

change(ev){
    ev.preventDefault()//不用return false
}

4、事件处理函数里的this是undefined(啊………),如果希望事件处理函数里的this是React组件对象本身,则需要用bind。

change(){
//事件处理函数
    console.log('事件函数里的this:',this);//undefined
}

3.2、事件语法

3.2.1、格式

<JSX元素 onClick={this.实例方法|函数体}  />
<input type="button" value="测试01" onClick={this.fn01} />
<input type="button" value="测试02" onClick={()=>{console.log("事件绑定箭头函数")}} />

3.2.2、事件处理函数里的this问题

我们已经知道,react事件函数里的this是undefined,那么怎么才能让事件函数里的this指向React组件对象本身

提供了以下几种方案,我将一一演示;

1)、使用bind

  • 在构造函数里写
this.方法=this.方法.bind(this)  
class Viv extends React.Component{
    constructor(){
        super();
        //将此处的this绑定到change事件函数,bind()方法会返回
        //一个新的函数对象(改变了this指向的change函数)
        this.change2 = this.change.bind(this)
    }

    change(){
        console.log('事件函数里的this:',this);
    }

    render=()=>{
        return (
            <div>
            {/* 在绑定事件时绑定改变this指向后的change函数 */}
               <input type="button" value="点击触发事件2" 
               onClick={this.change2}/>
            </div>
        )
    }
}

注意:以上代码还可以写成:

class Viv extends React.Component{
        constructor(){
            super();
            //将此处的this绑定到change事件函数,bind()方法会返回
            //一个新的函数对象(改变了this指向的change函数)
            this.change = this.change.bind(this)
        }

        change(){
            console.log('事件函数里的this:',this);
        }

        render=()=>{
            return (
                <div>
                   <input type="button" value="点击触发事件2" onClick={this.change}/>

                </div>
            )
        }
    }

细心的朋友应该发现了,

this.change2 = this.change.bind(this)

还可以写成:

this.change = this.change.bind(this)

既然会返回一个新的函数对象,为何不直接用原函数接收呢?相当于重新赋值了。

控制台运行结果:

在这里插入图片描述

  • 在事件绑定时写
onClick={this.方法.bind(this)}
class Viv extends React.Component{
     constructor(){
         super();
     }

     change(){
         console.log('事件函数里的this:',this);
     }

     render=()=>{
         return (
             <div>
             {/* 此处直接使用bind */}
                <input type="button" value="点击触发事件4" 
                onClick={this.change.bind(this)}/>
             </div>
         )
     }
}

2)、使用箭头函数

  • 事件绑定时使用
onClick={()=>this.方法()}
class Viv extends React.Component{
    constructor(){
        super();
    }

    change(){
        console.log('事件函数里的this:',this);
    }

    render=()=>{
        return (
            <div>
    {/* 
    		这里注意:箭头函数内部this.change()带括号的,
            因为此处绑定事件函数是把外部的箭头函数作为
            事件处理函数绑定的,当点击触发事件则会
            执行内部的this.change()执行change函数. 				
	*/}
               <input type="button" value="点击触发事件5" 
               onClick={()=>this.change()}/>
            </div>
        )
    }
}
  • 定义方法时,直接使用
方法=()=>{箭头函数定义方法}  //这个方法可能是最简单的
class Viv extends React.Component{
    constructor(){
        super();
    }

    change=()=>{
    /*
	    其他地方都不需要改,只需要把绑定的
	    事件函数写成箭头函数的形式就ok
    */
        console.log('事件函数里的this:',this);
    }

    render=()=>{
        return (
            <div> 
               <input type="button" value="点击触发事件6" 
               onClick={this.change}/>
            </div>
        )
    }
}

3.3、事件对象

在学习原生js时我们就已经学习过事件对象,react里的事件对象是经过react处理过的。

那么如何获取呢?

1)、直接声明(没有其它参数的情况下

class Viv extends React.Component{
    constructor(){
        super();
    }

    change=(ev)=>{
        console.log('事件对象:',ev);
    }

    render=()=>{
        return (
            <div>
               <input type="button" value="点击触发事件" 
               onClick={this.change}/>
            </div>
        )
    }
}

打印事件对象结果:

在这里插入图片描述
注意:形参ev的名字任意,但最好是event缩写或首字母。

2)、箭头函数里直接声明(有其它参数的情况下

class Viv extends React.Component{
    constructor(){
        super();
    }

    change(ev,str){
        console.log('事件对象:',ev);
        console.log('str:',str);
    }

    render=()=>{
        return (
            <div>
               <input type="button" value="点击触发事件" onClick={(ev)=>this.change(ev,'hello')}/>
            </div>
        )
    }
}

打印结果:

在这里插入图片描述
此处有个坑,看你跳不跳:(需要注意)

1,当执行以下代码时,onClick绑定的是外部的箭头函数,那么事件处理函数就是这个箭头函数,而不再是change函数了。

<input type="button" value="点击触发事件" 
onClick={(ev)=>this.change(ev,'hello')}/>

2,所以,要获取事件对象其实是获取箭头函数的事件对象,即ev,当点击按钮时执行change函数,将ev和str作为实参传给change函数。
3,在change函数内部,接收并打印这两个传来的值。

给事件属性绑定的函数,永远只会有一个参数,该参数就是事件对象。

3.4、阻止浏览器的默认行为

只能用preventDefault,不能在事件函数里使用return false

四、组件的内容

组件的内容,使用 props.children属性获取。

function Mve(props){
    return (
        <div>
            <p>组件内容:{props.children}</p>
        </div>
    )
}

ReactDOM.render(
   <Mve>我是组件的内容</Mve>,
    document.getElementById('box')
)

五、refs

用来获取DOM的,和vue里的refs类似。

表示对组件真正实例(也就是html标签,也就是DOM对象)的引用,其实就是ReactDOM.render()返回的组件实例;ref可以写在html标签里,也可以写在组件(自定义标签里)

但是,尽量不要操作DOM。

使用:

1)赋值为字符串(官方不推荐使用)

  <input type="text" ref="username" />
 
   this.refs.username.value

2)赋值为回调函数

​ 当给 HTML 元素添加 ref 属性时,ref 回调接收了底层的 DOM 元素作为参数。

​ ref 回调会在componentDidMount 或 componentDidUpdate 这些生命周期回调之前执行。

//ref的值赋成回调函数时,回调的参数就是当前dom元素。
// callback refs  回调

<jsx ref={el => this.定义一个实例属性 = el} //el就是dom对象
    
    
this.定义一个实例属性 //后期用作访问jsx元素
//当组件挂载时,将 DOM el元素传递给 ref 的回调
//当组件卸载时,则会传递 null。
//ref 回调会在 componentDidMount 和 componentDidUpdate 生命周期之前调用
    
    如:
  <input type="text" ref={(currDom) => this.input1  = currDom} />
  <input type="text" ref={(currDom) => this.input2 = currDom} />

3)React.createRef() (React16.3提供)

​ 使用此方法来创建ref。将其赋值给一个变量,通过ref挂载在dom节点或组件上,该ref的current属性将能拿到dom节点或组件的实例

//1、在构造函数里
// 实例化
this.firstRef = React.createRef() //发生在构造器

//2、挂载在ref属性上
<jsx ref={this.firstRef} />
    
//3、获取dom原始
this.firstRef.current //current是官方的属性
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值