前言
在日常项目中,我们经常遇到一些组件不符合我们使用要求的,遇到简单的只需要加个/deep/
来深度修改样式即可,但是如果碰到组件结构不符合要求或者需要添加新的HTML
元素的时候就手足无措,这篇文章就教大家如何修改别人的组件库,这里拿vant
组件库举个例子
需求
现在手头有个需求需要改造vant里头的预览组件ImagePreviewItem
添加高斯模糊背景,页面效果如下👇:
需求分析
实现原理很简单前景图设为contain
,后景图设置cover
,再加一层黑色透明度的遮罩即可,实现方式如下👇:
<body>
<div class="container"></div>
<div class="mat_class">
<img
src="https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=1991193171,3776224643&fm=26&gp=0.
class="image"
/>
</div>
<div class="mask"></div>
</body>
<style>
body {
margin: 0;
padding: 0;
}
.container {
width: 100%;
height: calc(100vh);
background: url(https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=1991193171,3776224643&fm
no-repeat;
background-size: cover;
filter: blur(10px);
}
.mat_class {
position: absolute;
top: 50%;
-webkit-transform: translateY(-50%);
transform: translateY(-50%);
width: calc(100vw);
z-index: 400;
}
.image {
display: block;
width: 100%;
height: 100%;
object-fit: contain;
}
.mask {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: black;
z-index: 200;
opacity: 0.2;
}
</style>
准备工作
patch-package
是一个用来给其他npm
包打补丁的包,实际原理也是在本工程保存一份修改的代码,只不过不是用全量代码的形式保存,而是保存了git diff
的结果,节省了代码体积
- 安装
patch-package
npm i patch-package --save-dev
- 去
github
下载package.json
里头对应版本的vant
组件源码
开始改造
- 打开
node_module
文件夹下的vant
文件夹,打开package.json
文件,可以看到
"main": "lib/index.js",
"module": "es/index.js",
因为这边我们使用ESM
规范导入,所以使用module
因此需要改造的是vant
文件夹底下的es
文件夹下的image-preview
中的ImagePreviewItem.js
文件
- 因为es编译出来的不是我们熟悉的代码,小改还行,但是如果要大改,对于不熟悉这种语法的朋友来说非常吃力,这就是我们为什么要下载vant源码的原因了
打开vant源码找到src
文件夹下的ImagePreviewItem.js
文件,这就是预览组件的源码,分别添加固定样式和新的HTML
元素:
computed: {
+ containStyle: function containStyle() {
+ const style = {
+ background: 'url(' + this.src + ') no-repeat',
+ backgroundSize: 'cover',
+ };
+ return style;
+ },
imageStyle() {
...
render() {
const imageSlots = {
loading: () => <Loading type="spinner" />,
};
return (
<SwipeItem class={bem('swipe-item')}>
+ <div class={bem('swipe-container')} style={this.containStyle}></div
<Image
src={this.src}
fit="contain"
class={bem('image', { vertical: this.vertical })}
style={this.imageStyle}
scopedSlots={imageSlots}
onLoad={this.onLoad}
/>
+ <div class={bem('swipe-mask')}></div>
</SwipeItem>
);
},
之后执行yarn build
编译到es文件夹中,就生成了前面我们node_module
中的es
文件了
这样只需要把需要改造的代码片段复制到我们的node_module
中修改包源码即可
接下来是最重要的步骤:
- 执行
npx patch-package vant
给vant
打补丁,会将当前node_modules
下的源码与原始源码进行git diff
之后npm
会在项目根目录下的patches
目录中创建一个名为vant+version.patch
的文件,提交到git
,这样别人更新下来同样会起作用。
- 后续只要执行
npx patch-package
命令,就会把项目patches
目录下的补丁应用到node_modules
的对应包中,这个执行时机一般可以设置为postinstall
这个勾子
"scripts": {
"postinstall": "patch-package"
}
- 前面的方式是在项目中应用所有补丁。如果当这个包版本更新后,要单独应用补丁,可以使用
git
执行命令:
git apply --ignore-whitespace patches/package-name+0.44.2.patch
使用
这里只需要给我们已添加的遮罩,图片和背景图另外使用
/deep/
添加动态样式即可,这样可以做到别的模块中的预览效果不受影响(因为未添加大小和额外样式,因此可以保持原有效果)
完整示例🌰:
<template>
<div>
<van-image-preview
v-model="show"
:images="images"
@change="onChange"
:closeable="true"
/>
<button @click="preview">预览</button>
</div>
</template>
<script>
export default {
data() {
return {
show: false,
index: 0,
images: [
'https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=1943289212,3608954242&fm=26&gp=0.jpg',
'https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=1991193171,3776224643&fm=26&gp=0.jpg',
],
};
},
methods: {
onChange(index) {
this.index = index;
},
preview() {
this.show = true;
},
},
};
</script>
<style lang="less" scoped>
/deep/ .van-image-preview__swipe-mask {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: black;
z-index: 200;
opacity: 0.2;
}
/deep/ .van-image-preview__overlay {
background-color: white;
}
/deep/ .van-image-preview__image {
position: absolute;
top: 50%;
transform: translateY(-50%);
width: calc(100vw);
z-index: 400;
}
/deep/ .van-image-preview__swipe-container {
width: 100%;
height: calc(100vh);
filter: blur(10px);
}
</style>
小插曲
在之前我直接对node_module
进行修改,希望可以即刻看到效果,但是出现了问题,怎么修改node_module
发现都不生效
在一番思考后发现是dllPlugin
插件缓存的问题
为了杜绝缓存现象,现在在每次修改并且执行npx patch-package vant
命令之前都要先执行一遍yarn build:dll
清除缓存
有用的工具
很多时候,我们会遇到template
模板中变量报错的问题,可以通过如下方式在控制台打印结果
// 只在测试环境中可以使用
// main.js
Vue.prototype.$log = window.console.log;
// 在组件内部调用
<div>{{$log(info)}}</div>
总结步骤
- 安装
patch-package
,下载对应版本vant
源码 - 在
vant
源码中修改代码后编译,将生成es
文件夹中对应代码复制到node_module
中 - 有
dllPlugin
先执行yarn build:dll
清除缓存,之后执行npx patch-package vant
生成vant+version.patch
文件,并提交 4、后续有更新时执行postinstall
或git
命令应用新版本补丁
扩展 🏆
如果你觉得本文对你有帮助,可以查看我的其他文章❤️: