react-组件基础

1.目标

能够使用函数创建组件
能够使用class创建组件
能够给React元素绑定事件
能够使用state和setState()
能够处理事件中的this指向问题
能够使用受控组件方式处理表单

2.目录

React组件介绍
React组件的两种创建方式
React事件处理
有状态组件和无状态组件
组件中的state和setState()
事件绑定this指向
表单处理

3.react组件介绍

组件是React的一等公民,使用React就是在用组件
组件表示页面中的部分功能
组合多个组件实现完整的页面功能
特点:可复用、独立、可组合

4.react组件的两种创建方式

A. 使用函数创建组件
B. 使用类创建组件

4.1 使用函数创建组件

A. 函数组件:使用JS的函数(或箭头函数)创建的组件
B. 约定1:函数名称必须以大写字母开头
C. 约定2:函数组件必须有返回值,表示该组件的结构
D. 如果返回值为null,表示不渲染任何内容

function Hello(){
return (
<div>这是我的第一个函数组件</div>
)
}

A. 渲染函数组件:用函数名作为组件标签名
B. 组件标签可以是单标签也可以是双标签

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

4.2 使用类创建组件

A. 类组件:使用ES6的class创建的组件
B. 约定1:类名称也必须以大写字母开头
C. 约定2:类组件必须继承React.Component父类,从而可以使用父类中提供的方法或属性
D. 约定3:类组件必须提供render()方法
E. 约定4:render()方法必须有返回值,表示该组件的结构

class Hello1 extends React.Component{
render(){
return (
<div>
我是一个类组件
</div>
)
}
}
ReactDOM.render(<Hello1 />,document.getElementById('root'))

4.3 抽离为单独JS文件

A. 思考:项目中的组件多了之后,该如何组织这些组件呢?
B. 选择一:将所有组件放在同一个JS文件中
C. 选择二:将每个组件放到单独的JS文件中
D. 组件作为一个独立的个体,一般都会放到一个单独的JS文件中
E. 抽离步骤:
\1. 创建Hello.js
\2. 在Hello.js中导入React
\3. 创建组件(函数或类)
\4. 在Hello.js中导出该组件
\5. 在index.js中导入Hello组件
\6. 渲染组件
在这里插入图片描述

5.React事件处理

\1. 事件绑定
\2. 事件对象

5.1 事件绑定

A. React事件绑定语法与DM事件语法相似
B. 语法:on+事件名称=[事件处理程序],比如:onClick={()=>{}}
C. 注意:React事件采取驼峰命名法,比如:onMouseEnter、onFocus
D. 在函数组件绑定事件:
Index.js(函数事件绑定)

// 函数组件事件绑定
function Hello() {
  function clickHandle() {
    console.log("函数事件触发了");
  }
  return <button onClick={clickHandle}>点击触发函数事件</button>;
}

ReactDOM.createRoot(document.getElementById("root")).render(<Hello></Hello>);

index.js(类事件绑定)

// 类事件绑定
class Hello2 extends React.Component {
  clickHandle() {
    console.log("类事件触发了");
  }
  render() {
    return <button onClick={this.clickHandle}>点击触发类事件</button>;
  }
}

ReactDOM.createRoot(document.getElementById("root")).render(<Hello2></Hello2>);

区别:
在这里插入图片描述

5.2 事件对象

A. 可以通过事件处理程序的参数获取到事件对象
B. React中的事件对象叫做:合成事件(对象)
C. 合成事件:兼容所有浏览器,无需担心跨浏览器兼容性问题

// 事件对象
class App extends React.Component {
  clickHandel(e) {
    // 阻止浏览器默认行为
    e.preventDefault();
    console.log("点击事件触发了");
  }
  render() {
    return (
      <a href="https://www.baidu.com" onClick={this.clickHandel}>
        百度
      </a>
    );
  }
}

ReactDOM.createRoot(document.getElementById("root")).render(<App></App>);

6.有状态组件和无状态组件

