[React]面向组件编程

news2024/11/19 14:30:34

1. 定义组件

- 函数式定义(简单组件),使用function定义

import React from 'react';
import ReactDOM from 'react-dom/client';

function App() {
  return (
    <button onClick={handleClick}>click</button> // 直接把方法handleClick赋值给onClick
  )
  
  function handleClick() {
    alert('click')
  }
}
export default App; // 其他组件引用时需要export出去

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);

- 类式定义(复杂组件),使用class定义

import React from 'react';
import ReactDOM from 'react-dom/client';

class App extends React.Component {
  render() {
    return (
      <button onClick={this.handleClick}>click</button>  // this代表在App的实例对象上赋值handleClick
    )
  }
  handleClick() {
    alert('click')
  }
}
export default App; // 其他组件引用时需要export出去

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);

2. state,设置组件初始值

- 原始定义,需要在constructor中定义state和绑定方法handleClick的this

class Weather extends React.Component {
  // 创建构造器,类似ruby的initialize
  constructor(props) {
  	// 构造器是否接收props,是否传递给super,取决于是否希望在构造器中通过this访问props
  	// 如果是 super(),则 console.log(this.props)为undefined, console.log(props)就是传进来的props
  	// 如果是 super(props),则 console.log(this.props)为Weather的实例
    super(props) // 调用父类React.Component的构造器
    this.state = { isHot: true, wind: 'big' }
    this.handleClick = this.handleClick.bind(this) // 给handleClick绑定this
  }

  render() {
    const isHot = this.state.isHot
    return (
      <h1 onClick={this.handleClick}>Today is very {isHot ? 'hot' : 'cold'}, wind: {this.state.wind}</h1>
    )
  }
  
  handleClick() {
    this.setState({ isHot: !this.state.isHot, wind: this.state.wind !== 'big' ? 'big' : 'small' })
  }
}

- 简化后在类中直接给state和handleClick赋值,就直接把属性和方法绑定到Weather的实例上了

class Weather extends React.Component {
  // 初始化
  state = { isHot: true, wind: 'big' }
  // 渲染
  render() {
    const isHot = this.state.isHot
    return (
      <h1 onClick={this.handleClick}>Today is very {isHot ? 'hot' : 'cold'}, wind: {this.state.wind}</h1>
    )
  }
  // 自定义方法
  handleClick = () => {
    this.setState({ isHot: !this.state.isHot, wind: this.state.wind !== 'big' ? 'big' : 'small' })
  }
}

3. props,从组件外部给组件定义中传值

- 函数式组件使用props

