整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

React 入门 Day 02:深入理解事件绑定与组

React 入门 Day 02:深入理解事件绑定与组件

在继续学习 React 的第二天里,我们将深入探讨 React 中的事件绑定以及如何创建和使用组件。这些基础知识将帮助你构建动态和交互式的用户界面。


1. React 中的事件绑定

事件绑定是前端开发中不可或缺的一部分。在 React 中,事件绑定与传统的 HTML 有所不同,React 使用了自己的合成事件系统来处理事件。

1.1 基本事件绑定

在 React 中,可以直接在 JSX 中绑定事件。事件名称使用 camelCase 命名,并传入一个事件处理函数。

示例代码:

import React from 'react';

class ClickButton extends React.Component {
  handleClick=()=> {
    alert('Button Clicked!');
  };

  render() {
    return (
      <button onClick={this.handleClick}>Click Me</button>
    );
  }
}

export default ClickButton;

1.2 向事件处理函数传递参数

有时需要向事件处理函数传递参数,可以通过箭头函数或 Function.prototype.bind 方法实现。

示例代码:

import React from 'react';

class ParameterButton extends React.Component {
  handleClick=(param)=> {
    alert(`Button Clicked with parameter: ${param}`);
  };

  render() {
    return (
      <button onClick={()=> this.handleClick('Hello')}>Click Me</button>
    );
  }
}

export default ParameterButton;

2. React 组件

组件是 React 应用的核心单位,它们可以是类组件或函数组件,并且能够相互嵌套和组合。

2.1 函数组件

函数组件是最简单的 React 组件。它们仅仅是一个接受 props 并返回 JSX 的函数。

示例代码:

import React from 'react';

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

export default Welcome;

2.2 类组件

类组件提供了更丰富的功能特性,如状态(state)和生命周期方法。

示例代码:

import React, { Component } from 'react';

class Welcome extends Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}

export default Welcome;

2.3 组件的状态 (State)

状态是类组件的一个核心概念,用于存储组件的数据变化。使用 this.state 初始化状态,并通过 setState 方法更新状态。

示例代码:

import React, { Component } from 'react';

class Counter extends Component {
  constructor(props) {
    super(props);
    this.state={
      count: 0
    };
  }

  increment=()=> {
    this.setState({ count: this.state.count + 1 });
  };

  render() {
    return (
      <div>
        <p>Count: {this.state.count}</p>
        <button onClick={this.increment}>Increment</button>
      </div>
    );
  }
}

export default Counter;

2.4 组件间通信

组件间通信主要通过 props 进行,父组件可以将数据传递给子组件,子组件通过 this.props 访问数据。

示例代码:

import React from 'react';

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

function App() {
  return (
    <div>
      <Welcome name="Alice" />
      <Welcome name="Bob" />
    </div>
  );
}

export default App;

2.5 组合 vs 继承

React 推崇使用组合(composition)而不是继承(inheritance)来重用代码。

示例代码:

import React from 'react';

function FancyBorder(props) {
  return (
    <div className={'FancyBorder FancyBorder-' + props.color}>
      {props.children}
    </div>
  );
}

function Dialog(props) {
  return (
    <FancyBorder color="blue">
      <h1 className="Dialog-title">
        {props.title}
      </h1>
      <p className="Dialog-message">
        {props.message}
      </p>
    </FancyBorder>
  );
}

function WelcomeDialog() {
  return (
    <Dialog
      title="Welcome"
      message="Thank you for visiting our spacecraft!" />
  );
}

export default WelcomeDialog;

总结

通过第二天的学习,你应该已经掌握了 React 中的事件绑定和组件的基本用法。深入理解这些概念将帮助你更好地构建复杂的、可维护的 React 应用。

附录

1. 推荐阅读

  • React 官方文档
  • JavaScript 事件处理

2. 练习题

  1. 创建一个计数器组件,实现加减功能,并将其与父组件进行组合。
  2. 创建一个包含多个输入框的表单组件,并实现表单数据的提交和验证。