A. 函数组件又叫做无状态组件,类组件又叫做有状态组件
B. 状态(state)即数据
C. 函数组件没有自己的状态,只负责数据展示(静)
D. 类组件有自己的状态,负责更新UI,让页面”动”起来
比如计算器案例中,点击按钮让数值加1。0和1就是不同时刻的状态,而由0变为1就表示状态发生了变
化。状态变化后,UI也要相应的更新。React中想要实现该功能,就要使用有状态组件来完成。
在这里插入图片描述

7.组件中的state和setState

A. state的基本使用
B. setState()修改状态

7.1 state的基本使用

A. 状态(state)即数据,是组件内部的私有数据,只能在组件内部使用
B. state的值是对象,表示一个组件中可以有多个数据
C. 状态即数据
D. 状态是私有的,只能在组件内部使用
E. 通过this.state来获取状态

// 有状态组件
class Hello3 extends React.Component {
  constructor() {
    super(); // 必须写
  }
  state = {
    count: 0,
  };
  render() {
    return (
      <div>
        有状态组件
        <h1>计数器:{this.state.count}</h1>
      </div>
    );
  }
}

ReactDOM.createRoot(document.getElementById("root")).render(<Hello3></Hello3>);

7.2 setState()修改状态

A. 状态是可变的
B. 语法:this.setState({要修改的数据})
C. 注意:不要直接修改state中的值,这是错误的!!!!
D. setState()作用:1.修改state 2.更新UI
E. 思想:数据驱动视图

// 有状态组件
class Hello3 extends React.Component {
  constructor() {
    super(); // 必须写
  }
  state = {
    count: 0,
  };
  render() {
    return (
      <div>
        有状态组件
        <h1>计数器:{this.state.count}</h1>
        <button
          onClick={() => {
            this.setState({ count: this.state.count + 1 });
          }}
        >
          +1
        </button>
      </div>
    );
  }
}

ReactDOM.createRoot(document.getElementById("root")).render(<Hello3></Hello3>);

7.3 从JSX中抽离事件处理程序

A. JSX中掺杂过多JS逻辑代码,会显得非常混乱
B. 推荐:将逻辑抽离到单据的方法中,保证JSX结构清晰
在这里插入图片描述
在这里插入图片描述

// 有状态组件
class Hello3 extends React.Component {
  constructor() {
    super(); // 必须写
  }
  state = {
    count: 0,
  };
  onIncrement() { 
    console.log(this, "抽离出来的this");
    this.setState({
      count: this.state.count + 2,
    });
  }
  render() {
    return (
      <div>
        有状态组件
        <h1>计数器:{this.state.count}</h1>
        <button
          onClick={() => {
            console.log(this, "函数式事件触发的this");
            this.setState({ count: this.state.count + 1 });
          }}
        >
          +1
        </button>
        <button onClick={this.onIncrement}>+2</button>
      </div>
    );
  }
}

ReactDOM.createRoot(document.getElementById("root")).render(<Hello3></Hello3>);

A. 原因:事件处理程序中this的值为undefined—抽离出来的方法用箭头函数可解决
B. 希望:this指向组件实例(render方法中的this即为组件实例)
把state放在,构造函数里面

8.事件绑定this指向

A. 抽离出的事件处理函数使用箭头函数
B. Function.prototype.bind() 【在构造函数中使用.bind(this)来绑定this上下文】
C. 在render方法中使用箭头函数来调用onIncrement,但这样每次渲染都会创建一个新的函数,可能会影响性能

8.1 箭头函数

A. 利用箭头函数自身不绑定this的特点
B. Render()方法中的this为组件实例,可以获取到setState()
在这里插入图片描述

8.2 在构造函数中使用.bind(this)来绑定this上下文–Function.prototype.bind()

在这里插入图片描述

8.3 在render方法中使用箭头函数来调用onIncrement,但这样每次渲染都会创建一个新的函数,可能会影响性能

<button onClick={() => this.onIncrement()}>+2</button>

9.表单处理

\1. 受控组件
\2. 非受控组件(DOM方式)

9.1 受控组件