- 函数式组件使用props
```typescript
import React from 'react';
import ReactDOM from 'react-dom/client';
import PropTypes from 'prop-types';

function Person(props){
  const { name, age, sex } = props
  return (
    <ul>
      <li>name: {name}</li>
      <li>age: {age}</li>
      <li>sex: {sex}</li>
    </ul>
  )
}
// 限制属性
Person.propTypes = {
  name: PropTypes.string.isRequired,
  age: PropTypes.number,
  sex: PropTypes.string,
  speak: PropTypes.func
}
// 设置属性默认值
Person.defaultProps = {
  age: 18,
  sex: 'female'
}

function speak() {
  console.log('speak')
}

const root = ReactDOM.createRoot(document.getElementById('root'));
const p = { name: 'Tom' }
root.render(
  <React.StrictMode>
    {/* <Person name={p.name} age={p.age} sex={p.sex} speak={speak} /> */}
    <Person {...p} speak={speak} />
  </React.StrictMode>
);

- 类式组件使用props

import React from 'react';
import ReactDOM from 'react-dom/client';
import PropTypes from 'prop-types';

class Person extends React.Component {
  render() {
    const { name, age, sex } = this.props
    return (
      <ul>
        <li>name: {name}</li>
        <li>age: {age}</li>
        <li>sex: {sex}</li>
      </ul>
    )
  }
  state = { isHot: true } // 这是给组件实例对象赋值
  // 限制属性 前面加 static 是给组件类赋值
  static propTypes = {
    name: PropTypes.string.isRequired,
    age: PropTypes.number,
    sex: PropTypes.string,
    speak: PropTypes.func
  }
  // 设置属性默认值
  static defaultProps = {
    age: 18,
    sex: 'female'
  }
}

function speak() {
  console.log('speak')
}

const root = ReactDOM.createRoot(document.getElementById('root'));
const p = { name: 'Tom' }
root.render(
  <React.StrictMode>
    {/* <Person name={p.name} age={p.age} sex={p.sex} speak={speak} /> */}
    <Person {...p} speak={speak} />
  </React.StrictMode>
);

4. refs,获取其他html元素的dom,相当于$(‘#xx’)

- 字符串形式ref

class Demo extends React.Component {
  render() {
    return (
      <>
        <input ref="input1" type="text" />
        <button onClick={this.tipLeftInput}>Click me</button>
        <input ref="input2" onBlur={this.tiprightInput} type="text" />
      </>
    )
  }

  tipLeftInput = () => {
    alert(this.refs.input1.value);
  }
  tiprightInput = () => {
    alert(this.refs.input2.value);
  }
}

- 回调形式ref

class Demo extends React.Component {
  render() {
    return (
      <>
        <input ref={(currentNode) => { this.input1 = currentNode }} type="text" />
        {/* <input ref={currentNode => this.input1 = currentNode} type="text" />  简写 */}
        <button onClick={this.tipLeftInput}>Click me</button>
        <input ref={(currentNode) => { this.rightInput = currentNode }} onBlur={this.tiprightInput} type="text" />
      </>
    )
  }

  tipLeftInput = () => {
    alert(this.input1.value);
  }
  tiprightInput = () => {
    alert(this.rightInput.value);
  }
}
  • ref回调函,如果是内联函数方式定义的,在更新过程中(更改state重新渲染render)会被执行两次,第一次传入参数null,第二次传入参数为DOM, 可以将ref回调函数定义为class的绑定函数避免上述问题。
    在这里插入图片描述

- createRef api创建ref , 较麻烦

class Demo extends React.Component {
  render() {
    return (
      <>
        <input ref={this.myRef1} type="text" />
        <button onClick={this.tipLeftInput}>Click me</button>
        <input ref={this.myRef2} onBlur={this.tiprightInput} type="text" />
      </>
    )
  }
  myRef1 = React.createRef()
  myRef2 = React.createRef()

  tipLeftInput = () => {
    console.log(this.myRef1.current.value);
  }

  tiprightInput = () => {
    console.log(this.myRef2.current.value);
  }
}

5. 事件处理

- button要获取input的值,使用ref

class Demo extends React.Component {
  render() {
    return (
      <>
        <input ref={this.myRef1} type="text" />
        <button onClick={this.tipLeftInput}>Click me</button>
      </>
    )
  }
  myRef1 = React.createRef()

  tipLeftInput = () => {
    console.log(this.myRef1.current.value);
  }
}

- input获取本身DOM的值,使用e.target获取dom

class Demo extends React.Component {
  render() {
    return (
      <>
        <input onBlur={this.tiprightInput} type="text" />
      </>
    )
  }
  
  tiprightInput = (e) => {
    console.log(e.target.value);
  }
}

6. 非受控组件和受控组件

- 非受控组件,使用ref取值,不建议使用

class Login extends React.Component {
  render() {
    return (
      <form onSubmit={this.submit}>
        <input type="text" name="username" ref={ref => this.username = ref} />
        <input type="text" name="password" ref={ref => this.password = ref} />
        <input type="submit" name="" />
      </form>
    )
  }

  submit = (e) => {
    e.preventDefault();
    alert(`username: ${this.username.value}, password: ${this.password.value}`)
  }
}

- 受控组件,使用state取值,建议使用

class Login extends React.Component {
  state = {
    username: '',
    password: ''
  }

  render() {
    return (
      <form onSubmit={this.submit}>
        <input type="text" name="username" onChange={this.saveUsername} />
        <input type="text" name="password" onChange={this.savePassword} />
        <input type="submit" name="" />
      </form>
    )
  }

  saveUsername = (e) => {
    this.setState({ username: e.target.value })
  }

  savePassword = (e) => {
    this.setState({ password: e.target.value })
  }

  submit = (e) => {
    e.preventDefault();
    alert(`username: ${this.state.username}, password: ${this.state.password}`)
  }
}

7.高阶函数

-上面的代码重构,onChange 调用的是saveFormdate方法return的返回值,是个函数
必须把一个函数交给onChange

class Login extends React.Component {
  state = {
    username: '',
    password: ''
  }

  render() {
    return (
      <form onSubmit={this.submit}>
        <input type="text" name="username" onChange={this.saveFormdate('username')} />
        <input type="text" name="password" onChange={this.saveFormdate('password')} />
        <input type="submit" name="" />
      </form>
    )
  }

  saveFormdate = (params) => {
    return (e) => {
      this.setState({ [params]: e.target.value })
    }
  }

  submit = (e) => {
    e.preventDefault();
    alert(`username: ${this.state.username}, password: ${this.state.password}`)
  }
}

8. 生命周期,回调函数或者叫钩子函数

class Life extends React.Component {
  // 构造器
  constructor(props) {
    console.log('constructor')
    super(props)
    this.state = { num: 0 }
  }
  // 组件挂载前调用
  componentWillMount() {
    console.log('componentWillMount')
  }
  // 询问是否更新组件调用
  shouldComponentUpdate() {
    console.log('shouldComponentUpdate')
    return true // 默认返回true
  }
  // 组件更新前调用
  componentWillUpdate() {
    console.log('componentWillUpdate')
  }
  // 组件挂载,初始化渲染、状态更新后调用
  render() {
    console.log('render')
    return (
      <>
        <h1 style={{ opacity: this.state.opacity }}>当前数字: {this.state.num}</h1>
        <button onClick={this.add}>数字+1</button>
        <button onClick={this.unmount}>卸载组件</button>
      </>
    )
  }
  // 组件更新后调用
  componentDidUpdate() {
    console.log('componentDidUpdate')
  }
  // 组件挂载后调用,调用一次
  componentDidMount() {
    console.log('componentDidMount')
  }
  // 组件卸载前调用
  componentWillUnmount() {
    console.log('componentWillUnmount')
  }

  // 数字+1调用
  add = () => {
    const { num } = this.state
    this.setState({ num: num + 1 })
  }

  // 卸载组件调用
  unmount = () => {
    root.unmount();
  }
}

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

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

相关文章

Pycharm+Gitlab+Jenkins持续集成自动化测试总结

一、Gitlab如何删除远程仓库的代码 1、如果本地仓库不小心删除&#xff0c;没关系&#xff0c;再新建一个空文件夹&#xff1b; 2、在空文件夹中右键&#xff0c;进入Git Bash命令行模式&#xff1b; 3、然后克隆远程仓库&#xff1b; git clone http://175.30.32.65:9000/r…

由半数年轻人存款不足10万而引发的思考!

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

windows安装youcompleteme

通过vim-plug&#xff0c;安装youcompleteme安装clangd-completer。python .\install.py --clangd-completer --msvc16c系补全需提供编译参数给clangd。两种种方式 安装c开发编译环境&#xff0c;即visual c 相关环境。 参考 ycm-core/YouCompleteMe: A code-completion en…

PMBOK第七版有什么新变化?影响8月PMP考试吗?

PMBOK是项目管理学习过程中必不可少的重要教材&#xff0c;从1996年PMI发布第一版PMBOK到现在&#xff0c;PMBOK已经更新到第七版&#xff0c;那么第七版PMBOK有哪些新变化呢&#xff1f;会影响8月考试吗&#xff1f;下面老师来为您详细解答。 1 PMBOK主要变化演进情况 私免费…

Istio 什么是服务网格

什么是服务网格 服务网格(Service Mesh)这个术语通常用于描述构成这些应用程序的微服务网络以及应用之间的交互。随着规模和复杂性的增长&#xff0c;服务网格越来越难以理解和管理。 它的需求包括服务发现、负载均衡、故障恢复、指标收集和监控以及通常更加复杂的运维需求&am…

高压功率放大器在超声波探测器中的应用

超声波探测技术是一种非常重要的无损检测技术&#xff0c;广泛应用于医学、工业等领域。超声波探测器中的高压功率放大器是其中一个关键部件&#xff0c;它主要用于将微弱的超声信号放大到能够进行后续处理和分析的程度。 在超声波探测器中&#xff0c;超声波发射器会向被测物体…

Qt编码方式

中文乱码算是一个常见的问题&#xff0c;本文提供两种解决方案 1 对字符串单独进行处理(不推荐) QString strQString::fromLocal8Bit("阿萨德");//使用此函数进行转码以显示正常(本地语言方式) QString strQString::fromUtf8("阿萨德");//qt还提供了从其他…

Bug小能手系列(python)_8: 使用mne库读取gdf文件报错 Cannot cast ufunc ‘clip‘ output

Cannot cast ufunc clip output from dtype float64 to dtype uint32 with casting rule same_kind 0. 错误介绍1. 环境介绍2. 问题分析3. 解决方法4. 总结 0. 错误介绍 在加载BCI Competition IV 2a数据集时&#xff0c;当使用mne库的io的read_raw_gdf()函数时出错。注&#…

Haproxy开源负载均衡部署

第一步环境准备&#xff1a; systemctl stop firewalld setenforce 0 systemctl disable firewalld.service #设置开机不启动防火墙sed -i s/SELINUX.*/SELINUXdisabled/ /etc/sysconfig/selinux #设置开机不启动防火墙iptables -F centos7服务器 haproxy 192.168…

自动化测试验证码tesseract安装以及python联调

前提 经常会遇到登录系统时候需要输入动态验证码的情况&#xff0c;但是自动化如何识别图片然后登陆系统&#xff1f; 需要用到pytesseract识别验证码图片以及PIL图像处理方法 import pytesseract from PIL import Image, ImageEnhance1、tesseract安装 OCR&#xff0c;即O…

ESP32报错-Invalid chip id. Expected 9 read 0. Bootloader for wrong chip?

异常现象&#xff1a; 如下图所示&#xff0c;ESP32的 bootloader 运行时候一直报错&#xff0c;导致设备频繁重启&#xff0c;无法跳转至APP 原因及解决方式&#xff1a; 这个报错的原因就是程序编译时候选择的芯片型号和当前实际运行的芯片型号不一致&#xff0c;导致无法…

两个链表的第一个公共节点

题目描述 输入两个链表&#xff0c;找出它们的第一个公共节点。 如下面的两个链表&#xff1a; 在节点 c1 开始相交。 示例 1&#xff1a; 输入&#xff1a;intersectVal 8, listA [4,1,8,4,5], listB [5,0,1,8,4,5], skipA 2, skipB 3 输出&#xff1a;Reference of…

「一键智能去除文件名中的特殊符号,让文件批量改名更加简单!」

文件批量改名一直是个繁琐的任务&#xff0c;其中最麻烦的问题之一就是文件名中的特殊符号。手动去除这些符号是一项耗时而繁琐的工作&#xff0c;但现在有一个更加智能的解决方案&#xff0c;可以让你快速的去除文件名中的特殊符号。方法如下&#xff1a; 首先&#xff0c;我…

漏洞预警|Apache StreamPipes 权限升级漏洞

棱镜七彩安全预警 近日&#xff0c;棱镜七彩威胁情报团队探测到开源项目Apache StreamPipes 存在权限升级漏洞&#xff0c;经分析研判&#xff0c;向全社会发起开源漏洞预警公告&#xff0c;提醒相关安全团队及时响应。 项目介绍 Apache StreamPipes&#xff08;incubating&…

【正点原子STM32连载】 第四十三章 DHT11数字温湿度传感器 摘自【正点原子】STM32F103 战舰开发指南V1.2

1&#xff09;实验平台&#xff1a;正点原子stm32f103战舰开发板V4 2&#xff09;平台购买地址&#xff1a;https://detail.tmall.com/item.htm?id609294757420 3&#xff09;全套实验源码手册视频下载地址&#xff1a; http://www.openedv.com/thread-340252-1-1.html# 第四…

如何在 ZBrush 和 UE5 中创建精灵吟游诗人(P1)

小伙伴们大家好&#xff0c;今天 云渲染小编给大家带来的是CG艺术家Hugo Sena关于“精灵吟游诗人”项目背后的工作流程&#xff0c;讨论了角色身体、服装和竖琴的工作流程&#xff0c;并解释了如何在虚幻引擎 5 中设置灯光。篇幅较长&#xff0c;分为上下两篇&#xff0c;大家接…

导出csv列错乱

今天在导出CSV文件的时候文件的列错乱了。 场景是将数据库信息导出&#xff0c;采用的是CSV&#xff0c;比excel快点。然后数据需要经过处理后再导入到其他库&#xff0c;导入的时候部分文件解析出错了&#xff0c;原因就是CSV文件内容的列和导入映射的实体字段数量对不上。见…

把你的 Python 技能从 “Hello World“ 升级到 “万能钥匙“:掌握 Python 的输出、输入、数据类型转换和运算符!

前言 这篇文章我将为大家分享 python 的输出、输入、数据类型的转换和运算符 相关的知识。如果大家也想跟着博主一起学习 python &#xff0c;欢迎订阅专栏哦python学习&#x1f60a; 输出 我们都知道&#xff0c;要想知道程序的运行结果&#xff0c;就需要将结果给打印到屏…

EventLog Analyzer:保障企业等保合规的安全利器

企业等保合规是现代信息安全管理的重要组成部分。在信息化时代&#xff0c;企业面临着越来越多的网络安全威胁和合规要求。为了确保企业的信息系统安全可靠&#xff0c;以及满足相关法规和标准的要求&#xff0c;企业需要借助强大的安全事件管理工具。EventLog Analyzer作为一种…

【力扣】前缀和/滑动窗口:209. 长度最小的子数组

【力扣】前缀和/滑动窗口&#xff1a;209. 长度最小的子数组 文章目录 【力扣】前缀和/滑动窗口&#xff1a;209. 长度最小的子数组1. 问题2. 题解2.1 暴力法2.2 前缀和 二分查找2.3 滑动窗口 参考 1. 问题 给定一个含有 n 个正整数的数组和一个正整数 target 。 找出该数组…