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

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.xdnf.cn/news/783163.html

相关文章:

  • Express 集成Sequelize+Sqlite3 默认开启WAL 进程间通信 Conf 打包成可执行 exe 文件
  • mobilnet v4 部署笔记
  • [yolov11改进系列]基于yolov11引入自集成注意力机制SEAM解决遮挡问题的python源码+训练源码
  • 机器学习实战36-基于遗传算法的水泵调度优化项目研究与代码实现
  • 华为云Flexus+DeepSeek征文|基于华为云Flexus X实例的小说转语音助手应用构建实录
  • java int 颜色值转换为string 不带透明度
  • Numpy入门2——视图和副本、伪随机数、切片和索引、数组的轴操作
  • 从0到1认识EFK
  • Oracle 用户/权限/角色管理
  • Linux随记(十八)
  • ElasticSearch+Gin+Gorm简单示例
  • cacti导出的1分钟监控数据csv文件读取并按5分钟求平均值,然后计算95计费值,假设31天的月份
  • graphviz, dot, Error: lost rA sA edge; 独立的模块
  • 项目执行中缺乏灵活应对机制,如何增强适应性?
  • 活动选择问题一文详解
  • 【论文阅读】Dolphin: Document Image Parsing via Heterogeneous Anchor Prompting
  • CppCon 2014 学习:The Perils of Strict Aliasing
  • 业务材料——半导体行业MES系统核心功能工业协议AI赋能
  • 不确定性分析在LEAP能源-环境系统建模中的整合与应用
  • 论文中pdf图片文件太大怎么办
  • GPTBots在AI大语言模型应用中敏感数据匿名化探索和实践
  • 无人机自主降落论文解析
  • TypeScript 高级类型深度指南:从类型体操到实战设计
  • vue入门环境搭建及demo运行
  • 生成JavaDoc文档
  • 用 Vue 做一个轻量离线的“待办清单 + 情绪打卡”小工具
  • 项目课题——基于ESP32的智能插座
  • 华为数据之道 精读——【173页】读书笔记【附全文阅读】
  • VsCode 安装 Cline 插件并使用免费模型(例如 DeepSeek)
  • SQL进阶之旅 Day 13:CTE与递归查询技术