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

如何让自定义导航栏搜索输入组件具备复用性?

改造搜索输入组件以提升复用性

在我的应用中,搜索输入是最常用的元素之一,可用于搜索产品、主题、分类等。我已创建该搜索输入元素,代码如下所示。请问如何改造这个导航栏搜索输入,使其具备复用性以在其他场景使用?

原始代码:

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 01:10:19