将事件侦听器添加到我的页面会导致问题
Posted
技术标签:
【中文标题】将事件侦听器添加到我的页面会导致问题【英文标题】:adding event listener to to my page is causing issues 【发布时间】:2020-06-08 14:32:40 【问题描述】:由于某种原因,当我运行 yarn start 时,我正在使用 react 制作一个 nodejs 应用程序,我收到此错误“TypeError: btn_bmi.addEventListener is not a function”。任何人有任何想法为什么会像这样设置它在过去对我有用我不确定是什么导致了错误?
import React from 'react';
var btn_bmi = document.getElementsByClassName('bmi_button');
btn_bmi.addEventListener('click', calculate_bmi());
function calculate_bmi()
let Weight = document.getElementsByClassName('bmi_weight').value;
let Height = document.getElementsByClassName('bmi_height').value;
let Age = document.getElementsByClassName('bmi_age').value;
let Test = document.getElementsByClassName('test_print');
let bmi_calc = Weight / Height / Height * 10000;
let bmr_calc = 88.2 + (13.362 + Weight) + (4.799 + Height) - (5.677 + Age);
//if nothing entered show error
if (Weight, Height, Age == 0)
alert("Please enter your Height, Weight and Age so we can achieve your goals!")
else
//
Test.innerhtml = document.write= bmi_calc + bmr_calc;
function setup_page ()
return (
<div className='setup_main'>
<input className= 'bmi_weight' type='number' placeholder='Weight in kg:'></input>
<input className= 'bmi_height' type='number' placeholder='Height in cm:'></input>
<input className= 'bmi_age' type='number' placeholder='Age:'></input>
<button className='bmi_button'>calculate</button>
<p className='test_print'></p>
</div>
);
export default setup_page;
【问题讨论】:
你不应该以这种方式混合 vanilla JS DOM 方法和 React 代码。尝试改用 React 方法和工具(onClick 代替 addEventListeners,Components 代替使用 innerHTML 等)。这段代码需要大量重构。您得到的 TypeError 应该是您最不关心的恕我直言。 这能回答你的问题吗? What do querySelectorAll and getElementsBy* methods return? 我真的很陌生,所以我想借鉴我以前使用 javascript 的经验,但这显然不是正确的实现var btn_bmi = document.getElementsByClassName('bmi_button');
返回一个没有 .addEventListener()
方法的 HTMLCollection
对象(类似数组的对象)。您必须从集合中获取一个或多个项目,并在每个您想要的项目上调用 .addEventListener()
,或者使用不同的方法,例如仅返回单个 DOM 元素的 document.querySelector()
。
【参考方案1】:
document.getElementsByClassName(...)
返回 HTMLCollection
,而不是单个 HTML 元素。这是因为您可以拥有多个具有相同类名的元素。
如果您想假设只有一个回来,请替换为:
var btn_bmi = document.getElementsByClassName('bmi_button')[0];
或者,IMO 清洁工:
const btn_bmi = document.querySelector('.bmi_button');
但实际上,对您来说最好的做法是将事件侦听器放在 JSX 中;这样,当 React 输出 DOM 并重新渲染时,事件附件/分离会为您处理:
<button className='bmi_button' onClick=calculate_bmi>calculate</button>
【讨论】:
【参考方案2】:React 创建了不能被 document.querySelector 和其他类似函数访问的虚拟 DOM。如果你想访问由 react 创建的东西,你必须使用this
如果你正在使用类组件或挂钩useRef()
如果你正在使用函数组件(名称可以是别的东西,但我的意思是那些:const MyComponent = props => ( <some-element />)
)。为了您的目的,您应该创建一个将其值保持在某个状态的表单(this.state
或 useState()
钩子)EDIT
下面的答案也很正确,但是如果您使用 React 来呈现您的 html,则 document.getElementsByClassname 的结果将返回空集合
【讨论】:
非常感谢,虽然我对 javascript 和 html 有一些经验,但我是新来的一个 nodejs,所以这对我来说是新的哈哈【参考方案3】:另外if (Weight, Height, Age == 0)
可能不会像你认为的那样做。
【讨论】:
以上是关于将事件侦听器添加到我的页面会导致问题的主要内容,如果未能解决你的问题,请参考以下文章
向大约 15 个 firebase 对象添加值/子事件会导致堆大小增加吗?
向任何控件添加事件处理程序会导致 Visual Studio 中的错误