在继续学习 React 的第二天里,我们将深入探讨 React 中的事件绑定以及如何创建和使用组件。这些基础知识将帮助你构建动态和交互式的用户界面。
事件绑定是前端开发中不可或缺的一部分。在 React 中,事件绑定与传统的 HTML 有所不同,React 使用了自己的合成事件系统来处理事件。
在 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;
有时需要向事件处理函数传递参数,可以通过箭头函数或 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;
组件是 React 应用的核心单位,它们可以是类组件或函数组件,并且能够相互嵌套和组合。
函数组件是最简单的 React 组件。它们仅仅是一个接受 props 并返回 JSX 的函数。
import React from 'react';
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
export default Welcome;
类组件提供了更丰富的功能特性,如状态(state)和生命周期方法。
import React, { Component } from 'react';
class Welcome extends Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
export default Welcome;
状态是类组件的一个核心概念,用于存储组件的数据变化。使用 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;
组件间通信主要通过 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;
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 应用。
更多前端开发精彩内容,请持续关注!
家一定遇到过在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方法
*请认真填写需求信息,我们会在24小时内与您取得联系。