Ant的优势之处
AntDesign目前在前端是使用的非常广泛的一个前端资源库,其拥有丰富的组件
这一点特别是在ant-design-pro上体现的更明显,对比与element-ui上,一般在处理复杂后台业务的时候建议使用ant,在处理想要更好更漂亮的ui时建议使用element
关于Input组件的@clear事件
关于Input输入框组件上,element-ui和ant都提供了clear用于清空当前用户的输入内容
<el-input placeholder="请输入内容" v-model="input" clearable @clear='fireEvent' />
<a-input placeholder="请输入内容" allow-clear @change="onChange" />
<a-input-search placeholder="请输入内容" allow-clear @change="onChange" @search='fireSearch' />
但是他们的不同之处是element提供了clear事件之后的回调,而ant并未提供该功能
ant这里倒是有一个类似的a-input-search
的能力(@search)
来对事件进行触发,但是回看官方文档就会发现,Enter和Clear动作都会导致(@search)
的触发,其定制化并不符合我们的需求,我只想要@clear的回调,因此可能要涉及到对ant组件库中Input组件的功能进行调整
源码跟踪
- 首先我们跟踪到ant中Input组件的源码,找到对应的
/input/index.js
,然后发现实际组件是/input/Input.js
文件 - 跟踪后发现其引用了另一个文件
/input/ClearableLabeledInput.js
然后跟踪发现在#34有一个renderClearIcon
方法,该方法最后渲染出来了一个clear按钮,并且具有onclick事件handleReset
查看调用发现该事件函数的定义在
/input/Input.js
中handleReset: function handleReset(e) { var _this2 = this; this.setValue('', function () { _this2.focus(); }); resolveOnChange(this.$refs.input, e, this.onChange); },
- 根据3中的发现,其实最终的问题就是onclear之后,事件没有向上抛出一个@clear的emit消息,因此我们只需要在这里增加一行
this.$nextTick(() => this.$emit('clear', e))
就可以解决这个clear事件的触发 - 现在的问题是,我们如何去修改他的源码,并且还能在prod打包的时候也生效
修改方案
这里根据vite的文档我们引入了一个外部的库来ant的原始代码进行变更:@rollup/plugin-replace
文档地址:https://www.npmjs.com/package/@rollup/plugin-replace
其实际原理就是在开发模式和编译模式下,都对其源代码进行拦截并修改
这里提供一下,我这里的修改方案:
const fs = require('fs')
const replace = require('@rollup/plugin-replace')
const defaultReg = /(@ant-design-vue-v1\\design\\es\\input\\Input\.js)|(@ant-design-vue-v1\/design\/es\/input\/Input\.js)/
const exportFn = (reg = defaultReg) => {
return {
name: 'vite-plugin-qdesign-input-clear-event-resolver',
configResolved(config) {
// 以来预构建时候替换 esbuild
config.optimizeDeps.esbuildOptions.plugins = config.optimizeDeps
.esbuildOptions.plugins
? config.optimizeDeps.esbuildOptions.plugins
: []
config.optimizeDeps.esbuildOptions.plugins.push({
name: 'replace-code',
setup(build) {
// MARK 调试的时候可以尝试直接idea启动debug模式,加断点,确认代码的执行无误
// MARK 页面debugger确认的时候先用调试编译,触发debug模式的断点,触发资源更新,然后再正常启动触发页面的断点,可能会快一些
build.onLoad(
{
filter: reg,
},
(args) => {
// 首先获取源代码内容
let source = fs.readFileSync(args.path, 'utf8')
source = source.replace('var _this2 = this;', `var _this2 = this;this.$nextTick(()=>this.$emit('clear', e))`)
return {
contents: source,
}
},
)
},
})
// 添加打包时的替换 rollup
config.plugins.push(
replace({
// MARK 调试的时候断点加在:@rollup/plugin-replace/dist/rollup-plugin-replace.cjs.js
// MARK 然后调用idea的debug模式,触发断点,调试速度最快
values: {
'var _this2 = this;': (id) => {
return `var _this2 = this;this.$nextTick(()=>this.$emit('clear', e))`
},
},
delimiters: ['', ''], // replace方法在进行匹配的时候是采用的正则,因此会自动带上前缀和后缀['\\b', '\\b(?!\\.)'],按需使用
include: [reg],
preventAssignment: true,
}),
)
},
}
}
module.exports = exportFn
在上面的代码中#4行表示了在rollup中需要匹配的文件正则-适配linux和windows
其主要替换代码在#26和#41行
自此,AntDesignVue的Input输入框就具有了清空会回调的能力,Input.TextArea也有这个问题,可以按需增加
自此,我们就可以正常使用ant中Input组件的@clear事件了
<a-input placeholder="请输入内容" allow-clear @clear="clearEventFire" />