A. HTML中的表单元素是可输入的,也就是有自己的可变状态
B. 而,React中可变状态通常保存在state,并且只能通过setState()方法来修改
C.React将state与表单元素值value绑定到一起,由state的值来控制表单元素的值
D. 受控组件:其值受到React控制的表单元素
E. 步骤
\1. 在state中添加一个状态,作为表单元素的value值(控制表单元素值的来源)
\2. 给表单元素绑定change事件,将表单元素的值设置为state的值(控制表单元素值的变化)

class Hello4 extends React.Component {
  constructor() {
    super();
    this.state = {
      txt: "默认值",
    };
  }
  inputHandle = (e) => {
    this.setState({
      txt: e.target.value,
    });
  };
  render() {
    return (
      <div>
        文本的值:{this.state.txt}
        <br />
        <input
          type="text"
          value={this.state.txt}
          onChange={this.inputHandle}
        ></input>
      </div>
    );
  }
}

ReactDOM.createRoot(document.getElementById("root")).render(<Hello4></Hello4>);

示例:
A.文本框、富文本框、下拉框
B.复选框

class Hello4 extends React.Component {
  constructor() {
    super();
    this.state = {
      txt: "默认值",
      content: "",
      city: "zj",
      isChecked: true,
    };
  }
  handleChange1 = (e) => {
    this.setState({
      txt: e.target.value,
    });
  };
  handleChange2 = (e) => {
    this.setState({
      content: e.target.value,
    });
  };
  handleChange3 = (e) => {
    this.setState({
      city: e.target.value,
    });
  };
  handleChange4 = (e) => {
    console.log(e, "e4");
    this.setState({
      isChecked: e.target.checked,
    });
  };
  render() {
    return (
      <div>
        {/* 输入框 */}
        文本的值:{this.state.txt}
        <input
          type="text"
          value={this.state.txt}
          onChange={this.handleChange1}
        ></input>
        <br />
        {/* 文本框 */}
        文本框的值:{this.state.content}
        <textarea
          value={this.state.content}
          onChange={this.handleChange2}
        ></textarea>
        <br />
        {/* 下拉框 */}
        下拉框的值:{this.state.city}
        <select value={this.state.city} onChange={this.handleChange3}>
          <option value="zj">浙江</option>
          <option value="js">江苏</option>
          <option value="sh">上海</option>
          <option value="bj">北京</option>
        </select>
        <br />
        {/* 复选框 */}
        复选框的值:{this.state.isChecked}
        <input
          type="checkbox"
          checked={this.state.isChecked}
          onChange={this.handleChange4}
        ></input>
      </div>
    );
  }
}

ReactDOM.createRoot(document.getElementById("root")).render(<Hello4></Hello4>);

9.1.1 多表单元素优化

A. 问题:每个表单元素都有一个单独的事件处理程序处理太繁琐
B. 优化:使用一个事件处理程序同时处理多个表单元素

9.1.2 多表单元素优化步骤

A. 给表单元素添加name属性,名称与state相同
B. 根据表单元素类型获取对应值
C. 在change事件处理程序中通过[name]来修改对应的state

class Hello4 extends React.Component {
  constructor() {
    super();
    this.state = {
      txt: "默认值",
      content: "",
      city: "zj",
      isChecked: true,
    };
  }
  handleForm = (e) => {
    const value =
      e.target.type === "checkbox" ? e.target.checked : e.target.value;
    this.setState({
      [e.target.name]: value,
    });
  };
  render() {
    return (
      <div>
        {/* 输入框 */}
        文本的值:{this.state.txt}
        <input
          type="text"
          name="txt"
          value={this.state.txt}
          onChange={this.handleForm}
        ></input>
        <br />
        {/* 文本框 */}
        文本框的值:{this.state.content}
        <textarea
          name="content"
          value={this.state.content}
          onChange={this.handleForm}
        ></textarea>
        <br />
        {/* 下拉框 */}
        下拉框的值:{this.state.city}
        <select value={this.state.city} name="city" onChange={this.handleForm}>
          <option value="zj">浙江</option>
          <option value="js">江苏</option>
          <option value="sh">上海</option>
          <option value="bj">北京</option>
        </select>
        <br />
        {/* 复选框 */}
        复选框的值:{this.state.isChecked}
        <input
          type="checkbox"
          name="isChecked"
          checked={this.state.isChecked}
          onChange={this.handleForm}
        ></input>
      </div>
    );
  }
}

