使用过element-ui
的朋友都知道,当我们给select
组件绑定一个不在options
列表的值时,该值仍然会展示在选择框中,效果如下图:
但我们希望的效果是,value
仍为"111",但不展示在选择框中,如图:
怎么实现呢?我能想到的方法有两种:
- 基于
el-select
再封装一个组件,在组件mounted
的时候判断modelValue
在不在options
里面,不在的话就重置成空字符串; - 修改
el-select
源码;
第一种方法得新建一个组件,然后在用到select
组件的地方都要import
一遍,之前用到el-select
的地方也都要改,或者全局注册这个新的组件,这种做法感觉相对low一些,直接放弃;
之前学习过神光大佬的调试秘籍,里面讲到了怎样调试源码,所以今天尝试下第二种方法。由于node_modules
里的element-ui
是编译后的代码,没有关联sourcemap
,为了拿到sourcemap
,我们需要去github
下载element-ui
源码,具体操作步骤如下:
git clone https://github.com/ElemeFE/element.git
- 源码clone好以后,
npm install
安装源码所需依赖,这里可能会遇到node-sass
报错,使用nvm
切换成对应版本的node
即可 - 修改
build/webpack.common.js
,增加devtool: 'cheap-module-source-map',
,如图:
- 执行
npm run dist
,将生成的lib
文件夹替换到原项目的node_modules
中,如图:
- 在原项目执行
npm run serve
,打开浏览器,在sources
面板即可看到element-ui
中的.vue
源码了,如图:
知道了怎么调试element-ui
源码以后,接下来就是分析具体问题了,既然是调试el-select
组件,那么肯定是先找到packages
文件夹里的select.vue
文件
- 先看下
mounted
方法,里面有一句this.setSelected()
,顾名思义,猜想这个方法可能就是设置下拉框的选中值,所以我们在这里打一个断点
- 进入
setSelected
方法内部,可以看到里面有一个关键的方法getOption
,通过let option = this.getOption(this.value);
可以看出这一句是通过传入的v-model
的值去options
里找对应的option
,后续的逻辑就都跟这个option
有关了,所以不难看出核心的逻辑应该都在这个getOption
里面了
- 继续进入到
getOption
方法内部,可以看到getOption
接收的value
就是我们v-model
里传入的111,如图:
- 从524至533行的
for
循环就是将传入的111去options
里找有没有对应的option
,很明显传入111,找不到对应的option
,所以为undefined
,如图:
- 既然找不到对应的
option
,那么就继续执行535至545行,可以看到当找不到对应的option
时,又会创建一个newOption
并最终返回,这个newOption
对应的label
和value
就是我们传入的111,如图:
- 到了这里我们就定位到问题了,所以最简单的解决办法就是把
newOption
的label
和value
直接给空字符串就好(这里可以临时加上/* eslint-disable */,避免重新编译报错),如图:
- 最后将
element-ui
源码重新执行npm run dist
,将生成的lib
文件夹再次覆盖到原项目即可,效果如图: