1.在github上提issue
通常第三方库都有自己的github
仓库地址或者官网,如果有github
仓库的话就可以在github
上提issue
,要注意的是一定要按照仓库作者规定的格式提issue
,写明bug
复现过程,否则issue
可能会被忽略。
这种方法理论上是最好的,但是也有一些缺点:
- 仓库作者可能不维护了,那么issue将不会被解决
- 仓库作者不认同观点,可能会拒绝所提的issue
- 仓库作者接受所提的issue,但认为其优先级低,可能需要很长时间才会解决
2.fork代码自己修改
如果急需解决bug
的话,可以尝试自己把原仓库fork
下来进行修改,并且将代码发布到npm
仓库中,供项目使用。这种方法的缺点有:
- 增加维护成本,需要和原仓库保持同步,否则会丢失更新
- 后期可能会和原仓库出现难以合并的分歧
- 注意合法性问题,可能需要原作者授权
综上,如果原仓库一直在更新的话,需要考虑原仓库和自己仓库的代码同步问题,因此这种方法更适合在原仓库不再维护的情况下使用。
此外还可以给仓库作者提PR,这样就不用担心后续维护的问题了,也是一种比较好的方式,即满足了自己的需求还为开源库做了贡献,但前提是作者接受了PR。
3.使用pack-package打补丁
在不修改源代码的情况下,也可以通过直接修改其打包后的代码来实现所需功能,步骤如下:
安装pack-package
npm i patch-package
修改代码
在node_modules
中找到对应模块的位置,以element-plus
为例,假设要对Button
组件的点击事件进行修改,找到Button
组件以及代码中相应位置,如图所示,添加代码console.log('click')
。代码修改后的预期结果是所有用了Button
组件的地方,在点击按钮时都会在控制台输出click
。
验证代码
模版中使用el-button
组件:
<template>
<div>
<el-button>Default</el-button>
</div>
</template>
如下图所示代码中并没有主动监听el-button
的click事件,但是每次点击时都会在控制台输出"click
"
注:如果使用了vite
,要注意在重新运行前清除缓存,否则可能会出现代码不生效的问题。
保存修改的代码
为了便于代码的分发,需要把在element-ui
中修改的代码保存下来,通过执行命令npx patch-package package-name
会生成一个.patch
文件,里面包含了修改前后的diff
信息。
其中内容为:
diff --git a/node_modules/element-plus/es/components/button/src/use-button.mjs b/node_modules/element-plus/es/components/button/src/use-button.mjs
index 884214f..59c9c6c 100644
--- a/node_modules/element-plus/es/components/button/src/use-button.mjs
+++ b/node_modules/element-plus/es/components/button/src/use-button.mjs
@@ -52,6 +52,7 @@ const useButton = (props, emit) => {
return false;
});
const handleClick = (evt) => {
+ console.log('click')
if (_disabled.value || props.loading) {
evt.stopPropagation();
return;</font>
至此,只要执行patch-package
命令即可将patch
中的代码并入到node_modules
对应文件中。为简化此过程,通常在package.json
的scripts
对象中加入"postinstall": "patch-package"
配置,这样每当执行npm install
之后,都会自动执行patch-package
命令。
适用场景
和第二种方法的适用场景类似,但更加适用于修改一些较小的bug
,因为node_modules
中通常是打包后的代码,特别是经过混淆和压缩的代码,修改难度相对较高。另外打补丁的方法也不需要去另外维护仓库。需要注意的是用这种方法修改,需要锁定包的版本,如果后期需要升级包的话,补丁也需要看实际情况去做相应修改。
4.pnpm patch打补丁
和pack-package
类似。
使用命令pnpm patch package-name
,还是以element plus
为例,命令为pnpm patch element-plus
,执行命令后会将对应npm
包复制到一个叫.pnpm_patches
的目录中,如下图所示。
然后就可以在这个新生成的目录中编辑代码,依然在相同位置添加代码console.log('click')
。编辑完成后,执行上图中绿色的提交修改的代码。
此时package.json
中自动多了代码:
"pnpm": {
"patchedDependencies": {
"element-plus": "patches/element-plus.patch"
}
}
同时目录中也多了patches
文件夹,以及element-plus.patch
这个补丁文件,里面也是修改前后的diff
信息。
最后删除node_modules
文件夹,重新安装依赖,查看修改后的代码是否被添加进来。
这种方法的适用场景和使用pack-package
是类似的。
5.动态修改代码(Vue)
由于在vue
中通过ref
可以拿到所使用组件的实例对象,所以理论上我们可以直接修改这个实例对象来达到一些目的。以element-plus
的el-cascader
级联组件为例,查看实例对象:
里面有一个cascaderPanelRef
属性,el-cascader
是基于cascaderPanel
的,它包括了级连组件的核心功能。cascaderPanelRef
中有:
注意到里面有一个handleKeyDown
的方法,这个方法的详细信息并没有在官方文档中所体现,根据其名称,猜测会对键盘方向键的事件进行处理。尝试对其进行修改:
onMounted(() => {
let value = refCascade.value
nextTick(() => {
let cascaderPanelRef = value.cascaderPanelRef
let old = cascaderPanelRef.handleKeyDown
cascaderPanelRef.handleKeyDown = function (...args) {
old.apply(cascaderPanelRef, args)
console.log('keydown')
}
})
})
如上述代码所示,在保持原有功能的基础上,每当触发keydown
事件时,还会在控制台打印keydown
。
由于handleKeyDown
是cascaderPanelRef
对象自身的方法,并非是从原型链上继承的,因此上面所做的修改只在当前组件实例生效,其它同样的组件是不受任何影响的。
注:vue2中的ref可拿到完整的组件实例对象,而vue3中只能拿到组件主动暴露出来的属性或方法,修改受限,这种方法在vue2中更能发挥作用。
总结
在有条件的情况下,尽可能选择第一种方案,可以免去后续维护代码的工作。否则要修改的代码较多的话可以选择第二种方案,同时也可以给作者提PR,若作者接受的话也可以免去后续代码维护的工作。其他情况酌情选择第3、4、5种方案。
Comments | NOTHING