【React】三.React组件基础学习

news2024/11/16 21:44:50

目录

React组件介绍

React组件的两种创建方式

使用函数创建组件

函数组件

渲染函数组件

示例

使用类创建组件

抽离为独立的JS文件

步骤

 问题记录

React事件处理

事件绑定

记录问题 

事件对象

有状态组件和无状态组件

无状态组件(木偶组件)特点

有状态组件的特点

组件中的state和setState()

state的基本使用

setState()修改状态

事件绑定this指向

1.箭头函数

2.Function.prototype.bind()

3.class的实例方法

 总结

表单处理

受控组件

步骤

 多个受控组件的实例

多表单元素优化步骤

非受控组件

使用步骤

总结


React组件介绍

  • 组件化是React的核心思想
  • 组件可以实现页面中的部分功能
  • 组合多个组件可以实现完整的页面功能 
  • 特点:可复用、独立、可组合

React组件的两种创建方式

使用函数创建组件

函数组件

    使用JS的函数(或箭头函数)创建的组件

        约定1:函数名称必须以大写字母开头

        约定2:函数组件必须有返回值,表示该组件的结构。如果不需要返回内容需要写返回null

渲染函数组件

    用函数名作为组件标签名

    组件渲染可以是单标签也可以是双标签

示例

function Hello() {
    return (
        <div>这是我的第一个函数组件!</div>
    )
}
ReactDOM.render(<Hello/>,document.getElementById('component'))

 在新的js文件中写入代码,在index.js导入新建的js文件,在index.html中添加id为component的div,将函数组件渲染到component节点上。

使用类创建组件

 类组件:使用ES6的class创建的组件

        约定1:类名称也必须以大写字母开头

        约定2:类组件应该继承React.Component父类,从而可以使用父类中提供的方法或者属性

        约定3:类组件必须提供render()方法

        约定4:render()方法必须有返回值,表示该组件的结构

class Hello extends React.Component{
    render() {
        return (
        <div>这是我的第一个类组件,哈哈哈哈</div>
    )
    }
}
    

ReactDOM.render(<Hello/>,document.getElementById('component2'))

抽离为独立的JS文件

多个组件存在时,一般都会放到一个单独的JS文件中 

步骤

  1. 创建Demo.js
  2. 在Demo.js中导入React
  3. 创建组件(函数或类)
  4. 在Demo.js中导出该组件
  5. 在index.js中导入Hello组件

 Demo.js

//创建文件
// 导入React
import React from 'react'
// 创建组件
class Demo extends React.Component{
    render() {
        return<div> Hello Class Component!</div>
    }
}
// 导出组件
export default Demo

index.js

//导入Demo组件
import Demo from './2抽离为独立的js文件'

// 渲染导入的组件
ReactDOM.render(<Demo/>,document.getElementById('export-component'))

 问题记录

在Demo.js中一开始我导入了

import React from 'react'

import ReactDOM from 'react-dom'

 之后按照步骤去抽离js文件,结果出现报错和警告,报错是

Parsing error: Identifier 'React' has already been declared.

解析错误,标识符React已经被声明,就是重复导入就会出现解析报错

删除第一行之后

(警告)'ReactDOM' is defined but never used 

就是没有使用就不用导入了抽离js并没有在本脚本中渲染组件所以用不着reactdom。

React事件处理

事件绑定

React事件绑定语法与DOM事件语法相似

语法:on+事件名称={事件处理程序},比如onClick={()=>{}}

注意:React事件采用驼峰命名法,比如:onMouseEnter,onFocus

import React from 'react'

import ReactDOM from 'react-dom'
class App extends React.Component{
    handleClick() {
        console.log('单击事件触发了')
    }
    render() {
        return (
            <button onClick={this.handleClick}>点我</button>
        )
    }
}
// 渲染组件
ReactDOM.render(<App/>, document.getElementById('shijianbangding'));

