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

React---day8

9.6 不可变数据的力量

我们知道是不能够修改this.state里面的数据的

举个例子

export class App extends React.PureComponent{constructor(){super();this.state = {userList:[{name : "tom" , age : 18},{name : "lily" , age : 20},{name : "tiki" , age : 18},]}}render(){const userList =this.state.userListreturn (<div><ul>{userList.map((item , index , arr) => {return (<li key={index}>{item.name} + {item.age}</li>)})}</ul><button onClick={() => this.addNewUser()}>点击添加</button></div>)}

不推荐的做法:

        const newData = {name : "hcy" , age : 19}this.state.userList.push(newData);this.setState({userList:this.state.userList})

因为我们修改了state里面的数据,但是这种方式直接修改原数组,不符合 React 的不可变性原则

我们的APP继承了PureComponent,它有shouldcomponnets方法,这个方法必须发生改变才会执行,但是我们这样的方法指向同一个地址(相同)所以是不会改变的

**推荐做法:**不要直接修改 state,应该用新数组。

    const newData = {name : "hcy" , age : 19}this.setState({userList:[...this.state.userList , newData]//不要直接修改 state,应该用新数组。})

9.7 全局事件传递events

开发中跨组件之间的事件传递,使用events

通过npm或者yarn来安装events

 npm add events

events常用的API:

  • 创建EventEmitter对象:eventBus对象;
  • 发出事件:eventBus.emit(“事件名称”, 参数列表);
  • 监听事件:eventBus.addListener(“事件名称”, 监听函数);
  • 移除事件:eventBus.removeListener(“事件名称”, 监听函数);

事件演练:

import React, { PureComponent } from 'react'
import {EventEmitter} from 'events'
// 需求:点击profile中的按钮->进行跨组件之间的事件传递
// 1、创建EventEmitter对象:eventBus对象
const evebtBus = new EventEmitter();export default class App extends PureComponent {render() {return (<div><Header /><Profile/></div>)}
}
class Header extends PureComponent{// 进行监听componentDidMount(){// 添加事件监听// 3、监听事件:eventBus.addListener("事件名称", 监听函数);// (eventName: string | symbol, listener: (...args: any[]) => void):// this.handleSayHelloListener:没有括号,因为是函数evebtBus.addListener("sayHello" , this.handleSayHelloListener)}componentWillUnmount(){// 取消事件监听//  (...args: any[]) => void)// 4、 移除事件:eventBus.removeListener("事件名称", 监听函数);evebtBus.removeListener("sayHello" ,this.handleSayHelloListener)}// ...args// 多个参数要写多个形参handleSayHelloListener(str , num){console.log(str + num);}render (){return (<div>Hello World</div>)}
}
class Profile extends PureComponent{render (){return(<div>Hello Profile<button onClick={() => this.emmitEvent()}>点击Profile</button></div>)}
// 2、发出事件:eventBus.emit("事件名称", 参数列表);emmitEvent(){evebtBus.emit("sayHello" , "Hello Home" , 123)}
}

10、受控和非受控组件

10.1 refs的使用

  • 方式一:传入一个对象
    • 对象是通过 React.createRef() 方式创建出来的;
    • 使用时获取到创建的对象其中有一个current属性就是对应的元素;
  • 方式二:传入一个函数
    • 该函数会在DOM被挂载时进行回调,这个函数会传入一个 元素对象,我们可以自己保存;
    • 使用时,直接拿到之前保存的元素对象即可;
import React, { PureComponent } from 'react';
import Pure from './Pure';
export default class App extends PureComponent {constructor() {super();this.titleRef = React.createRef();this.titleEle = null;}render() {return (<div>{/* 1、React.createRef() */}<h2 ref={this.titleRef} >Hello World</h2>{/* 2、传入一个函数 */}<h2 ref={(args) => this.titleEle = args}>Hello World</h2><button onClick={() => this.changeRef()}>点击切换</button></div>);}changeRef() {this.titleRef.current.innerHTML = "Hello React";this.titleEle.innerHTML = "Hello React"}appAdd(){console.log(this.pureRef.current.btnAdd());}
}

10.2 ref的类型

ref 的值根据节点的类型而有所不同:

  • 当 ref 属性用于 HTML 元素时,构造函数中使用 React.createRef() 创建的 ref 接收底层 DOM 元素作为其 current 属性;
  • 当 ref 属性用于自定义 class 组件时,ref 对象接收组件的挂载实例作为其 current 属性;
  • 你不能在函数组件上使用 ref 属性,因为他们没有实例;

举一个组件上使用ref的例子:

          // 组件的refthis.pureRef = React.createRef();{/* 3、当 ref 属性用于自定义 class 组件时,ref 对象接收组件的挂载实例作为其 current 属性; */}<Pure  ref={this.pureRef}/><button onClick={() => this.appAdd()}>app+1</button>

10.3 受控组件

受控组件是单元素(如<input><textarea>等)的值由React的state进行“控制”,即组件的状态(state)是唯一数据源

import React, { PureComponent } from 'react'export default class App extends PureComponent {constructor(){super();this.state = {username:""}}render() {return (<div><form><input type='text'value={this.state.username}onChange={(e) => this.handleChange(e)}/><input type='submit'onClick={(e) => this.handleSubmit(e)}/></form></div>)}handleSubmit(event){event.preventDefault();console.log("提交内容:",this.state.username)}handleChange(event){this.setState({username:event.target.value})}
}

<input>value 属性绑定了 this.state.username,输入框的内容只能通过 setState 来改变。每当用户输入内容时,onChange 事件会触发 handleChange,进而更新 state,React 再把最新的 state 赋值给 input 的 value。

总结:
受控组件的输入值受 React 组件的 state 控制,React 负责管理和同步表单数据,这就是“受控”的含义。

其他受控通过组件:比如select

import React, { PureComponent } from 'react'export default class App extends PureComponent {constructor(){super();this.state = {fruit:"apple"//默认为苹果}}render() {return (<div><form onSubmit={(e) => this.handleSubmit(e)}>{/* 选择器 */}<select value={this.state.fruit}name='fruits'onChange={(e) => this.handleChange(e)}><option value="apple">苹果</option><option value="oringe">橘子</option><option value="bannana">香蕉</option></select></form></div>)}handleSubmit(event){event.preventDefault();console.log("提交内容:",this.state.fruit)}handleChange(event){this.setState({fruit:event.target.value})}
}

受控组件—多输入

要是不抽取代码就会很冗余

import React, { PureComponent } from 'react'export default class App extends PureComponent {constructor(){super();this.state = {username:"",password:""}}render() {return (<div><form><input type='text'name='username'value={this.state.username}onChange={(e) => this.handleChange(e)}/><input name='password'type='password'value={this.state.password}onChange={(e) => this.handleChange(e)}/><input type='submit'onClick={(e) => this.handleSubmit(e)}/></form></div>)}handleSubmit(event){event.preventDefault();const {username , password } = this.state;console.log("提交内容:",username , password )}
//   handleusernameChange(event){
//    this.setState({
//     username:event.target.value
//    })//   }
//    handlepasswordChange(event){
//    this.setState({
//     password:event.target.value
//    })//   }handleChange(event){this.setState({[event.target.name] : event.target.value})}
//   我们可以把handleChange写为一个,因为她们的样式是都是:
//     handle{key}Change(event){
//    this.setState({
//     {key}:event.target.value
//    })//   }
// 我们只需要动态更新key就好
// 1、input设置name
// 2、event.target.name得到不同的key
}

10.4 非受控组件的使用

如果要使用非受控组件中的数据,那么我们需要使用 ref 来从DOM节点中获取表单数据。

在非受控组件中通常使用defaultValue来设置默认值;

import React, { createRef, PureComponent } from 'react'export default class App extends PureComponent {constructor(){super();this.nameRef = createRef()//创建ref对象}render() {return (<div><form><input type='text'ref={this.nameRef}//绑定ref/><input type='submit'onClick={ this.handleSubmit}/></form></div>)}handleSubmit = (event) => {event.preventDefault();console.log("提交内容:",this.nameRef.current.value)}//箭头函数
}
http://www.lryc.cn/news/2400648.html

相关文章:

  • C# Onnx 动漫人物人脸检测
  • C++内存列传之RAII宇宙:智能指针
  • PVE 虚拟机安装 Ubuntu Server V24 系统 —— 一步一步安装配置基于 Ubuntu Server 的 NodeJS 服务器详细实录1
  • GitHub 趋势日报 (2025年06月03日)
  • 出现dev/nvmeOnip2 contains a file system with errors, check forced 解决方法
  • Vue3.5 企业级管理系统实战(二十二):动态菜单
  • 磨皮功能 C++/C的OpenCV 实现
  • 蓝牙防丢器应用方案
  • TDengine 开发指南——高效写入
  • Linux kill 暂停命令
  • Unity与Excel表格交互热更方案
  • LVS、NGINX、HAPROXY的调度算法
  • C++ 使用 ffmpeg 解码本地视频并获取每帧的YUV数据
  • 分布式微服务系统架构第143集:pom文件
  • 2.0 阅读方法论与知识总结
  • 5. Qt中.pro文件(1)
  • 第八部分:第三节 - 事件处理:响应顾客的操作
  • 共识机制全景图:PoW、PoS 与 DAG 的技术对比
  • 学习笔记085——Spring Data JPA笔记
  • 可视化大屏工具对比:GoView、DataRoom、积木JimuBI、Metabase、DataEase、Apache Superset 与 Grafana
  • 内网穿透:打破网络限制的利器!深入探索和简单实现方案
  • 如何选择合适的哈希算法以确保数据安全?
  • 简数采集技巧之快速获取特殊链接网址URL方法
  • React 性能监控与错误上报
  • AI 如何改变软件文档生产方式?
  • 激光干涉仪:解锁协作机器人DD马达的精度密码
  • Windows如何定制键盘按键
  • go语言学习 第1章:走进Golang
  • 使用Prometheus+Grafana+Alertmanager+Webhook-dingtalk搭建监控平台
  • HOPE800系列变频器安装到快速调试的详细操作说明