介绍
今天在写代码的时候,用到了Ant Design的Select组件,也就是下拉选择框,和以前一样,习惯性的给Select组件加上了placeholder
,但是运行程序时,发现Select组件中并未显示placeholder
。我的代码如下,大家看出问题来了吗?
1 | import { Form, Select } from 'antd'; |
问题分析
没错,罪魁祸首就是这个initialValues={{ select: '' }}
,因为我在Form
组件中设置了Select
组件初始值为''
,注意initialValues中小写的select
对应Form.Item中组件的name
,不要与大写的Select名字搞混了,这就导致该组件的值被设置为空字符串,从而无法显示placeholder
。
如果把这个initialValues
去掉,或者将其设置为undefined
,就可以正常显示placeholder
了。
反过来思考一下,placeholder
的作用是在用户尚未选择某个值的时候给用户一个提示,而空字符串从程序的角度来说,是一个合法的值,从而导致Ant Design的Select组件不会显示placeholder
。
但是undefined
就不一样了,它表示没有值,这时Select组件就会显示placeholder
。(还是基础不牢呀)。
源码分析
为了追本溯源,我们从源码的角度分析一下其中细节,首先去Ant Design
的github页面将源码下载到本机。https://github.com/ant-design/ant-design
然后找到Select
组件的源码,路径是src/components/select
。在这个目录下,我们可以找到index.tsx
文件。这就是Select组件的入口了。
于是尝试在文件中搜索placeholder
,竟然没找到,这时我才意识到,Ant Design的Select组件并没有直接处理placeholder
,而是通过rc-select
这个库来实现的。
1 | const InternalSelect = <OptionType extends BaseOptionType | DefaultOptionType = DefaultOptionType>() { |
从上面的代码可以看出,InternalSelect
组件内容是通过RcSelect
来实现的,而RcSelect
是一个来自rc-select
库的组件。遂又去github上找到这个库的源码 - https://github.com/react-component/select。
全库搜索placeholder
,很快找到了相关代码,下面是placeholder
对应的结点的定义,最终Select通过渲染这个结点来显示placeholder
。
1 | const placeholderNode = React.useMemo<React.ReactNode>(() => { |
if(item)
- 这句很快被排除,因为item
是当前选中的值,而我们要显示placeholder
的前提是没有选中任何值。
于是来到style这一行,可以看到如果hasTextInput
为true
,则placeholder
的样式会被设置为visibility: 'hidden'
- 也就是隐藏。
1 | style={ hasTextInput ? { visibility: 'hidden' } : undefined } |
继续查找hasTextInput
的定义,发现它是通过inputValue
来判断的。
1 | const hasTextInput = mode !== 'combobox' && !open && !showSearch ? false : !!inputValue; |
继续查找inputValue
的定义,最终发现如下代码,看到了吗?这里添加了空字符串,也就是说如果inputValue
是空字符串,那么hasTextInput
就会被设置为true
,从而导致placeholder
被隐藏。
1 | let inputValue: string = searchValue || ''; |
打完收工,觉得有用就点个关注,你的关注是我输出的动力!我们明天再见!