不要忘记在index.html创建渲染到的目标(某个div)     index.js 引入本js脚本

// 通过函数组件绑定事件
function App() {
    function handleClick() {
        console.log('通过函数组件绑定函数,单击事件触发了')
    }
    return (
        <button onClick={handleClick}>点我</button>
    )
}

记录问题 

在函数组件中绑定事件中

// 通过函数组件绑定事件

function App() {

    function handleClick() {

        console.log('通过函数组件绑定函数,单击事件触发了')

    }

    return (

        <button onClick={this.handleClick}>点我</button>

    )

}

 Line 17:14:  'handleClick' is defined but never used  

事件对象

可以通过事件处理程序的参数获取到事件对象

React中的事件对象叫做合成事件(对象)

合成事件:兼容所有浏览器,无需担心跨浏览器兼容性问题

import React from 'react'

import ReactDOM from 'react-dom'

class App extends React.Component{

    handleClick(e) {

        //阻止浏览器的默认行为

        e.preventDefault()

        console.log('a标签的单击事件触发了')

    }

    render() {

        return (

            <a href='http://www.baidu.com' onClick={this.handleClick}>百度</a>

        )

    }

}

//渲染组件

ReactDOM.render(<App/>,document.getElementById('shijianduixiang'))

有状态组件和无状态组件

函数组件又叫做无状态组件,类组件又叫做有状态组件

状态(state)即数据

函数组件、无状态组件、展示型组件主要关注UI的展示;

类组件、有状态组件、容器型组件主要关注数据逻辑;

在适合的情况下,我们都应该且必须使用无状态组件。无状态组件不像其他两种方法在调用时会创建新实例,它创建时始终保持了一个实例,避免了不必要的检查和内存分配,做到了内部优化。——摘自《深入 React 技术栈》

无状态组件(木偶组件)特点

  • 不能参与组件的各个生命周期的管理
  • 不能被实例化

有状态组件的特点

  • 用来处理数据或者页面逻辑交互
  • 类组件可以维护自身的状态变量,即组件的state 
  • 有状态组件组件还有不同的生命周期方法,可以让开发者能够在组件的不同阶段(挂载、更新、卸载),对组件做更多的控制。 

参考文献

浅析React有状态组件和无状态组件 - 简书 (jianshu.com)

组件中的state和setState()

state的基本使用

状态(state)即数据,是组件内部的私有数据,只能在组件内部使用

state的值是对象,表示一个组件中可以有多个数据

import React from 'react'

import ReactDOM from 'react-dom'

class App extends React.Component{
    //constructor() {
        //super()//ES6要求

        //初始化state
        // this.state = {
        //     count:2023
        // }
    //}
    
        // 简化语法
     state = {
        count:2023
    }

    render() {
        return (
            <div>
                <h1>计数器:{ this.state.count}</h1>
            </div>
        )
    }
}

// 渲染组件
ReactDOM.render(<App/>,document.getElementById('state'))

显示结果 

