介绍
今天在写代码的时候,用到了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 || ''; |
打完收工,觉得有用就点个关注,你的关注是我输出的动力!我们明天再见!