如何让自定义导航栏搜索输入组件具备复用性?
改造搜索输入组件以提升复用性
在我的应用中,搜索输入是最常用的元素之一,可用于搜索产品、主题、分类等。我已创建该搜索输入元素,代码如下所示。请问如何改造这个导航栏搜索输入,使其具备复用性以在其他场景使用?
原始代码:
import React from 'react' import { Box, FormControl, InputBase } from '@mui/material' import { styled } from '@mui/material/styles'; import { ContainedButton } from '../../ui-kit'; const StyledInput = styled(InputBase)(({ theme }) => ({ color: 'inherit', border: 'none', outline: 'none', '& .MuiInputBase-input': { maxHeight: '30px', padding: '4px 16px', maxWidth: '100%', borderLeft: `1px solid ${theme.palette.grey[100]}`, fontSize: 16, lineHeight: 1.125, color: theme.palette.text.primary, }, width: '100%', })); const CONTAINED_BUTTON_STYLED = { minWidth: '111px', borderRadius: '0 2px 2px 0', }; export const SearchInput = () => { return ( <Box> <FormControl sx={{ flexDirection: 'row', ml: '16px', width: '100%' }}> <StyledInput placeholder="Search on Website" /> <ContainedButton sx={CONTAINED_BUTTON_STYLED} title="Search" /> </FormControl> </Box> ) }
改造方案
要让组件具备复用性,核心是把固定配置和逻辑抽离成可配置的props,让组件能适应不同场景的需求,具体改造点如下:
1. 提取可配置属性到props
将占位符文本、按钮文案、组件样式等固定值改为通过props传入,同时保留默认值确保基础可用性。
2. 支持受控/非受控输入模式
允许父组件控制输入值(受控模式),或者让组件内部维护状态(非受控模式),适配不同的业务场景。
3. 传递搜索回调函数
把搜索逻辑交给父组件实现,组件只负责UI渲染和值的传递,通过onSearch回调触发搜索行为。
4. 样式可扩展
保留默认样式的同时,允许通过props传入额外的sx样式,覆盖或扩展组件、输入框、按钮的样式。
改造后的完整代码
import React, { useState } from 'react' import { Box, FormControl, InputBase } from '@mui/material' import { styled } from '@mui/material/styles'; import { ContainedButton } from '../../ui-kit'; const StyledInput = styled(InputBase)(({ theme }) => ({ color: 'inherit', border: 'none', outline: 'none', '& .MuiInputBase-input': { maxHeight: '30px', padding: '4px 16px', maxWidth: '100%', borderLeft: `1px solid ${theme.palette.grey[100]}`, fontSize: 16, lineHeight: 1.125, color: theme.palette.text.primary, }, width: '100%', })); const DEFAULT_BUTTON_STYLE = { minWidth: '111px', borderRadius: '0 2px 2px 0', }; // 定义组件的props类型 type SearchInputProps = { placeholder?: string; buttonText?: string; value?: string; onChange?: (value: string) => void; onSearch: (value: string) => void; sx?: React.CSSProperties; inputSx?: React.CSSProperties; buttonSx?: React.CSSProperties; marginLeft?: string; }; export const SearchInput = ({ placeholder = "Search on Website", buttonText = "Search", value: externalValue, onChange: externalOnChange, onSearch, sx = {}, inputSx = {}, buttonSx = {}, marginLeft = '16px' }: SearchInputProps) => { // 内部状态用于非受控模式 const [internalValue, setInternalValue] = useState(''); const isControlled = externalValue !== undefined; const currentValue = isControlled ? externalValue : internalValue; const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => { const newValue = e.target.value; if (isControlled && externalOnChange) { externalOnChange(newValue); } else { setInternalValue(newValue); } }; const handleSearch = () => { onSearch(currentValue); }; return ( <Box sx={sx}> <FormControl sx={{ flexDirection: 'row', ml: marginLeft, width: '100%' }}> <StyledInput placeholder={placeholder} value={currentValue} onChange={handleChange} sx={inputSx} /> <ContainedButton sx={{ ...DEFAULT_BUTTON_STYLE, ...buttonSx }} title={buttonText} onClick={handleSearch} /> </FormControl> </Box> ) }
使用示例
非受控模式(组件维护状态)
<SearchInput placeholder="Search Products" buttonText="Find Products" onSearch={(value) => console.log('搜索产品:', value)} />
受控模式(父组件控制状态)
const [searchValue, setSearchValue] = useState(''); <SearchInput placeholder="Search Categories" buttonText="Search Category" value={searchValue} onChange={setSearchValue} onSearch={(value) => console.log('搜索分类:', value)} marginLeft="8px" buttonSx={{ minWidth: '130px' }} />
内容的提问来源于stack exchange,提问作者Muhammad Nurul Ahsan
相关产品推荐
相关产品推荐