ReactDOM.createRoot(document.getElementById("root")).render(<Hello4></Hello4>);

9.2 非受控组件

A. 说明:借助于ref,使用原生DOM方法来获取表单元素值
B. ref的作用:获取DOM或组件
C. 使用步骤:

  1. 调用React.createRef()方法创建一个ref对象
  2. 将创建好的ref对象添加到文本框中
  3. 通过ref对象获取到文本框的值
class Hello6 extends React.Component {
  constructor() {
    super();
    // 创建Ref
    this.textRef = React.createRef();
  }
  getText = () => {
    console.log(this.textRef);
    console.log(this.textRef.current.value);
  };
  render() {
    return (
      <div>
        <input type="text" ref={this.textRef}></input>
        <button onClick={this.getText}>获取文本框的值</button>
      </div>
    );
  }
}
ReactDOM.createRoot(document.getElementById("root")).render(<Hello6></Hello6>);

10.react组件基础-案例评论列表

index.js

class Comment extends React.Component {
  constructor() {
    super();
    // 初始化值
      this.state = {
      userName: "",
      userContent: "",
      comments: [
        { id: 1, name: "周可可", content: "大家好,我是周可可~~" },
        { id: 2, name: "周嫑嫑", content: "每没有人能欺负周可可!!!" },
        { id: 3, name: "周深", content: "大家好,我是周深~~" },
        { id: 4, name: "周浅", content: "大家好,我是周浅~~" },
      ],
    };
  }
  // 数据展示
  renderList = () => {
    return this.state.comments.length == 0 ? (
      <div>暂无评论,快去发布吧~</div>
    ) : (
      <div>
        <ul className="contentDetailBox">
          {this.state.comments.map((item) => (
            <li key={item.id}>
              评论人:{item.name}
              <br />
              评论内容:{item.content}
            </li>
          ))}
        </ul>
      </div>
    );
  };
  // 数据响应式
  changeForm = (e) => {
    const { name, value } = e.target;
    this.setState({
      [name]: value,
    });
  };
  // 添加
  addComment = () => {
    let { userName, userContent, comments } = this.state;
    // 非空校验
    if (userName.trim() == "" || userContent.trim() == "") {
      return alert("用户名或评论内容不能为空!");
    }
    const newComments = [
      {
        id: comments.length > 0 ? comments.length + 1 : 1,
        name: userName,
        content: userContent,
      },
      ...comments,
    ];
    console.log(newComments, "newComments");
    this.setState({ comments: newComments });
    // 清空数据
    this.state.userName = "";
    this.state.userContent = "";
  };
  render() {
    const { userName, userContent } = this.state;
    return (
      <div>
        <div className="appp">
          <h1>评论</h1>
          <div>
            <input
              name="userName"
              placeholder="请输入评论人"
              className="userIpt"
              value={userName}
              onChange={this.changeForm}
            ></input>
          </div>
          <br />
          <div style={{ marginBottom: "10px" }}>
            <textarea
              name="userContent"
              placeholder="请输入评论内容"
              rows={10}
              cols={50}
              className="contentTextarea"
              value={userContent}
              onChange={this.changeForm}
            ></textarea>
          </div>
          <button onClick={this.addComment}>发布评论</button>
          <div>
            <h2 style={{ textAlign: "center" }}>评论详情</h2>
            {this.renderList()}
          </div>
        </div>
      </div>
    );
  }
}

ReactDOM.createRoot(document.getElementById("root")).render(
  <Comment></Comment>
);

index.css

.appp {
  width: 35%;
  height: 700px;
  border: 1px solid gray;
  padding-left: 50px;
}

.appp h1 {
  text-align: center;
}

.userIpt {
  width: 40%;
}

.contentDetailBox {
  height: 300px;
  overflow-y: scroll;
}

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

新加坡服务器托管:开启全球化发展之门

