最新资讯

  • React---day8

React---day8

2025-06-09 07:01:06 0 阅读

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.userList
        return (
           
    { userList.map((item , index , arr) => { return (
  • {item.name} + {item.age}
  • ) }) }
) }

不推荐的做法:

        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 (
      
) } } 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 (
Hello World
) } } class Profile extends PureComponent{ render (){ return(
Hello Profile
) } // 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 (
      
{/* 1、React.createRef() */}

Hello World

{/* 2、传入一个函数 */}

this.titleEle = args}>Hello World

); } 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的例子:

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

10.3 受控组件

受控组件是单元素(如