修改组件库源码来获得符合需求的组件

项目需求多种多样,会出现开源组件库中的组件无法满足需求或者有 bug 的情况,可以区分以下情况,进行相应的处理。

以下示例以在 Vue2 中使用 Ant Design Vue 进行讲解。

样式修改

局部修改

这里我们以组件 Button 按钮为例,该组件文档上只枚举了固定的几种按钮类型,并确定了相关的颜色。自定义修改按钮的背景色及相关色彩是个常见的需求。

现进行自定义样式处理。

<template>
  <div>
    <a-button class="custom-btn">Default</a-button>
  </div>
</template>
<style lang="less" scoped>
.custom-btn {
  background: blue;
  color: white;
}
</style>

将代码运行,可以看到按钮色彩发生了改变。这里我们并没有使用深度选择器。

我们在浏览器中查看具体的组件dom解析

<div id="app">
  <div data-v-93538cd2="">
    <button data-v-93538cd2="" type="button" class="custom-btn ant-btn">
      <span>Default</span>
    </button>
  </div>
</div>

可以看到,我们在组件上添加的类选择器名称 custom-btn 直接渲染在原生 button 上。

那我们可以简单理解,当我们自定义的类,直接渲染在我们需要自定义样式的 dom 元素上,则不需要进行特殊的处理,直接可以自定义样式。

我们找一个稍微复杂一点的 Tabs 标签页 组件,进一步说明。

<template>
  <div>
    <a-tabs class="custom-tabs">
      <a-tab-pane key="1" tab="Tab 1">
        Content of Tab Pane 1
      </a-tab-pane>
      <a-tab-pane key="2" tab="Tab 2" force-render>
        Content of Tab Pane 2
      </a-tab-pane>
    </a-tabs>
  </div>
</template>

先进行无任何处理的样式修改:

<style lang="less" scoped>
.custom-tabs {
  .ant-tabs-tab {
    border: 1px solid blue;
  }
}

样式没变化。。。我们看下该段样式编译后的结束:

<style type="text/css">
.custom-tabs .ant-tabs-tab[data-v-93538cd2] {
  border: 1px solid blue;
}
</style>

看到 .ant-tabs-tab[data-v-93538cd2] 大概知道啥原因了。在我们自己的代码中,每一个dom节点,都会加上 scope 属性如 data-v-93538cd2,规避单页项目不同业务组件之间的样式相互影响。而现在使用的是组件库的组件,组件渲染后的dom上并没有 scope 属性。所以这里的样式是由于匹配不到,所以没生效。

这里的类选择器名称 ant-tabs-tab 是在浏览器查找需要自定义样式的 dom 节点上找到,那我们试试深度选择器 ::v-deep

<style lang="less" scoped>
.custom-tabs {
  ::v-deep .ant-tabs-tab {
    border: 1px solid blue;
  }
}

到这样式发生了变化。这里相对上面的例子,明显的变化是自定义类不在我们直接想自定义样式的 dom 节点上,我们需要自己在浏览器中查找想自定义样式的 dom 节点上已有的类,而这个 dom 类是在子组件中,不与父组件在同一dom层级。

在我们实际开发使用中,组件库组件未必挂载在当前组件内容中,比如挂载在页面body下。这里我们以 Modal 对话框组件为例。

<template>
  <div>
    <a-modal class="custom-modal" :visible="true" title="Basic Modal">
      <p>Some contents...</p>
      <p>Some contents...</p>
      <p>Some contents...</p>
    </a-modal>
  </div>
</template>
<style lang="less" scoped>
.custom-modal {
  .ant-modal-title {
    font-weight: bold;
    color: red!important;
  }
}
</style>

嗯,没生效。。。,那分析下,编译后的css代码在浏览中咋样。

<style type="text/css">
.custom-modal .ant-modal-title[data-v-93538cd2] {
  font-weight: bold;
  color: red!important;
}
</style>

看到 .ant-modal-title[data-v-93538cd2] 同样大概知道啥原因了。原因与上文一样,所以这里的样式是由于匹配不到,所以没生效。

那修改下样式,去除 scope 属性。

<style lang="less">
.custom-modal {
  .ant-modal-title {
    font-weight: bold;
    color: red!important;
  }
}
</style>

嗯,生效了。不过这里 modal 组件加上 custom-modal。那后续其他业务组件,也需要对 modal 组件进行样式自定义,名称极有可能也叫 custom-modal。

而由于上面我们并没有添加 scope 属性,这个样式是会造成全局影响。所以,更合理的做法,是对当前业务组件添加个容器类名。如这里是登录组件。那加个 login-wrap 类。

<style lang="less">
.login-wrap {
  .custom-modal {
    .ant-modal-title {
      font-weight: bold;
      color: red!important;
    }
  }
}
</style>

至此,对组件库组件的样式处理,目前这三类基本涉及到绝大部分场景。

下面对 vue 中使用深度选择器进一步讲解。

当项目中使用的 css 原生样式,则可以使用 >>> 深度选择器来修改第三方组件的样式。

当项目中使用的 css 预处理器,如 less 或 scss, 则可以使用 /deep/ 或者 ::v-deep 深度选择器来修改外用第三方组件的样式,其中深度选择器 ::v-deep 比较通用。

在vue3 中可以使用 :deep(<inner-selector>) 来深度选择到你要修改的样式,注意:这里没有空格。>>>/deep/::v-deep 在 vue3 中均以被弃用,虽然样式仍然生效,但是 Vue 已不推荐。

具体弃用的原因可以翻看这篇文章 scoped-styles-changes

全局修改

如果你要修改全局的样式,你可以在全局样式文件中写样式覆盖,引入到 main.js 中即可全局生效。

import "./src/styles/global.less";

内容修改

这里我们以 upload 组件为例。

拷贝源码进行修改

特定需求:在原有组件展示的信息基础上,还要显示上传文件的大小。

首先找到对应的 upload 组件:node_modules => ant-design-vue => es => upload。

对 upload 文件夹进行整体拷贝,将之粘贴到项目代码中,并对其进行修改。这样既可满足特定业务需求,又不会影响原组件在其他常规业务中的使用。

首先修改复制过来的 upload 组件对文件的路径引用,对依然还需要引用 node_modules 下的 ant-design-vue 组件库的代码文件,则批量修改路径为。

import xxx from 'ant-design-vue/es/xxx'

然后在 UploadList.js 中修改对应的代码

var preview = file.url ? [h(
  'a',
  ...
  [file.name]
), downloadOrDelete] : [h(
  'span',
  ...
  [file.name]
), downloadOrDelete];

修改后的代码

var preview = file.url ? [h(
  'a',
  ...
  [file.name, h('span', { style: { marginLeft: '20px' } }, [(file.size / 1024).toFixed(2) + 'kb'])]
), downloadOrDelete] : [h(
  'span',
  ...
  [file.name, h('span', { style: { marginLeft: '20px' } }, [(file.size / 1024).toFixed(2) + 'kb'])]
), downloadOrDelete];

效果对比:

局部使用

在需要使用的文件中引入、注册、使用

<template>
  <custom-upload
    name="file"
    action="https://www.mocky.io/v2/5cc8019d300000980a055e76"
  >
    <a-button> <a-icon type="upload" /> Click to Upload </a-button>
  </custom-upload>
</template>
<script>
  import customUpload from '@/components/pc/upload'

  export default {
    components: { customUpload },
  };
</script>

全局使用

在main.js中进行全局引入。

import customUpload from '@/components/upload'
Vue.use(customUpload)

然而业务代码中并未找到 customUpload 组件。

我们翻看下 upload 组件 index.js 的实现。

import Upload from './Upload';
...
Upload.install = function (Vue) {
  ...
  Vue.component(Upload.name, Upload);
  ...
};

export default Upload;

可以看到,Vue.component 进行全局注册的组件名引用的是 Upload 文件的 name。

我们找到 Upload.js 文件,可以看到

...
export default {
  name: 'AUpload',
  ...
}

这里依然用的是以前的name,所以这里需要修改为我们自定义的组件名称 CustomUpload。

到这,刷新下界面,可以看到效果已经显现。

此种方式,需要注意组件库版本的锁死,否则当组件库进行版本升级后,复制过来的代码与 node_modules 中组件库的代码可能已不再匹配。

修改源码并打包替换

上面方式是对编译后的代码进行更改。那我们也可以对组件库源码进行修改,并进行编译,将编译后的文件进行替换。

  1. 我们进入 ant-design-vue git 地址[https://github.com/vueComponent/ant-design-vue]
  2. 由于现在的项目还是基于 vue2 项目,所以这里选择组件库的 tag 为 1.7.8,由于我们不需要考虑项目的其他分支或者tag代码,所以可以直接对当前code进行zip下载。
  3. 下载解压后,对当前目录执行 npm i 命令,包下载完成后,找到 package.json 文件,看到可以执行 npm run start 命令,进行项目启动。

到这里项目已经成功启动了,那我们也可以展开对 upload 组件代码的更改。但目前我们还无从下手,不知道从哪里进行更改。

那我们回到最开始项目执行的命令,npm run start,那实际执行的语句是 cross-env NODE_ENV=development webpack-dev-server --config webpack.config.js

从上一步我们知道项目启动的配置文件是 webpack.config.js,我们找到这个文件,可以看到一段代码

  ...
  entry: {
    app: './examples/index.js',
  },
  ...

我们知道了应用的入口文件是 /examples/index.js,那我们找到这个文件,可以看到

import 'babel-polyfill';
import Vue from 'vue';
import App from './App.vue';
import Antd from 'ant-design-vue';
import 'ant-design-vue/style.js';

Vue.use(Antd);

new Vue({
  el: '#app',
  render: h => h(App),
});

到这,已经看到页面渲染的代码在 App.vue 文件中。我们点开这个文件,可以看到里面的代码与当前项目展示一致。那我们对 App.vue 文件进行代码处理,页面内容也跟着进行变化。

此时回到最初的问题,我们是希望修改 upload 组件的源码,但该如何进行引入以及修改呢。

我们再回到上面一段代码,可以看到我们引入了 ant-design-vue 组件库,以及 ant-design-vue/style.js 样式代码。可是翻看下 package.json 的依赖,我们并没有看到 ant-design-vue,再说,我们现在修改的就是这个框架,框架都没进行发布,怎么可能会有这个依赖包呢。这岂不是鸡生蛋蛋生鸡的问题。所以,这里引入的不是 node_modules 里面的依赖。

那我们再翻看下 webpack.config.js 文件,是否是编译工具进行了处理。

  ...
  alias: {
    'ant-design-vue': path.join(__dirname, './components'),
    vue$: 'vue/dist/vue.esm.js',
  },
  ...

到这里就明白了,原来 ant-design-vue 是别名,对应的路径是现有项目 components 里面的组件代码。

找到 ./components/index.js 文件,结合 ./examples/index.js 可以看到是组件进行了全局注入。

./components/index.js

components = [...]
const install = function(Vue) {
  components.map(component => {
    Vue.use(component);
  });
};

./examples/index.js

...
import Vue from 'vue';
import Antd from 'ant-design-vue';
import 'ant-design-vue/style.js';

Vue.use(Antd);
...

那到这里,我们明白,在 ./examples/App.vue 文件中直接使用 upload 组件,并对 ./components/upload下的组件代码进行修改,即可看到变化。

我们在 ./examples/App.vue 中添加代码

<template>
  <a-upload
    name="file"
    action="https://www.mocky.io/v2/5cc8019d300000980a055e76"
  >
    <a-button> <a-icon type="upload" /> Click to Upload </a-button>
  </a-upload>
</template>

接着,我们找到 ./components/upload/UploadList.jsx 文件,对其进行修改。

const preview = file.url
  ? [
      <a
        ...
      >
        {file.name}
        <span style="margin-left: 20px;">{ (file.size / 1024).toFixed(2) + 'kb' }</span>
      </a>,
      ...
    ]
  : [
      <span
        ...
      >
        {file.name}
        <span style="margin-left: 20px;">{ (file.size / 1024).toFixed(2) + 'kb' }</span>
      </span>,
     ...
    ];

可以看到,相比对编译后的代码进行修改,对组件库源码进行修改会明显简单一些。

到这可以执行打包命令 npm run dist。可以看到项目中生成了三个编译后的文件目录,分别为es,lib,dist。

我们将这三个文件进行复制,替换我们日常开发项目下的 node_modules 中的 ant-design-vue中的同名目录。

然后对项目进行重启,即可看到效果。到这里如果想将当前改动发布到私有库中,可以参考这篇文章 公共资源包发布流程详解

但这种弊端明显:

  1. 这种改动会造成所有引用该组件库的项目均受影响,如果是bug修复,那是良性的影响,但是在日常开发中,遇到更多的是组件本身不满足特定业务的需求,进而需要修改原有组件的功能,这种改变,对A项目是适当的更改,但是对B项目可能就是不恰当的变动。
  2. clone开源组件库进行定制开发后,将无法随开源库的迭代逐步消除本身的bug。

这种方式除非严重的bug修正,如果是定制改动,明显不如上一种方式。而bug修正,更合理的方式是在原仓库下提 PR,让作者进行合并。

patch-package 打补丁

当在项目中修改了 ant-design-vue 的源码,并且需要将改动同步到团队成员,那也可以使用 patch-package 对组件库打补丁,将修改同步到项目代码上。

我们先进行安装 npm i patch-package -S

然后进行源码的修改:找到 node_modules 目录中 ant-design-vue 下 upload 组件源码

在 UploadList.js 中进行修改

var preview = file.url ? [h(
  'a',
  ...
  [file.name]
), downloadOrDelete] : [h(
  'span',
  ...
  [file.name]
), downloadOrDelete];

修改后的代码

var preview = file.url ? [h(
  'a',
  ...
  [file.name, h('span', { style: { marginLeft: '20px' } }, [(file.size / 1024).toFixed(2) + 'kb'])]
), downloadOrDelete] : [h(
  'span',
  ...
  [file.name, h('span', { style: { marginLeft: '20px' } }, [(file.size / 1024).toFixed(2) + 'kb'])]
), downloadOrDelete];

执行命令创建组件库补丁文件:npx patch-package ant-design-vue,这里 ant-design-vue 指的是被修改的依赖包的名字,不是被修改的文件的名字。

执行该命令后会在项目根目录中自动创建一个 patches 文件夹,该文件夹中会出现一个 修改依赖包名称+version.patch 的补丁文件。本次操作这里出现的文件名称为 ant-design-vue+1.7.8.patch。

那 .patch 文件为什么能作为补丁文件,我们打开 ant-design-vue+1.7.8.patch 文件看一下里面内容。

diff --git a/node_modules/ant-design-vue/es/upload/UploadList.js b/node_modules/ant-design-vue/es/upload/UploadList.js
index e0dfa8a..573ac90 100644
--- a/node_modules/ant-design-vue/es/upload/UploadList.js
+++ b/node_modules/ant-design-vue/es/upload/UploadList.js
@@ -234,7 +234,7 @@ export default {
             }
           }
         }]),