新加坡作为一个小国家&#xff0c;却在全球范围内享有极高的声誉。新加坡作为亚洲的科技中心&#xff0c;拥有先进的通信基础设施和成熟的机房托管市场。除了其独特的地理位置和发达的经济体系外&#xff0c;新加坡还以其开放的商业环境和便利的托管服务吸引着越来越多的国际公…

排序算法--堆排序

堆排序的时间复杂度是O&#xff08;N*logN&#xff09;&#xff0c;优于选择排序O&#xff08;N^2&#xff09; 一、堆 1.堆的概念&#xff1a;堆一般指的是二叉堆&#xff0c;顾名思义&#xff0c;二叉堆是完全二叉树或者近似完全二 2.堆的性质&#xff1a;①完全二叉树 ②每…

UE5 C++ 单播 多播代理 动态多播代理

一. 代理机制&#xff0c;代理也叫做委托&#xff0c;其作用就是提供一种消息机制。 发送方 &#xff0c;接收方 分别叫做 触发点和执行点。就是软件中的观察者模式的原理。 创建一个C Actor作为练习 二.单播代理 创建一个C Actor MyDeligateActor作为练习 在MyDeligateAc…

智慧餐饮系统架构的设计与实现

随着科技的不断发展&#xff0c;智慧餐饮系统在餐饮行业中扮演着越来越重要的角色。智慧餐饮系统整合了信息技术&#xff0c;以提高餐饮企业的管理效率、客户服务质量和市场竞争力。本文将探讨智慧餐饮系统架构的设计与实现&#xff0c;并探讨其在餐饮行业中的应用前景。 架构…

2024年2月国内如何快速注册OnlyFans最新小白教学

前言 onlyface软件是一个创立于2016年的订阅式社交媒体平台&#xff0c;创作者可以在自己的账号发布原创的照片或视频&#xff0c;并将其设置成付费模式&#xff0c;若用户想查看则需要每月交费订阅。 需要注意的是&#xff0c;网络上可能存在非法或不道德的应用程序&#xff…

k8s1.23.15集群二进制部署

一、前言 二进制部署1.23.15版本k8s集群&#xff0c;etcd集群部署与k8s集群节点复用&#xff0c;手动颁发集群证书 主机信息如下 主机名称ip地址服务k8s-master0110.1.60.125docker、etcd、kube-apiserver、kube-schduler、kube-controller-manage、kubelet、kube-proxyk8s-no…

Unity(第十部)时间函数和文件函数

