You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中InputBase子组件聚焦时如何触发父div元素聚焦并修改样式

问题说明

这是我当前的SearchBar效果:
当前SearchBar
我想要实现的效果是:当我聚焦<InputBase>组件时,触发父级<div className={classes.search} ref={refSearchBar}></div>的聚焦状态,让父元素的box-shadow变成如下效果:
预期效果
我尝试用useRef实现但没有生效,原代码如下:

import React, { useRef } from "react";
import { makeStyles } from "@material-ui/core/styles";
import InputBase from "@material-ui/core/InputBase";
import SearchIcon from "@material-ui/icons/Search";

const useStyles = makeStyles((theme) => ({
  search: {
    position: "relative",
    borderRadius: theme.shape.borderRadius,
    padding: "0 0.5rem",
    width: "50%",
    border: "1px solid grey",
    "&:focus": {
      boxShadow: "0 0 0 1px blue, 0 0 0 4px blue"
    }
  },
}));

export default function PrimarySearchAppBar(props) {
  const classes = useStyles();
  const refSearchBar = useRef(null);

  return (
    <div className={classes.search} ref={refSearchBar}>
      <div className={classes.searchIcon}>
        <SearchIcon />
      </div>
      <InputBase
        placeholder="Search…"
        classes={{
          root: classes.inputRoot,
          input: classes.inputInput
        }}
        inputProps={{ "aria-label": "search" }}
        style={{ width: "100%" }}
        onClick={() => {
          refSearchBar.current.focus();
        }}
      />
    </div>
  );
}
解决方案

你的代码不生效有两个核心问题:

  1. 普通div元素默认不支持聚焦事件,必须给父div添加tabIndex属性才能触发:focus伪类对应的样式
  2. 你绑定的是onClick事件,仅点击输入框时会触发,用键盘Tab切换聚焦到输入框的场景无法覆盖,应该改为绑定onFocus事件

另外需要在父div的聚焦样式里加outline: none,去掉浏览器默认的聚焦轮廓线,避免和自定义的box-shadow冲突,同时补全缺失的搜索图标、输入框样式避免布局错位,修改后的完整代码如下:

import React, { useRef } from "react";
import { makeStyles } from "@material-ui/core/styles";
import InputBase from "@material-ui/core/InputBase";
import SearchIcon from "@material-ui/icons/Search";

const useStyles = makeStyles((theme) => ({
  search: {
    position: "relative",
    borderRadius: theme.shape.borderRadius,
    padding: "0 0.5rem",
    width: "50%",
    border: "1px solid grey",
    "&:focus": {
      outline: "none",
      boxShadow: "0 0 0 1px blue, 0 0 0 4px rgba(0,0,255,0.2)"
    }
  },
  searchIcon: {
    height: "100%",
    position: "absolute",
    pointerEvents: "none",
    display: "flex",
    alignItems: "center",
    justifyContent: "center",
    left: 8,
  },
  inputRoot: {
    color: "inherit",
    width: "100%",
  },
  inputInput: {
    padding: theme.spacing(1, 1, 1, 0),
    paddingLeft: `calc(1em + ${theme.spacing(2)}px)`,
    width: "100%",
  }
}));

export default function PrimarySearchAppBar(props) {
  const classes = useStyles();
  const refSearchBar = useRef(null);

  return (
    <div className={classes.search} ref={refSearchBar} tabIndex={0}>
      <div className={classes.searchIcon}>
        <SearchIcon />
      </div>
      <InputBase
        placeholder="Search…"
        classes={{
          root: classes.inputRoot,
          input: classes.inputInput
        }}
        inputProps={{ "aria-label": "search" }}
        onFocus={() => {
          refSearchBar.current.focus();
        }}
      />
    </div>
  );
}

内容的提问来源于stack exchange,提问作者CCCC

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 11:57:03