备份自原有库的 issue
@afc163:
http://aliceui.org/docs/javascript.html#%E5%9C%A8-arale-%E4%B8%AD%E4%BD%BF%E7%94%A8%E6%A0%B7%E5%BC%8F
在上面的链接中提到,目前在 Arale 中使用样式有两种方案。一种是使用标准的 link 标签,一种是在 JS 中 require 样式文件的方式。
其中,后一种方式由于比较对用户友好方便,成为 Alice 中的一个重要实践。目前使用了第二种方法载入样式的组件有 arale.dialog
、alipay.xbox
、alipay.poptip
,实践中发现有较为严重的冲突问题。
主要原因是支付宝的页面上已经使用了很多 ui-poptip、ui-dialog、ui-xbox 等 className ,因此这些组件的样式都和页面互相造成了冲突。
冲突主要分为两部分,一是其他样式对模块自身的影响覆盖,二是模块自身对其他样式的覆盖。
1、解决其他样式对模块自身的影响覆盖。
现在解决这个问题的方案是使用 classPrefix 来替换模板中的类命名空间,然后自己写样式来定义。
比如在 alipay.xbox 组件中,模板 xbox.tpl 和 样式文件 xbox.css 如下:
<div class="ui-xbox">
<div class="ui-xbox-container"></div>
</div>
.ui-xbox { ... }
.ui-xbox-container { ... }
将 classPrefix 置换为 ui-newxbox 后,模板变为了:
<div class="ui-newxbox">
<div class="ui-newxbox-container"></div>
</div>
这样页面上的 ui-xbox 类就不会再影响我们的结构了。第一个问题的解决方案是能解决问题但比较麻烦的,这个方案更大的用途是用来做自定义的样式。
2、解决模块自身对其他样式的影响覆盖。
这个问题是本 issue 主要要解决的问题。 继续看上面的例子:
.ui-xbox { ... }
.ui-xbox-container { ... }
无论 classPrefix 是否自定义,这段样式始终会通过 importStyle 的方式载入,也就有可能对页面上的其他 ui-xbox 产生冲突。
importStyle('.ui-xbox{...};.ui-xbox-containter{...}');
要解决这个问题,目前想到的有以下几个方案:
-
当 classPrefix 自定义时,说明开发者不再需要使用默认样式,需要自己写相关样式,就不再载入 xbox.css 。
方案缺点:当用户需要避免自身模块对页面其他地方冲突时,必须自定义 classPrefix 。
-
统一使用 ai-
开头代替目前的 ui-
前缀,规避这个问题。
方案缺点:没有实际解决问题,未来的冲突还可能存在,特别是同一组件的不同版本的问题。
-
在 spm 打包时,把样式中的类的主要名称全部替换成 classPrefix 的默认值。比如上面的 xbox.css,假设 classPrefix 为 alipay-xbox,将会被替换成:
.alipay-xbox-1_0_0 { ... }
.alipay-xbox-1_0_0-container { ... }
就是将所有的 ui-xbox
替换成 alipay-xbox-1_0_0
这样 family、name 和版本的集合,同时也需要修改相应的模板。这样生成的奇异的默认样式就基本上不会和已有的样式产生冲突,并且不同版本之间也会有隔离。
方案缺点:对样式书写有一定要求。而且替换的 ui-xbox 和被替换的 alipay-xbox 分别用什么方式进行指定还不清楚。
综上,方案 3 是我们(我)比较中意的方案,但也有很多问题要解决。希望尽快解决这个问题,并将在 spm2 进行实现。
或者大家有没有什么更好的方案?
@fool2fish @leoner @lepture @lifesinger @popomore @shaoshuai0102 @noahlu
最终解决方案
package.json 配置 styleBox 会支持此功能
"spm": {
"styleBox": true
}
spm build
会有两方面的处理
对于 require 的样式
这部分样式会打包进来,并添加前缀,其他样式不处理。
define(function(require, exports, module) {
require('./xbox.css');
});
转换成
define('alipay/xbox/1.0.0/xbox', [..., './xbox.css'], function(require, exports, module) {
require('./xbox.css');
});
define('alipay/xbox/1.0.0/xbox.css', [], function() {
seajs.importStyle('.alipay-xbox-1_0_0 .ui-xbox{} ...');
});
对于 js
会处理所有的 js 脚本,在下方如下添加
define('alipay/xbox/1.0.0/xbox', [..., './xbox.css'], function(require, exports, module) {
require('./xbox.css');
module.exports.outerBoxClass = "alipay-xbox-1_0_0";
});
widget 的处理
如果组件存在 outerBoxClass,在生成 element 的时候会生成一个 outerBox
<div class="alipay-xbox-1_0_0">
<div class="ui-box"></div> // <= 这是 element
</div>