时间函数 using System.Collections; using System.Collections.Generic; using UnityEngine;public class game : MonoBehaviour {// Start is called before the first frame updatefloat timer 0;void Start(){//游戏开始到现在所花的时间Debug.Log(Time.time);//时间缩放值…

AI不离谱,大语言模型ChatMusician可以理解曲谱生成AI音乐

虽然大型语言模型在文本生成AI音乐方面已经表现得相当出色&#xff0c;但它们在音乐这一人类创造性领域的表现却还有待提高。然而&#xff0c;近日推出的ChatMusician打破了这一局面&#xff0c;成为了一个集成了内在音乐能力的开源大型语言模型。 ChatMusician论文地址&#x…

【JSON2WEB】06 JSON2WEB前端框架搭建

【JSON2WEB】01 WEB管理信息系统架构设计 【JSON2WEB】02 JSON2WEB初步UI设计 【JSON2WEB】03 go的模板包html/template的使用 【JSON2WEB】04 amis低代码前端框架介绍 【JSON2WEB】05 前端开发三件套 HTML CSS JavaScript 速成 前端技术路线太多了&#xff0c;知识点更多&…

【C语言】学生宿舍信息管理系统

目录 项目说明 1. 数据结构设计 2. 功能实现 3. 主菜单设计 4. 文件操作 5. 系统使用 项目展示 1.主菜单功能界面 ​编辑 2.添加信息 3.查询信息 4.修改信息 5.删除信息 6.退出程序 项目完整代码 结语 在这篇博客中&#xff0c;我们将探讨如何使用C语言来开发…

斯元Z-ONE-China Cybersecurity Tech Landscape·中国网络安全全景图-百度网盘下载

面向全球&#xff0c;斯元Z-ONE正式发布首版「China Cybersecurity Tech Landscape中国网络安全全景图」。 为了提升海外市场对中国网络安全行业的全局认识&#xff0c;方便国际客户及合作伙伴了解中国网络安全科技的赛道分布和国内外厂商对标&#xff0c;助力中国网安厂商出海…

java springmvc/springboot 项目通过HttpServletRequest对象获取请求体body工具类

请求 测试接口 获取到的 获取到打印出的json字符串里有空格这些&#xff0c;在json解析的时候正常解析为json对象了。 工具类代码 import lombok.extern.slf4j.Slf4j; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.we…

FL Studio 21.2.3.3586 for Mac中文版新功能介绍及2024年最新更新日志

如果你正计划学习音乐制作&#xff0c;一款强大且易学的音乐制作软件是必不可少的。由于很多小伙伴对音乐制作软件没有实际体验过&#xff0c;到底选择哪一款软件最合适成为当下最纠结的问题。 这里为大家推荐一款功能强大且适合新手小伙伴的音乐编曲软件—FL Studio 21.2.3.35…

雾锁王国服务器配置怎么选择?阿里云和腾讯云

雾锁王国/Enshrouded服务器CPU内存配置如何选择&#xff1f;阿里云服务器网aliyunfuwuqi.com建议选择8核32G配置&#xff0c;支持4人玩家畅玩&#xff0c;自带10M公网带宽&#xff0c;1个月90元&#xff0c;3个月271元&#xff0c;幻兽帕鲁服务器申请页面 https://t.aliyun.com…

MySQL数据库下载及安装教程

MySQL数据库下载及安装教程 一、MySQL数据库下载及安装教程1.MySQL数据库下载1.1 MySQL官网1.2 MySQL官网下载页&#xff08;表面上的&#xff09;1.3 MySQL官网下载页&#xff08;真正的下载地址&#xff09;1.4 下载教程 2.MySQL数据库安装教程2.1 MySQL数据库安装版配置安装…

腾讯云4核8G服务器支持多少人在线访问?

腾讯云4核8G服务器支持多少人在线访问&#xff1f;支持25人同时访问。实际上程序效率不同支持人数在线人数不同&#xff0c;公网带宽也是影响4核8G服务器并发数的一大因素&#xff0c;假设公网带宽太小&#xff0c;流量直接卡在入口&#xff0c;4核8G配置的CPU内存也会造成计算…

C++:回调函数的应用

本文关于回调函数的学习的学习资料都来自于这里。 原文写得非常详细&#xff0c;所以将原文的大部分内容作为笔记摘抄了过来。 文章目录 1.回调函数1.1普通函数作为回调函数1.2类的静态函数作为回调函数1.3类的非静态成员函数作为回调函数1.4优化--非静态包装为静态 2. std::f…

【ArcGIS】重采样栅格像元匹配问题:不同空间分辨率栅格数据统一

重采样栅格像元匹配问题&#xff1a;不同空间分辨率栅格数据统一 原始数据数据1&#xff1a;GDP分布数据2.1&#xff1a;人口密度数据2.2&#xff1a;人口总数数据3&#xff1a;土地利用类型 数据处理操作1&#xff1a;将人口密度数据投影至GDP数据&#xff08;栅格数据的投影变…

Vite创建的Vue3项目按需导入(自动导入) Element Plus 样式错误以及编译器报错的问题

文章目录 前言配置 Element Plus 自动导入解决 ElMessage, ElNotification 等组件样式不正确的问题解决 ElMessage, ElNotification 等组件编译器报错的问题 前言 在Vite构建的Vue3项目中&#xff0c;可以通过官方推荐的自动导入的方法&#xff0c;方便地使用Element Plus&…

苍穹外卖 -- day10- Spring Task- 订单状态定时处理- WebSocket- 来单提醒- 客户催单

苍穹外卖-day10 功能实现&#xff1a;订单状态定时处理、来单提醒和客户催单 订单状态定时处理&#xff1a; 来单提醒&#xff1a; 客户催单&#xff1a; 1. Spring Task 1.1 介绍 Spring Task 是Spring框架提供的任务调度工具&#xff0c;可以按照约定的时间自动执行某个代…