背景
最近接手了一个公共组件的开发,这个组件的作用是供接入方收集用户的使用体验,涉及红线,这里就不放出产品图片了
大体的功能:
- 用户可以评星
- 根据星级做出对应的操作,如:3星及以上则自动上报,然后弹出谢谢反馈
- 3星以下视为不太满意,弹出不太满意原因:tags选项
- 用户点击空白处或者叉掉组件自动上报提交
技术
- react17
- antd4.x
- less
最后需要发布到npm,并支持sdk的方式引入
开发中遇到的问题
主要讲一下遇到的样式冲突问题,其实这些问题都是一环扣一环,有上一个问题才出现的下一个问题
前缀污染
修改antd组件的样式时在本地时生效的,打包后在平台上使用失效了 因为我这里使用了rate评分组件,所以我就拿这个组件举例子 应产品需求图,要在原来的rate组件上修改⭐️的颜色,自然而然先去查看对应的class ant-rate-star,找到对应的类名如下
所以理所当然的写出了如下代码
.ant-rate-star-full {
color: #FFD392;
}
这样看起来没问题吧,但是在有些平台上使用就会出现样式不生效的问题。 于是打开平台的控制台先查看源码,发现上面的代码并没有丢失。只是类名的前缀变了
于是去请教平台的开发者,原来是他使用了antd提供的自定义前缀(如下图)。
同时自定义变量@ant-prefix导致css中的类名前缀都变了,知道问题后就好解决了,不就是外部定义的@ant-prefix污染了内部的吗,究其根本就是组件没有引入自己的@ant-prefix变量
于是加入以下代码就可以解决
@root-entry-name: 'default';
@import (reference) '~antd/es/style/themes/index.less';
上面代码执行完后,还会引入变量@ant-prefix,于是组件内部有自己的前缀,就不会受到外部的影响了
同类名污染
还是这个rate组件,有个使用组件的平台使用的antd版本是2.x版本,出现了下面的情况
查看dom元素发现2.x的⭐️是用的伪类实现的,而4.x使用的是svg实现的,所以同一个类名实现了两次⭐️
所以要从根本解决问题害得在上一步的基础上将antd的类名都更改
- 在代码中加入前缀更改
<ConfigProvider prefixCls='dd-rc-feedback' iconPrefixCls='dd-rc-feedback-icon'>
</ConfigProvider>
这一步的作用是将antd的class中的前缀ant都变成定义的dd-rc-feedback
- 在webpack中自定义变量,参考webpack文档www.webpackjs.com/loaders/les…
lessOptions: (options) => {
options.lessOptions.modifyVars = {
'ant-prefix': 'dd-rc-feedback',
'iconfont-css-prefix': 'dd-rc-feedback-icon',
}
return options
}
这一步的作用是将less中的变量ant-prefix定义为dd-rc-feedback
经过以上两个操作,组件内以ant-prefix为前缀的类名的样式都不会影响到外部
变量污染
还记得在前面为了解决前缀污染,加入了两行代码吗?主要作用就是引入antd自定义的变量@ant-prefix 但是问题就出在这,引入这个变量的同时又引入了其他主题变量
这就会出现一个问题: 因为这些变量都是在全局定义的,如果使用组件的平台自定义antd的变量(如:自定义主题),就会出现变量被组件的变量覆盖(因为组件肯定是后引入的,会覆盖最初的变量)
要解决以上问题思路很简单,就是在控制一下组件中antd变量的作用范围,最直接的就是在前面加个类名。社区里有提供这么一个plugins:postcss-selector-namespace,他的作用就是可以在所有class再加个class,于是加入以下代码
// postcss.config.js
module.exports = {
plugins: {
'postcss-selector-namespace': {
namespace(css) {
return '.dd-rc-feedback'
}
}
}
}
最终css就会这样
最终,经过以上3种方式的处理,达成了组件样式与宿主样式完全隔离的效果