「强烈推荐」实用性超强的vant组件魔改教程

3,780 阅读4分钟

前言

在日常项目中,我们经常遇到一些组件不符合我们使用要求的,遇到简单的只需要加个/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组件源码

开始改造

  1. 打开node_module文件夹下的vant文件夹,打开package.json文件,可以看到
"main": "lib/index.js",
"module": "es/index.js",

因为这边我们使用ESM规范导入,所以使用module

因此需要改造的是vant文件夹底下的es文件夹下的image-preview中的ImagePreviewItem.js文件

  1. 因为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中修改包源码即可

接下来是最重要的步骤:

  1. 执行npx patch-package vantvant打补丁,会将当前node_modules下的源码与原始源码进行git diff

之后npm会在项目根目录下的patches目录中创建一个名为vant+version.patch的文件,提交到git,这样别人更新下来同样会起作用。

  1. 后续只要执行npx patch-package命令,就会把项目patches目录下的补丁应用到node_modules的对应包中,这个执行时机一般可以设置为postinstall这个勾子
"scripts": {
  "postinstall": "patch-package"
}
  1. 前面的方式是在项目中应用所有补丁。如果当这个包版本更新后,要单独应用补丁,可以使用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>

总结步骤

  1. 安装patch-package,下载对应版本vant源码
  2. vant源码中修改代码后编译,将生成es文件夹中对应代码复制到node_module
  3. dllPlugin先执行yarn build:dll清除缓存,之后执行npx patch-package vant生成vant+version.patch文件,并提交 4、后续有更新时执行postinstallgit命令应用新版本补丁

扩展 🏆

如果你觉得本文对你有帮助,可以查看我的其他文章❤️:

👍 「多图预警」那些年,被blob虐过的程序猿觉醒了!

👍 vue3实战笔记 | 快速入门🚀

👍 10个简单的技巧让你的 vue.js 代码更优雅🍊

👍 零距离接触websocket🚀

👍 Web开发应了解的5种设计模式