-        [file.name]
+        [file.name, h('span', { style: { marginLeft: '20px' } }, [(file.size / 1024).toFixed(2) + 'kb'])]
       ), downloadOrDelete] : [h(
         'span',
         {
@@ -249,7 +249,7 @@ export default {
             title: file.name
           }
         },
-        [file.name]
+        [file.name, h('span', { style: { marginLeft: '20px' } }, [(file.size / 1024).toFixed(2) + 'kb'])]
       ), downloadOrDelete];
       var style = file.url || file.thumbUrl ? undefined : {
         pointerEvents: 'none',

其实就是一些 git diff 记录描述,补丁原理呼之欲出 —— patch-package 会将当前 node_modules 下的源码与原始源码进行git diff,并在项目根目录下生成一个patch补丁文件。

那测试是否生效,首先删除 node_modules 文件夹。然后修改根目录下的 package.json 文件,在 scripts 中添加 “postinstall”: “patch-package”。

"scripts": {
  "postinstall":"patch-package"
},

执行 npm i,重新安装依赖。

D:\project\personal\frontEndTestProject\modern_dev\my_project>npm i
...
npm WARN deprecated request@2.88.2: request has been deprecated, see https://github.com/request/request/issues/3142
...
> my_project@0.1.0 postinstall
> patch-package

patch-package 8.0.0
Applying patches...
ant-design-vue@1.7.8 ✔

added 1468 packages in 2m

可以看到源码中被修改的代码还在。这里是因为 postinstall 是 Node.js 应用程序中的 NPM Scripts 钩子,它表示在 npm i 执行完毕后自动执行的脚本命令。

至此补丁文件已经生成完毕,我们需要将它提交到 git 中,直接执行常规 git 操作即可。

当其他同事拉下代码后如何应用补丁呢?已经下载过依赖包的项目,直接执行 npx patch-package,即可将补丁打上。如果是新拉下来的项目,直接执行 npm i,则在下载依赖包结束后,自动执行打上补丁的过程。

如果你安装的包版本和你之前生成的补丁中记录时的包版本不一样,npx patch-package 会报错,通过提示你可以更方便的定位问题

my_project>npx patch-package

patch-package 8.0.0
Applying patches...
ant-design-vue@1.7.8 ✔

Warning: patch-package detected a patch file version mismatch

  Don't worry! This is probably fine. The patch was still applied
  successfully. Here's the deets:

  Patch file created for

    ant-design-vue@1.7.8

  applied to

    ant-design-vue@1.7.0

  At path

    node_modules/ant-design-vue

  This warning is just to give you a heads-up. There is a small chance of
  breakage even though the patch was applied successfully. Make sure the package
  still behaves like you expect (you wrote tests, right?) and then run

    patch-package ant-design-vue

  to update the version in the patch file name and make this warning go away.

---
patch-package finished with 1 warning(s).

如果组件库有问题需要及时处理,并需要同步到其他团队成员,这是一种低成本又规范化的方式。

  • 19
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 要修改WPF组件源码,需要遵循以下步骤: 1. 获取源码:首先,需要从组件的官方资源开源代码中获取源代码。这可能需要注册账户或遵循一些特定的许可证要求。 2. 编译源码:得到源码后,您需要在本地编译它。这可能需要安装适当版本的开发工具和依赖项。确保您按照提供的指南设置好环境。 3. 理解代码结构:仔细阅读源码,理解代码的组织结构以及各个部分的功能和用途。这可以帮助您找到您希望修改的具体部分的位置。 4. 进行修改:根据您的需求,找到要修改代码文件,使用合适的编辑器打开它们。进行您的修改。确保您理解修改的影响,以及它们可能会对现有功能和其他组件产生的影响。 5. 编译和测试:在您进行了所需的修改后,重新编译整个组件。确保没有出现编译错误。然后,使用您修改后的组件来进行测试,确保它们按预期工作,不会引入新的错误或问题。 6. 提交和发布:如果您希望将您的修改应用于整个WP组件,您可以将您的修改提交给项目维护者。这可能需要通过某种形式的版本控制系统或协作平台完成。如果您打算以独立的形式使用您的修改,您可以直接将他们应用于您的项目中。 请注意,修改WPF组件源码需要深入了解WPF开发和编程。建议在进行修改之前,参考相关的文档、教程和开发指南,以确保您做出的修改正确无误,并且符合最佳实践。 ### 回答2: 要改变WPF组件源码,可以遵循以下步骤: 1. 下载并安装Visual Studio:确保已安装适用于WPF开发的最新版本的Visual Studio。 2. 导入组件:将组件源码文件夹导入到Visual Studio中,可以通过右键点击“解决方案资源管理器”面板中的“添加现有项目”选项来完成。 3. 修改源码:在Visual Studio中打开组件源码文件,可以在编辑器中对源码进行修改。根据自己的需求,可以更改组件的外观、行为或其他属性。 4. 构建和调试:在修改源码后,使用Visual Studio的构建选项来生成修改后的组件。然后,使用调试器来检查和测试新的组件行为。 5. 应用更改:将编译后的新组件文件(通常是.dll文件)替换原有的组件文件,或将其添加到项目中的引用中,以便在项目中使用新的修改后的组件。 需要注意的是,在修改WPF组件源码时,应该了解WPF的工作原理和代码结构,并遵循相关的编码规范。同时,谨慎修改源码,避免引入错误和不稳定的行为。在修改源码之前,最好对组件有一定的了解和经验,确保改动的合理性和可靠性。 ### 回答3: 要修改WPF组件源码,可以按照以下步骤进行: 1. 首先,确保你具备必要的开发工具,如Visual Studio等。 2. 在Visual Studio中,打开WPF组件的项目文件。通常,这些项目文件是以.sln或.csproj为扩展名的。 3. 导航到需要修改的WPF组件源码文件。该文件通常具有.cs扩展名。 4. 阅读和理解源码文件的结构和逻辑。了解组件的工作原理是进行修改的前提。 5. 根据需求进行修改。你可以修改属性、方法、事件等各个方面。确保你的修改不会导致组件的功能出现问题。 6. 保存并构建项目。确保没有出现编译错误。 7. 如果你希望自己的修改能够被其他项目使用,可以将修改后的组件打包为或NuGet包。这样,其他项目就可以直接引用你的组件。 请注意,修改WPF组件源码可能需要具备一定的编程技术和WPF开发经验。在进行修改之前,最好事先对WPF的基本原理有一定的了解。此外,记得备份原始源码,以防不慎修改导致无法恢复。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

定栓

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值