初始化state

   constructor() {
       super()//ES6要求
        //初始化state
        this.state = {
             count:2023
         }

 

根据ES6简化语法(推荐)

  state = {
        count:2023
    }

setState()修改状态

  • 状态是可变的
  • 语法:this.setState({要修改的数据})
  • 注意:不要直接修改state中的值
  • 作用:1.修改state  2.更新UI
    render() {
        return (
            <div>
                <h1>计数器:{this.state.count}</h1>
                <button onClick={() => {
                    this.setState({
                        count:this.state.count+1
                    })
                }}>+1</button>
            </div>
        )
    }

 JSX中掺杂过多JS逻辑代码,非常混乱,因此,把逻辑代码抽离到单独的方法中,保证JSX结构清晰。

记录问题

   //事件处理程序
    onIncrement() {
        console.log('事件处理程序中的this:', this);
        this.setState({
            count:this.state.count+1
        })
    }

    render() {
        return (
            <div>
                <h1>计数器:{this.state.count}</h1>
                <button onClick={this.onIncrement}>+1</button>
            </div>
        )
    }

原因:事件处理程序中的this值是undefined

希望:this指向组件实例(render方法中的this即为组件实例)

 改正后的代码在下一节

事件绑定this指向

1.箭头函数

利用箭头函数自身不绑定this的特点

render()方法中的this为组件实例,可以获取到setState()

import React from 'react'

import ReactDOM from 'react-dom'

class Arrow extends React.Component{

     state = {

        count:2023

    }

   

    //事件处理程序

    onIncrement1() {

        console.log('事件处理程序中的this:', this);

        this.setState({

            count:this.state.count+1

        })

    }

    render() {

        return (

            <div>

                <h1>计数器:{this.state.count}</h1>

                <button onClick={()=>this.onIncrement1()}>+1</button>

            </div>

        )

    }

}

// 渲染组件

ReactDOM.render(<Arrow/>,document.getElementById('jiantou'))

在改bug的时候,没有任何报错,button无效,最后发现是onIncrement方法没有写(),😓

2.Function.prototype.bind()

利用ES5中的bind方法,将事件处理程序中的this与组件实例绑定到一起

   constructor() {

        super()

        this.onIncrement=this.onIncrement.bind(this)

    }

import React from 'react'

import ReactDOM from 'react-dom'

class Bind extends React.Component{

     state = {
        count:2023
    }
    
    constructor() {
        super()
        this.onIncrement=this.onIncrement.bind(this)
    }
    //事件处理程序
    onIncrement() {
        console.log('事件处理程序中的this:', this);
        this.setState({
            count:this.state.count+1
        })
    }

    render() {
        return (
            <div>
                <h1>计数器:{this.state.count}</h1>
                <button onClick={this.onIncrement}>bind+1</button>
            </div>
        )
    }
}

// 渲染组件
ReactDOM.render(<Bind/>,document.getElementById('bind'))

3.class的实例方法

利用箭头函数形式的class实例方法

注意:该语法是实验性语法,但是,由于babel的存在可以直接使用

    //事件处理程序
    onIncrement=() =>{
        console.log('事件处理程序中的this:', this);
        this.setState({
            count:this.state.count+1
        })
    }

 总结

1.推荐使用class的实例方法

class Hello extends React.Component{
    onIncrement = () => {
        this.setState({……})
    }
}


2.箭头函数
 

  < button onClick = {()=> this.inCrement()}/>

3.bind

constructor(){
    super()
    this.onIncrement=this.onIncrement.bind(this)
}

表单处理

受控组件

html中的表单元素是可输入的,有自己的可变状态

react的可变状态通常保存在state中,并且只能通过setState()方法来修改

React将state与表单元素值value绑定到一起,由state的值来控制表单元素的值

<input type="text"  value={this.state.txt}  />

步骤

1.给state中添加一个状态,作为表单元素的value值(控制表单元素值的来源)

2.给表单元素绑定change事件,将表单元素的值设置为state的值(控制表单元素值的变化)

class App extends React.Component{
    state = {
        txt:''
    }

    handleChange = e => {
        this.setState({
            txt:e.target.value
        })
    }
    
    render() {
        return (
            <div>
                <input type='text'value={this.state.txt} onChange={this.handleChange}></input>
            </div>
        )
    }
}

 多个受控组件的实例

import React from 'react'

import ReactDOM from 'react-dom'

class App extends React.Component{
    state = {
        txt: '',
        content: '',
        city: 'sh',
        isChecked:false
    }
// 处理文本框的变化
    handleChange = e => {
        this.setState({
            txt:e.target.value
        })
    }
    // 处理富文本框的变化
    handleContent = e => {
        this.setState({
            content:e.target.value
        })
    }
    // 处理下拉框的变化
    handleCity = e => {
        this.setState({
            
        })
    }
    render() {
        return (
            <div>
                {/* 文本框 */}
                <input type='text'value={this.state.txt} onChange={this.handleChange}></input>
                <br />
                {/* 富文本框 */}
                <textarea value={this.state.content} onChange={this.handleContent}></textarea>
                <br />
                {/* 下拉框 */}
                <select value={this.state.city} onChange={this.handleCity}>
                    <option value="sh">上海</option>
                    <option value="bj">北京</option>
                    <option value="gz">广州</option>
                </select>
                <br />
                {/* 复选框 */}
                <input type="checkbox"></input>
            </div>
            
        )
    }
}
//渲染组件
ReactDOM.render(<App/>,document.getElementById('biaodan2'))

多表单元素优化步骤

1.给表单元素添加name属性,名称和state相同

 <input type='text' name='txt' value={this.state.txt} onChange={this.handleChange}></input>

2.根据表单元素获取对应值

        // 根据表单元素类型获取值

            const value = target.type === 'checkbox'

                ? target.checked

                : target.value

       

            //根据name设置对应state

            this.setState({

                [name]:value

            })

 3.在change事件处理程序中通过[name]来修改对应的state

 handleForm = e => {
        //获取当前DOM 对象
        const target = e.target
        
        //根据类型获取值
        const value = target.type === 'checkedbox'
            ? target.checked
            : target.value
        //获取name
        const name = target.name
        
        this.setState({
            //中括号是动态获取,因为name值不同
            [name]:value
        })
    }
    render() {
        return (
            <div>
                {/* 文本框 */}
                <input type='text' name='txt' value={this.state.txt} onChange={this.handleForm}></input>
                <br />
                {/* 富文本框 */}
                <textarea  value={this.state.content} onChange={this.handleForm}></textarea>
                <br />
                {/* 下拉框 */}
                <select value={this.state.city} onChange={this.handleForm}>
                    <option value="sh">上海</option>
                    <option value="bj">北京</option>
                    <option value="gz">广州</option>
                </select>
                <br />
                {/* 复选框 */}
                <input  name='isChecked' type="checkbox" checked={this.state.isChecked} onChange={this.handleForm}></input>
            </div>
    
        )
    }

非受控组件

使用步骤

1.调用React.createRef()方法创建一个ref对象

constructor(){

    super()

    this.txtRef=React.createRef()

}

2.将创建好的ref对象添加到文本框中

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

3.通过ref对象获取到文本框的值

console.log(this.txtRef.current.value) 

import React from 'react'

import ReactDOM from 'react-dom'

class App extends React.Component{
    constructor() {
        super()
        // 创建ref
        this.txtRef=React.createRef()
    }
    // 获取文本框的值
    getTxt = () => {
        console.log('文本框的值为:', this.txtRef.current.value);
    }
    render() {
        return (
            <div>
                <input type="text" ref={this.txtRef} />
                <button onClick={this.getTxt}>获取到文本框的值</button>
            </div>
        )
    }
}
//渲染组件
ReactDOM.render(<App />, document.getElementById('biaodan3'))

 React一般不直接操作DOM,所以非受控组件并不常用

总结

  1. 组件的两种创建方式:函数组件和类组件
  2. 无状态(函数)组件,负责静态结构展示
  3. 有状态(类)组件,负责更新UI
  4. 绑定事件注意this指向的问题
  5. 推荐使用受控组件来处理表单 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/170684.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

XSS(Cross Site Scripting)攻击简介

环境 Ubuntu 22.04IntelliJ IDEA 2022.1.3JDK 17.0.3.1Spring Boot 3.0.1Firefox 108.0.2 问题和分析 在IntelliJ IDEA中创建Spring Boot项目 test0116 &#xff0c;并选中 Spring Web 依赖。 在 src/main/java 下创建 MyController.java 如下&#xff1a; package com.ex…

Redis缓冲区不会还有人不知道吧?

1 简介 缓冲区&#xff0c;用一块内存空间暂时存放命令数据&#xff0c;以免因 数据和命令的处理速度&#xff1c;发送速度而导致数据丢失和性能问题。但缓冲区的内存空间有限&#xff0c;若持续&#xff1a; 往里写数据速度&#xff1e;从里读数据速度会导致缓冲区需越来越…

ATGM332D-5N卫星导航模块介绍

ATGM332D-5N卫星导航模块简介ATGM332D-5N系列模块是12X16 尺寸的高性能BDS/GNSS 全星座定位导航模块系列的总称。该系列模块产品都是基于中科微第四代低功耗GNSS SOC单芯片—AT6558&#xff0c;支持多种卫星导航系统&#xff0c;包括中国的BDS&#xff08;北斗卫星导航系统&…

BFS的入门与应用

目录 一、前言 二、BFS原理 二、BFS与最短路径 1、最短路径问题用BFS 2、迷宫&#xff08;2019年省赛&#xff0c;填空题&#xff0c;lanqiaoOJ题号602&#xff09; &#xff08;1&#xff09;字典序最小的最短路径 &#xff08;2&#xff09;输出路径的两种方法 三、B…

拉伯证券|今年首批游戏版号发放,机构看好春节行业景气度恢复

2023年第一批游戏版号发放。 昨日晚间&#xff0c;国家新闻出版署发布1月国产网络游戏审批信息&#xff0c;共88款游戏获批&#xff0c;其我国内各大游戏龙头均有所收成&#xff0c;包含腾讯《黎明觉悟&#xff1a;活力》、网易《逆水寒》&#xff08;移动版&#xff09;、完美…

数据治理:数据治理之道-组织机制-敏捷的治理组织

参考《一本书讲透数据治理》、《数据治理》等 组织机制&#xff1a;敏捷的治理组织 数据、组织、软件平台&#xff0c;是企业数字化转型面临的三座大山 数据&#xff1a;数据是企业数字化转型的根本驱动力之一&#xff0c;数字化转型中的企业必须做好数据治理与应用&#xff…

8Manage:分散的软件正在扼杀公司的生产力

在企业领域&#xff0c;数字化不仅仅是指工具能力&#xff0c;而是指用户如何很好地应用他们的知识来做决策&#xff0c;培养关系&#xff0c;建立声誉&#xff0c;以及动员同事、团队。几十年来&#xff0c;企业已经部署了生产力、搜索和协作平台&#xff0c;以提高员工和业务…

使用 tslib 库

tslib 是专门为触摸屏设备所开发的 Linux 应用层函数库&#xff0c;并且是开源。tslib 为触摸屏驱动和应用层之间的适配层&#xff0c; 它把应用程序中读取触摸屏 struct input_event 类型数据&#xff08;这是输入设备上报给应用层的原始数据&#xff09;并进行解析的操作过程…

ceres学习笔记(三)

学习了example中pose_graph_3d的部分&#xff0c;记录一下学习过程。 前言&#xff1a; 翻译一下readme里面的内容&#xff1a; ... 该示例还说明了如何将 Eigen 的几何模块与 Ceres 的自动微分功能结合使用。 为了表示方向&#xff0c;我们将使用 Eigen 的四元数&#xff…

测试开发 | Pytest 结合 Allure 生成测试报告

本文节选自霍格沃玆测试学院测试开发内部教材&#xff0c;进阶学习文末加群&#xff01; 测试报告在项目中是至关重要的角色&#xff0c;一个好的测试报告&#xff1a; 可以体现测试人员的工作量&#xff1b; 开发人员可以从测试报告中了解缺陷的情况&#xff1b; 测试经理可…

锂电产业如何利用视觉检测系统降本增效?

导语&#xff1a;机器视觉检测已在锂电池生产的各个环节中&#xff0c;为产品产量与质量提供可靠保障。维视智造作为锂电池视觉检测系统提供商&#xff0c;为企业提供专业、系统、稳定的锂电行业解决方案&#xff0c;可保证0漏检&#xff0c;确保安全生产&#xff0c;全面提升生…

炫酷 RGB 之.NET nanoFramework 点灯大师

前面介绍了 .NET nanoFramework 入门&#xff0c;本文继续以微雪的 ESP32-S2-Pico 为例介绍 .NET nanoFramework 的开发&#xff1a;控制 ESP32 板载 RGB 灯 和 外接 RGB 灯。内容包含 状态灯的意义、WS2812 、HSV、PWM 等相关知识。 文章目录1. 背景2. 状态灯的意义3. 板载 LE…

萌新如何使用printf函数?

&#x1f40e;作者的话 如果你搜索输入输出函数&#xff0c;那么你会看到输入输出流、Turbo标准库、标准输出端、stdout什么什么乱七八糟的&#xff0c;作为一个萌新&#xff0c;哪懂这些&#xff1f; 本文介绍萌新在前期的学习中&#xff0c;常用的输入输出函数及其功能~ 跳跃…

ROS2机器人编程简述humble-第二章-Controlling the Iterative Execution .3.1

2.3 ANALYZING THE BR2 BASICS PACKAGE 这一节内容有些多……前一篇&#xff1a;ROS2机器人编程简述humble-第二章-DEVELOPING THE FIRST NODE .2里面只有节点&#xff0c;没有任何实际功能。logger.cpp代码如下所示&#xff1a;#include "rclcpp/rclcpp.hpp"using n…

微信小程序分享的图片被裁切了。怎么让他不裁剪正常比例5:4显示

现在的效果 希望的效果 最主要的是下面的这个函数。把图片转成了5:4的临时图片 cutShareImg(doctorImg:string ){let thatthis;return new Promise((resolve) > {wx.getImageInfo({src: doctorImg, // 这里填写网络图片路径 success: (res) > {var data resconsole.l…

使用 LibreOffice 将 word 转化为 pdf 并解决中文乱码问题

目录 一、安装 LibreOffice 二、解决乱码问题 2.1 查看是否安装中文字体 2.2 准备字体 2.3 导入字体 2.4 验证 项目中有一个在线上传 word 并预览 pdf 报告的需求&#xff0c;因为项目部署在 ubuntu 上面&#xff0c;所以借助libreoffice 实现 word 转 pdf&#xff0c;然…

详细实例说明+典型案例实现 对枚举法进行全面分析 | C++

第五章 枚举法 目录 ●第五章 枚举法 ●前言 1.简要介绍 2.代码及结果示例&#xff08;简单理解&#xff09; 3.生活实例 ●二、枚举法的典型案例——鸡兔同笼&质数求解 1.鸡兔同笼 2.质数求解&#xff08;枚举法&#xff09; ●总结 前言 简单的来说…

最新 vue-cli 构建项目

vue-cli 构建项目 当前使用最新版本构建一个vue node项目 插件 vue-clivueelement-plusroutervuex 安装vue-cli npm install -g vue-cli安装完后 vue --version 查看版本 vue --version创建一个项目 vue create demo这里要选择版本&#xff0c;不同版本要相组合配置的插件…

反射的基本使用

文章目录1. 一个需求引出反射2. 反射机制2.1 Java Reflection2.2 Java 反射机制可以完成2.3 反射相关的主要类2.4 反射优点和缺点2.5 反射调用优化-关闭访问检查3. Class类3.1 基本介绍3.2 Class类的常用方法3.3 获取Class类对象3.4 哪些类型有Class对象3.5 类加载3.6 类加载流…

aws imagebuilder 理解并使用imagebuilder构建pcluster自定义ami

参考资料 ec2-image-builder-workshop Troubleshoot EC2 Image Builder 理解imagebuilder imagebuilder 使用 cinc-client 进行客户端统一配置&#xff0c;CINC is not Chef&#xff0c;而是chef的免费分发版本。 https://cinc.sh/about/ imagebuilder管道的整体逻辑如下 核…