更多前端开发精彩内容,请持续关注!

家一定遇到过在for循环中创建html元素,并且绑定事件的情况,

实际的效果,发现最后一个元素的事件将会覆盖前面所有元素的事件,如下面的代码:



	for (int i=0; i < 10; i++) {
		var  p=$("<p></p>");
		p.html(i);
		var url="http://localhost/p?id="+i;
		p.click(function(){
			window.open(url);
		});
		$("body").append(p);
	}


以上代码,目测看没有什么问题,但是实际情况是,所有的p元素的click事件都是相同了,最后一次的事件覆盖了前面所有的事件,

url都变成了最后一次的,这应该是jquery的一个bug


那应该如何解决呢?


我稍作调整,改成以下的就可以了




	for (int i=0; i < 10; i++) {
		var  p=$("<p></p>");
		p.html(i);
		var url="http://localhost/p?id="+i;
		p.attr("url",url);
		p.click(function(){
			window.open($(this).attr("url"));//此处不能直接写url
		});
		$("body").append(p);
	}


这样,每个p标签的事件都是独立的了。


网上看了听说可以使用数组的方法解决,希望有更优雅的解决方法,希望大家评论区讨论贡献

先对原生的addEventListener,removeEventListener两个函数,进行一定程度的改造。改造逻辑如下:

//保存Html元素,Html元素被绑定的事件种类,Html元素被绑定事件对应的函数
var objectExtraEventListenerMap=new Map();
//保存原生addEventListener
EventTarget.prototype.addExtraEventListener=EventTarget.prototype.addEventListener;
/**
 * 重写原生addEventListener
 * @param targetType 被绑定的事件
 * @param listener 被绑定到的函数
 */
EventTarget.prototype.addEventListener=function(targetType, listener) {

	// 先调用removeEventListener,删除已经绑定的方法
    this.removeEventListener(targetType, listener.name)

    var objectExtraEventMap=objectExtraEventListenerMap.get(this);
    if (typeof objectExtraEventMap=='undefined') {
        objectExtraEventMap=new Map();
        objectExtraEventMap.set(targetType, [listener])
    } else {
        var objectExtraListenerQueue=objectExtraEventMap.get(targetType);
        if (typeof objectExtraListenerQueue=='undefined') {
            objectExtraListenerQueue=new Array();
        }
        objectExtraListenerQueue.push(listener);
        objectExtraEventMap.set(targetType, objectExtraListenerQueue)
    }
    objectExtraEventListenerMap.set(this, objectExtraEventMap);
	// 调用被保存的原生addEventListener
    this.addExtraEventListener(targetType, listener);
};
//保存原生removeEventListener
EventTarget.prototype.removeExtraEventListener=EventTarget.prototype.removeEventListener;
/**
 * 重写原生removeEventListener
 * @param targetType 被绑定的事件
 * @param listener 被绑定到的函数名
 */
EventTarget.prototype.removeEventListener=function(targetType, listenerName) {
    var eventTargetObject=this;
    var objectExtraEventMap=objectExtraEventListenerMap.get(eventTargetObject);
    if (typeof objectExtraEventMap !='undefined') {
        var objectExtraListenerQueue=objectExtraEventMap.get(targetType);
        if (typeof objectExtraListenerQueue !='undefined') {
            objectExtraListenerQueue.forEach(function(listenerItem, index, targetQueue) {
                if (listenerItem.name==listenerName) {
                    targetQueue.splice(index, 1);
					// 调用被保存的原生removeEventListener
                    eventTargetObject.removeExtraEventListener(targetType, listenerItem);
                }
            });
        }
    }
}

此后,我们可以直接调用addEventListener方法。不用再手动调用removeEventListener就可以避免重复绑定事件了。

HTML代码

<input type="text" id="example" name="example">

JS调用addEventListener方法