React.js中点击div时如何获取元素的文本内容?
解决React子组件点击后传递内容到父组件的问题
我来帮你搞定这个问题~你现在的困境主要是既用了不符合React设计思路的DOM操作,还不小心犯了语法错误,咱们一步步来修正,用更React的方式实现需求。
先说说你现有代码为啥不工作
document.getElementsByClassName(".recipe-name")这里多了个多余的点号!这个方法接收的是不带点的类名字符串,而且它返回的是一个HTMLCollection集合(类似数组的结构),不是单个元素,所以哪怕去掉点号,你也得用document.getElementsByClassName("recipe-name")[0]?.textContent才能拿到第一个匹配元素的文本。但说实话,这种直接操作DOM的方式在React里真的不推荐,违背了React的数据流设计。- 你之前尝试用ref但没成功,大概率是ref的创建和引用方式不对,但同样,ref更适合用来处理DOM元素的交互(比如聚焦、滚动),而不是用来传递组件数据。
推荐方案:用回调函数实现组件间通信
React的核心是单向数据流,子组件应该通过父组件传递的回调函数把数据“递”回去,而不是让父组件直接伸手去子组件里拿DOM内容。这是React组件通信的标准做法,代码更清晰也更好维护。
第一步:改造子组件,添加点击事件并传递数据
在子组件的recipe-container div上绑定点击事件,把需要的菜谱名和食材数据整理好,通过父组件传过来的回调函数发回去:
export default class Recipecontainer extends React.Component { handleContainerClick = () => { const { recipe, onRecipeClick } = this.props; // 把需要的数据整理成你需要的格式,比如对象 const recipeInfo = { recipeName: recipe.recipeName, ingredients: recipe.ingredients.join('\n') // 用换行分隔食材,或者换成', '也可以 }; // 调用父组件的回调,把数据传过去 onRecipeClick(recipeInfo); }; render(){ const recipe = this.props.recipe; const recipeIngredients = recipe.ingredients.map((item, index) => <li key={index}>{item}</li>); return ( {/* 给容器div绑定点击事件 */} <div className="recipe-container" onClick={this.handleContainerClick}> <h3 className="recipe-name">{recipe.recipeName}</h3> <div className="food-img"> <img src={recipe.smallImageUrls} alt="菜谱图片"/> </div> <ul className="ingredient-list">{recipeIngredients}</ul> </div> ) } }
第二步:父组件接收数据并存储
父组件需要定义一个处理数据的方法,然后把这个方法作为props传给子组件。当子组件被点击时,这个方法就会接收到子组件传递的菜谱数据,你就可以把它存在state或者变量里了:
export default class ParentComponent extends React.Component { // 用state存储选中的菜谱数据,这样数据变化时组件会自动更新 state = { selectedRecipe: null }; saveData = (recipeInfo) => { // 这里拿到子组件传过来的数据,存到state里 this.setState({ selectedRecipe: recipeInfo }); // 也可以做其他操作,比如打印看看 console.log('选中的菜谱信息:', recipeInfo); }; render() { // 假设你有一个菜谱数组,循环渲染子组件 const recipes = []; // 这里替换成你的菜谱数据源 return ( <div className="parent-wrapper"> {recipes.map((recipe, idx) => ( <Recipecontainer key={idx} recipe={recipe} onRecipeClick={this.saveData} // 把回调函数传给子组件 /> ))} {/* 可以在这里展示选中的菜谱内容 */} {this.state.selectedRecipe && ( <div className="selected-recipe-card"> <h4>你选中的菜谱:{this.state.selectedRecipe.recipeName}</h4> <p>所需食材:<br/>{this.state.selectedRecipe.ingredients}</p> </div> )} </div> ); } }
如果你非要用ref的方式(不推荐,但可以实现)
如果你坚持想用ref来获取DOM内容,也能实现,但真的不建议这么做:
// 子组件修改 export default class Recipecontainer extends React.Component { // 创建一个ref绑定到容器div containerRef = React.createRef(); handleContainerClick = () => { const container = this.containerRef.current; if (!container) return; // 通过ref获取DOM元素的内容 const recipeName = container.querySelector('.recipe-name').textContent; const ingredients = container.querySelector('.ingredient-list').textContent; // 还是通过回调传给父组件 this.props.onRecipeClick({ recipeName, ingredients }); }; render(){ const recipe = this.props.recipe; const recipeIngredients = recipe.ingredients.map((item, index) => <li key={index}>{item}</li>); return ( <div className="recipe-container" ref={this.containerRef} onClick={this.handleContainerClick}> {/* 其他内容不变 */} </div> ) } }
父组件的用法和上面完全一样,还是通过onRecipeClick接收数据。
最后总结一下
强烈推荐用回调函数传递数据的方式,这是React的标准玩法,既符合单向数据流的设计,代码也更易读易维护。直接操作DOM的方式容易引发意想不到的问题,尤其是在组件重新渲染的时候。
内容的提问来源于stack exchange,提问作者YVH
相关产品推荐
相关产品推荐

