Code Monkey home page Code Monkey logo

brix's Introduction

Brix

基于淘宝 Kissy1.3框架的一淘通用组件框架。

如何使用

<link type="text/css" rel="stylesheet" href="http://a.tbcdn.cn/apps/e/brix/2.0/brix-min.css" charset="utf-8">
<script type="text/javascript" src="http://a.tbcdn.cn/s/kissy/1.3.0/seed-min.js"></script>
<script type="text/javascript" src="http://a.tbcdn.cn/apps/e/brix/2.0/brix-min.js" bx-config="{autoPagelet:true}"></script>
<script type="text/javascript">
	//业务代码,自动构建
	KISSY.ready(function(S){
		//pagelet自动构建完成
		Brix.ready(function(){
			//pagelet的实例
			Brix.pagelet.ready(function(){
				//拿到组件实例
				var brick = Brix.pagelet.getBrick('#id');
			});
		});
	});
</script>

组件库核心

  • brix.js : 框架的配置入口类
  • chunk.js : brick.jspagelet.js 类的父类
  • tmpler.js : 模板解析类,用 xtemplate 渲染。
  • dataset.js : 数据管理类,数据变化时,通知模板引擎更新
  • brick.js : 组件基类,所有组件继承此类
  • pagelet.js : 组件管理器,对组件实现渲染
  • demolet.js : demo组件管理器,根据业务组件的data.json和template.html显示预览

类关系图

Brix 类关系图

组件钩子

  • bx-name : 组件名称
  • bx-path : 组件地址,一般是包名 + 文件路径,核心组件可以省略配置
  • bx-config : 组件配置,动态渲染时候的参数
  • bx-tmpl : 组件模板,这个钩子和 bx-datakey组合使用,在数据更新时对模板重新渲染。具体写法详见: core/brix.html
  • bx-datakey : 组件数据对象 key 值,可以有多个 key,以 , 分割,且支持对象的子对象,如 “X.Y,Z.Y.X”

开发环境需求

开发

git clone git://github.com/etaoux/brix.git
cd brix

# If you have installed Grunt globally in the past, you will need to remove it first
npm uninstall -g grunt

# 安装 Grunt
npm install -g grunt-cli

# 以及插件模块
npm install

# 使用 Grunt 运行自动监视文件变化编译
grunt

目录结构

  • demo : 组件开发的demo目录,一般存放静态的html文件,名称以组件名命名。
  • dist : 工具打包生成的目标目录,不用人为进行编辑。
  • src : 源文件目录,你懂的;组件存放在gallery,再以组件名命名的组件目录,组件的js文件是以index.js命名,如下拉框组件:gallery/dropdown/index.js
  • tasks : 存放打包脚本目录
  • tools : 辅助工具目录

说明

  • 组件开发使用一般使用到src, demo两个目录, src是组件的源代码目录,进入目录后,再选择gallery还是style,同时开发时的demo文件存放在demo目录,对应gallery或style。这两个目录是直接提交到master分支。
  • 文档是在gh-pages-source分支,主要是操作_post目录,gallery组件直接放在_post/gallery目录下; style放在_post/style目录下。
  • gh-pages-source分支下不要去修改src与demo目录,提交也是无效的。
  • 组件中使用到的图片,都传到tps中,项目中直接使用链接地址。

brix's People

Contributors

bryant1410 avatar cyjake avatar haitaojarvis avatar huacnlee avatar keyapril avatar kirk-ye avatar limu avatar miaojing avatar nuysoft avatar retrythat avatar sapjax avatar shenhua1985 avatar shenhua19850119 avatar xthsky avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

brix's Issues

grunt-css的cssmin存在bug

测试用例如下:

.a {
  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff4444', endColorstr='#ff2222', GradientType=0);
}

通过grunt-css的cssmin压缩后,#ff4444会变成#f44,这样IE的filter就失效了。

暂无合适的工具替代,先取消css压缩吧。brix-min.css 先从 brix.css 拷贝过来。

如何理解 Chunk 的设计和实现思路?

Chunk 继承了 KISSY.RichBase、KISSY.Base、KISSY.Attribute、KISSY.Event 的功能,组合了 Dataset、Tmpler,还是 Brick、Pagelet 的父类。

感觉 Chunk 类似于 Model + View 的混合体,因为功能点上几乎等价。但是 chunk、bricks、pagelete 并不以 MVW(Model-View-Whatever)的结构分层,而是以模板、数据、事件&行为划分,Chunk 中包含了模板、数据,事件则在 Brick、Pagelete 中支持。刚阅读 chunk.js 时,觉得这种设计思路跳出了吵闹的 MVW 模式,隔了个周末再读,又感觉似乎是 MVW 的概念简化版,详细阐述下?

业务子组件库共用CSS如何处理?

直通车重构的系列组件有一些公用的CSS,内容比较简单.比如:

.fl{float:left;display:inline;}
.fr{float:right;display:inline;}
.mt15{margin-top:15px;}
.mb15{margin-bottom:15px;}
.ml15{margin-left:15px;}
.tl{text-align:left;}
.tr{text-align:right;}
.tc{text-align:center;}
.none{display:none;}

我们希望每个组件可以单独共享,那这类css如何做共享?冲突如何处理?写法是否该有些约定?

请不要在各个组件的 JS 里面直接 require css 文件

我们不能将前端架构的事情也一并搞了,你无法预计组件使用者如何来分布他们的 JS, CSS 部署结构
作为一个基础组件,我们应当保持原生态, CSS 和 JS 如何安放应当由组件使用者自己来决定。

以面包屑为例:

KISSY.add("brix/gallery/breadcrumbs/index",function(a,b){
    function c(){
        c.superclass.constructor.apply(this,arguments)
    }
    return c.ATTRS={},
    a.extend(c,b,{}),c},
    {requires:["brix/core/brick","./breadcrumbs.css"]}
);

在这里 requires [breadcrumbs.css] 不太合理,这么做意味着所有的项目都得按照 Brix 这样的目录结构来布置 (我不认为这是一个好的方式)。

如果想将所有的 CSS 和 JS 分别打包成一个 brix-all.js 和 brix-all.css 就不行了(实际上,我们就应该提供一个完整的打包文件)

brix 的模板解析问题二次探讨

上次的讨论在 #39

注释的写法很好的解决了子模板的匹配和提取,却留下了遗憾和不优雅。

在上次的分析中我们已经知道,我们需要的是从一段Html文本中找出特定标签的innerHTML,这里面最大的难点就是,Html标签是支持嵌套的,怎么能够找到指定标签相对应的闭合标签呢?

思路

我们可以这样想,先匹配最前面的起始标签,假设是div吧(<div),接着一旦遇到嵌套div,就“压入堆栈”,后面如果遇到div闭合标签了,就“弹出堆栈”。如果遇到闭合标签的时候,堆栈里面已经没有东西了,那么匹配结束,此结束标签为正确的闭合标签。

之所以这样去思考,是因为正则里有“平衡组”这样的特性能够实现刚才说的“堆栈”操作(平衡组参见),可惜的是js里的正则不支持这样的特性。

回归原始

我们回到原始,不考虑嵌套,我们的正则应该这样写

<([\w]+)\s+[^>]*?bx-tmpl=["']?([^"'\s]+?)["']?\s+[^>]*?bx-datakey=["']?([^"'\s]+)["']?[^>]*?>([\s\S]*?)</\1> 

夹杂在标签中的内容无非两种情况

  • 内容A: 标签,并且此标签内无嵌套div
  • 内容B: 任意其他内容

然后就是这两种内容的不断重复而已。正则表示如下:

(<\1[^>]*>([\s\S]*?)</\1>|[\s\S])*?

这样,我们就能获取最多嵌套一级的正则了

<([\w]+)\s+[^>]*?bx-tmpl=["']?([^"'\s]+?)["']?\s+[^>]*?bx-datakey=["']?([^"'\s]+)["']?[^>]*?>((?:<\1[^>]*>(?:[\s\S]*?)</\1>|[\s\S])*?)</\1> 

以此类推二级、三级

<([\w]+)\s+[^>]*?bx-tmpl=["']?([^"'\s]+?)["']?\s+[^>]*?bx-datakey=["']?([^"'\s]+)["']?[^>]*?>((?:<\1[^>]*>(?:<\1[^>]*>(?:[\s\S]*?)</\1>|[\s\S])*?</\1>|[\s\S])*?)</\1>


<([\w]+)\s+[^>]*?bx-tmpl=["']?([^"'\s]+?)["']?\s+[^>]*?bx-datakey=["']?([^"'\s]+)["']?[^>]*?>((?:<\1[^>]*>(?:<\1[^>]*>(?:<\1[^>]*>(?:[\s\S]*?)</\1>|[\s\S])*?</\1>|[\s\S])*?</\1>|[\s\S])*?)</\1> 

程序构建

所以实际上,只要你的html结构不是特别复杂的话,也就是说嵌套不会很深的话,那么你完全可以使用这种方式来匹配嵌套html标签,幸运的是,因为模板是用户传入的,在传入之前,我们其实就知道同一个标签的嵌套次数,那通过程序动态构建正则,我们也是能够实现无限级标签嵌套的获取,代码如下:

var level = 3;
var r = '<([\\w]+)\\s+[^>]*?bx-tmpl=["\']?([^"\'\\s]+?)["\']?\\s+[^>]*?bx-datakey=["\']?([^"\'\\s]+)["\']?[^>]*?>(@brix@)</\\1>';
while(level--){
    r = r.replace('@brix@','(?:<\\1[^>]*>@brix@</\\1>|[\\s\\S])*?');
}
r = r.replace('@brix@','(?:[\\s\\S]*?)');

欢天喜地

现在,我们终于可以不用再写

<!--bx-tmpl="list" bx-datakey="list"-->
<!--bx-tmpl="list">

更好的建议

你是否有更好的建议?

某些自定义控件需要增加 input[type=hidden] 用于存储控件的值

比如: starrating 和 switcher

这两个是非标准控件,这类控件在用于传统 Form 提交的场景会非常不变,因为没有一个标准的控件用于接受它的最终值,而是的使用的时候不得不用 JS 去获取这个非标准控件的值。这样给后端开发者带来一些不便。

但是............

假如我们可以再这些“非标准”控件里面植入 <input type="hidden" name="foobar" /> 这么一个隐藏的文本框,在非标准控件 change 的时候将结果放入此文本框里面,那么后端开发者就可以直接在 Form 提交以后,在服务器通过 foobar 这个参数获取到这个控件的最终值 (当然 foobar 可以由组件使用者来自由定义),而无需在 Form 提交前再单独调用 JS 获取结果。

以 switcher 为例:

<form action="/articles" method="GET">
<div bx-name="switcher">
  <input type="hidden" name="publish" value="true" />
  <label>公开</label>
  <div id="bx_switcher_post_publish" bx-name="switcher" bx-tmpl="switcher" class="switcher switcher-on">
    <span class="switcher-trigger"></span>
  </div>
  <label>不公开</label>
</div>
</form>

仅仅需要在 switcher 切换的时候改变上面那个文本框的值就可以了。

在后端代码的时候就只需要获取 publish 这个参数的值就可以拿到选择的结果的。

再到回来看,关于给“非标准控件”值修改

对于“非标准控件”赋值这个动作我们也应该支持通过修改这个文本框的内容而改变“非标准控件”的展示效果。

Brick下的模版增强配置RENDERERS存在问题

单独通过实例化Brick组件是没有问题的,RENDERS中的方法会添加到相应的组件data中,如果通过Pagelet 初始化组件,RENDERERS会添加到Pagelet下的bricks的相应组件下,这是没有问题的,但模版会继续从Pagelet下的data去查找RENDERERS中的方法,所以是找不到的,因为demo中没有用到RENDERS,所以一直未触发这个bug

建议是Pagelet 遍历生成Brick的RENDERS,并把其加入到自己的data中

按钮的class命名问题

自成 (15:06:34):
Brix 里面按钮大小用 45, 40, 30, 28, 25 这种命名能不能改成 large big normal small tiny bit
这样会好记很多
数字的东西以后容易混淆到底是 28 还是 26,22 还是 25

逸才 (15:06:50):
我觉得还是数字好记……
large big
看到了的话,哪个是 45 哪个是 40 都得想半天哇

自成 (15:07:37):
这里只是 large 和 big 的问题
但是 其他的每个数字用的时候都得回想到底是多少
而且还这么多,记不住的

关于书写习惯&约束的始末

ATTRS 配置项、EVENTS 事件绑定机制、METHODS 公共方法、FIRES 自定义事件、RENDERDERS 自定义事件,形成以上书写习惯&约束的初衷是什么,是否源于为了解决某个问题(继承?)还是为了抽象和封装?一直不理解这种写法的始末,求扫盲。

mu组件数组对象中又包含了一个数组,没有递归

{{#list}}
<tr>
    <td class="left" width="15">
        <i class="iconfont more-icon" mx-click="show">&#377</i>
    </td>
    <td>
        <div class="idea_desc">{{creativeDesc}}</div>
        <ul class="item-pic clearfix">
            {{#picUrls}}
            <li class="current{{__index__}}">
                <img src="{{.}}" width="40" height="40">
            </li>
            {{/picUrls}}
        </ul>
    </td>
    <td class="right" width="80">
        <span class="sendNum">{{sendNum}}</span>
    </td>
    <td class="center" width="230">
        <div class="operation">
            <p><a class="btn btn-blue" href="#">立即发送</a></p>
            {{#if(joinedSentList==0)}}
            <p class="status">
                <em class="color-grey cursor-pointer" mx-click="delaypush{}">加入待发送列表</em>
            </p>
            {{/if(joinedSentList==0)}}
            {{#if(joinedSentList==1)}}
            <p class="status"><em class="mr10">已加入</em><a href="#!/manage/weibo/weibo" target="_blank">查看</a></p>
            {{/if(joinedSentList==1)}}
        </div>
    </td>
</tr>
{{/list}}

这里listpicUrls都是数组,但__index__list的索引,二不是picUrls的索引值

function addArrayIndex(v) {
        for (var i = 0; i < v.length; i++) {
            var o = v[i];
            if (o !== null && typeof(o) === "object") {
                if (i === 0) {
                    o.__first__ = true;
                } else if (i === (v.length - 1)) {
                    o.__last__ = true;
                } else {
                    o.__mid__ = true;
                }
                o.__index__ = i;
            }
        }
    }

这里o如果是数组,没做递归

Brix, BRIX, or brix?

这个名字最初是我提议的,化用板砖的英文复数,bricks,写成 brix,让我们为一淘平台化添砖加瓦的意思。

框架的核心抛出一块砖(Brick),组件开发者构造一块玉(Component)。

不过现在得统一一下名称,现在的文档、页面里头,已经有三个了:

  • Brix
  • BRIX
  • brix

我是惯用 Brix 的。希望可以大家讨论一下,认可一个,在以后的文档中,只用一个写法,增加辨识度。

KISSY RichBase 使用

RichBase是一个基础类,通过继承RichBase可以以一种统一的方式创建自己的具有新的属性、并可作为事件目的(RichBase继承自Base,所以拥有Attribute,EventTarget的能力)的类。

如何引用

要使用RichBase,首先要引入KISSY的种子文件:

html代码:

<script src="http://a.tbcdn.cn/s/kissy/1.3.0/seed-min.js"></script>

js代码:

KISSY.use('rich-base',function(S,RichBase){

});

or

KISSY.add("brix/core/chunk", function(S, RichBase) {

}, {
    requires: ["rich-base"]
});

继承RichBase

下面的代码定义完,Chunk就和RichBase有了同样的功能

KISSY.add("brix/core/chunk", function(S, RichBase) {
    var Chunk = RichBase.extend({},{});
    return Chunk;
}, {
    requires: ["rich-base"]
});

接下来会为大家介绍更多……

构造函数

我们上面定义的Chunk类并没有显示指定构造函数,RichBase内部会动态的构建一个function作为Chunk的构造函数,并且名字是"RichBaseDerived",要显示的指定名称,只需要在在继承的最后一个参数写上名称即可

var Chunk = RichBase.extend({},{},'Chunk');

那如果我们需要显示的定义构造函数应该怎么办呢,看下面的代码?

var Chunk = RichBase.extend({
    constructor: function Chunk() {
        var self = this;
        //显示的调用父类的构造函数,这句很重要。
        Chunk.superclass.constructor.apply(self, arguments);
    }
},{});

初始化函数和析构函数

RichBase在初始化时会自动调用各级类的initializer函数,在析构时会自动调用destructor函数,所以有初始或者析构处理只需定义相应的函数就可以了,不用显式调用父类的函数。

var Chunk = RichBase.extend({
    initializer: function() {

    },
    destructor: function() {

    }
},{});

ATTRS属性

可以用关联矩阵(associative array)的方式定义类的属性和配置参数,具体请查看“Base ATTRS

var Chunk = RichBase.extend({
},{
    ATTRS: {
        attr: {
            valule:value,
            valueFn:function(){
            },
            setter:function(){
            },
            getter: function(s) {
            }
        }
});

ATTRS的bind和sync

RichBase提供了对属性值初始化的同步以及变化的事件监听。先看一下代码

var Chunk = RichBase.extend({
    _onSetAttr:function(){
    }
},{
    ATTRS: {
        attr: {
            valule:value,
            valueFn:function(){
            },
            setter:function(){
            },
            getter: function(s) {
            }
        }
});

实例化Chunk类并设置attr属性值

var chunk = new Chunk({attr:1});
chunk.set('attr',2);

上面的实例化和设置属性值,都会同步调用到类中定义的_onSetAttr函数。具体的调用可查看RichBase源码中的bindInternal和syncInternal函数。

Plugins

Plugins机制可以用来在类的实例(而不是类本身)上动态添加特性。RichBase提供了一个配置(plugins)和三个函数(plug、unplug和getPlugin)用来管理插件。

plugins

plugins的类型是Array,在类实例化的时候实例化plugin,并调用plugin的pluginInitializer初始化函数。在销毁的时候调用pluginDestructor析构函数。

plug(plugin)

参数plugin可以是类,也可以是实例,如果是类则无参实例化plugin。
两者都会调用plugin的pluginInitializer初始化函数

直接传实例化的示例代码:

new Editor().plug(new FontSize({
  default: '14px'
}))

unplug(plugin)

从plugins数组中移除plugin,并调用pluginDestructor析构函数。

getPlugin(id)

通过类plugin定义的的p.get('pluginId') || p.pluginId来拿到plugin的实例。

扩展

RichBase的extend还提供了扩展功能,把一个主类与多个扩充类合并为一个新类。KISSY内部的很多组件都是基于这个完成的。

给个Overlay示例代码吧,具体的Overlay的实现并不仅仅如此

var Overlay = RichBase.extend([
        Extension.ContentBox,
        Extension.Position,
        Loading,
        Extension.Align,
        Close,
        Mask,
        OverlayEffect
    ], {}, {
        ATTRS: {}
});

listeners

差点忘记了listeners,这个配置项是用来在实例化类的时候增加事件的监听,看一下代码你就明白了。

var chunk = new Chunk({
        attr:1,
        listeners:{
            myfire:function(e){

            },
            hefire :{
                fn:function(){},
                //上下文
                context:{}  
           }
        }});
chunk.fire('myfire');

总结

RichBase为我们提供了如此多的特性,采用KISSY开发模块和组件的同学,果断的用RichBase吧。

brix.js 是否有必要持有 ready 事件?

brix.js 是 Brix 应用的入口,主要提供了 3 项功能:

  1. 读取配置选项,与默认选项值合并,最终构造出完整的选项集。
  2. 提供 Brix.ready(fn) 功能,用以取代 KISSY.ready(),统一编码风格(推测)。
  3. 在选项 autoConfig 为 true 时配置包路径和包路径映射(map)。

在查看上述实现时,有 2 个疑问:

  1. brix.js 中涉及的初始化选项繁多,而且不集中,这个问题已向波哥反映,属于代码待重构改进。
  2. brix.js 是否有必要持有 ready 事件?个人没有觉得这么做带来了新功能或者方便,封装一次就多一个疑问多一点学习成本,因此建议仍然交给 KISSY.ready()。

datepicker日期同步bug

datepicker通过快捷选择日期选择时间段时,没有同步日期选择输入框里的值,仍旧显示的是前一个时间值。

Brix 组件平台接口设计探讨

目标:开发者能够方便的使用平台内组件完成业务逻辑的书写
理念:平台化之后,未来的页面里除了组件再无其他。

Brix 组件平台的类比模型是拼图。拼图游戏的玩法是,玩家依据完整的图案提示,把不同的拼图块组合在一起,最终得到一个正确的图案。拼图块是一块块相对独立的小图案。每个拼图块有突出及凹陷的部分,其大小与形状是完全一致的,通过它们可组装成更大的拼图,不需要借助胶水或剪刀等工具。因此拼图游戏老少皆宜,不一定要心灵手巧,都可以完成上千块拼图块组成的图案。当然,根据难易程度,花费的精力是不同的。决定其难易程度的因素,主要是图案复杂度跟拼图块的大小。

Brix 组件平台的设计文档(http://etaoux.github.com/brix/arch/1-goal/ )详细解释了平台的设计理念(拼图的游戏规则)跟如何组件化(制作合适大小的拼图块),本文不再说明。下面探讨组件接口(突出及凹陷部分)的设计。

Brix 组件平台的目标用户前期是前端工程师,但长远地看,还包括后端工程师。他们的前端知识可能并不全面。因此,在保持组件独立的同时,还要做到易于组装,有统一的接口规范,需要很少或不需要额外代码(胶水)即可工作。

胶水代码:

var a = new A;
var b = new B;
b.on(xx, function() {
  a.yy();
});

在Web App类型的应用中,通常会有大量的业务逻辑。本文不建议使用胶水代码来处理这些逻辑,而建议通过合理的数据处理加模版搞定(这应该是后端工程师必备的工作技能了)。对Web Page型应用,简单的组装通常就可以满足需求。

那么如何设计组件平台的接口可以满足上面的目标呢?在计算机世界里,应该有大量的模型可以参考。

操作系统就是一个很好的模型。操作系统本身就像Brix 组件平台,各种程序对应 Brix 组件,用户就组件使用者了。多数情况下,用户不需要知道程序是怎么编写的,就可以使用程序完成工作。

以Unix操作系统为例具体说明。各个进程间通信的媒介是标准流,一共有3个:标准输入(stdin)、标准输出(stdout)、标准错误输出(stderr)(ref: http://en.wikipedia.org/wiki/Standard_streams )。默认情况下,进程通过stdin接收外界的数据,通过stdout或stderr输出数据,但是用户可以对标准流进行重定向(常玩shell的同学对这个肯定不陌生)。

对应到组件平台,可以为各个组件添加固定的输入/输出接口。组件监听输入接口来响应交互操作,通过输出接口来影响其他组件的交互。输入/输出接口指向的引用,可以在模板中进行配置。这样,组件之间依然相互独立,统一的接口设计也完成了。组装好模板后,再准备好合适的数据,页面开发就完成了。

demo见这里:
http://etaoux.github.com/brix/demo/gallery/dropdown/dropdown4.html

Brix Style的mixin范围讨论

最近用脚本(tools/scan.js)统计了下Bootstrap的mixin使用频率,如下图:

可以看到,一共61个mixin,使用频率大于10的仅有4个(如果排除掉被重复了24遍的tableColumns,其实只有3个)。大部分mixin并不常使用,有用的mixin反而被淹没了。

因此Brix Style打算先保留Bootstrap中使用频率大于3的mixin,总mixin数目保持在20个以内。不知大家怎么看?

Brix Style意见收集-2013

Brix Style大家也使用了半年多了,有用的不爽的地方欢迎集中反馈。我们会努力改进。

文档建设的几个问题

首先要跟大家商量的是,该放在哪个仓库里面,etaoux 账号下有两个仓库:

github pages 提供的功能是:

后者 @limu 之前就创建过,我前些天做了写改动,加上了样式,用了 jekyll;前者是我今天新增加的,为了更好的 brix 项目的文档建设。两个都还很粗糙,只能算雏形。

现在我发现这么搞会有不少重复劳动,因此,不如以后都放到 etaoux.github.com 的 master 分支来搞?kissy 也是这么做的

另一个问题,是文档细节

我看了现有的文档,发现几个不爽处,在 https://github.com/etaoux/brix/blob/master/docs/HTML_CSS.md@keyapril 写的文档中都有:

  • 中英文混用的时候中间没有空格,“一淘组件HTML/CSS书写规范”,加上空格会美观许多 “一淘组件 HTML/CSS 书写规范”
  • 列表(ul、ol)的使用,会不会太多了?文档首先该是篇文章,仅仅罗列技术点可能不够吧?

最后的一个问题,是 github 提供的静态网站生成工具 jekyll 带来的。jekyll 提供语法高亮的功能,写法是:

{% highlight js linenos %}
;(function() {
    alert(1)
})()
{% endhighlight %}

挺好用,但是有个麻烦的问题,不能在列表中高亮语法。这么写,会把列表砍成两半:

- item 1
- item 2
   {% highlight js linenos %}
   ;(function() {
       console.log('hello world');
   })()
   {% endhighlight %}
- item 3

代码块会跑到列表外面去,我给 jekyll 提了 这个 bug,但是 fix 的机会渺茫。要规避这个问题有两个办法,1)是在列表中不要高亮代码;2)使用别的高亮方式。

后者,@keyapril 找了个很不错的 js 实现 http://softwaremaniacs.org/soft/highlight/en/description/

就这三个问题,想听听大家意见

style文件夹的混乱

现有style文件夹中涵盖了reset,layout,以及其他非js的组件(如:btn,tables等)
上周会议讨论组件需要版本管理,那btn等其实也需要版本管理,所以建议将style中非js的组件一同移到gallery文件夹中管理。

创意中心在引入 Brix Style 后遇到的一些问题以及解决办法

先说明一下创意中心,使用 Rails 开发,样式最初是纯 CSS 写,后来 Rails 有了 Asset Pipeline,改用 SCSS ,使用 KISSY CSS 里的 reset.css 做样式重置,没有栅格,简单写了个 1000px 宽的居中。

起初因为担心 normalize.less 与 reset.css 出入太多,没有使用编译好的 brix.css,而是挑了用得到的部分,一点点放进来。后来发现,除了重置方式的差别之外,form.less 打击面太广,也是一个大问题。标签与头像没有用上,按下不表。

问题一:Less 与 SCSS 之分

两周前开始尝试,用了最需要的 grid.less,并改写成 grid.scss。顺便在此详细答 @xthsky 问,为何改写而不直接用,原因如下:

  • Rails 默认支持的是这个
  • 旧代码全部是 SCSS
  • SCSS 的流程控制语法更简洁,mixin 和 include 的用法也更清楚明了

第三点在 grid.scss 中比较明显,代码请看 https://github.com/dotnil/brix-style/blob/master/src/grid.scss
对比 Less 版本:https://github.com/etaoux/brix/blob/master/src/style/mixins.less#L184

所以此问题,我的解决办法是用 SCSS 重写。除了流程控制语法差别比较大之外,其他的都比较细微:

不过,新启动的 Rails 项目,不用担心此问题,换 Less 的代价并不大,有现成的 gem 支持,https://github.com/metaskills/less-rails

reset 与 normalize

然后遇到的就是 Brix Style 自身代码的问题了,normalize 与 reset 的出入,我感受到比较多的就两个:

  • ul、ol 没有重置
  • p、h[1-6]、pre 等,有 margin: 1em 0

前者,我增加了 .reset 来把它们重置掉,在需要重置的 ul、ol 上加 .reset 就好:

ul, ol {
  &.reset {
    margin: 0;
    padding: 0;

    li {
      list-style: none;
      margin: none;
    }
  }
}

后者,我挺喜欢这种方式的。这个差别造成的问题自然不少,不过挨个改一下也没那么难。自带的 reset-patch 我并没有用。

form 太 tnnd 的暴力了

https://github.com/etaoux/brix/blob/master/src/style/forms.less#L73

label、input、legend 有 margin 有 width,让我之前散落各处,并不在 form 中 label、input 全都奇葩了……

所以我直接把它们塞回到 form 里面去 https://github.com/dotnil/brix-style/blob/master/src/form.scss#L42

其他一些与我项目不符的,则在项目样式中重置、补齐。

button 的不足之处

Rails 项目中,有种按钮是通过 <%= button_to %> 生成的,结构类似这样:

<%= button_to '拷贝创意', mitosis_creation_path(:id => creation.id), :class => 'btn', :method => 'post' %>
<form action="/creations/100351/mitosis" class="button_to" method="post">
  <div>
    <input class="btn" type="submit" value="拷贝创意">
    <input name="authenticity_token" type="hidden" value="XLtk0GDl1SEeTXinitnb/9DmaUNHBf7eGoszUlS1NRA=">
  </div>
</form>

为什么一个按钮要搞成这样,说来话长,幸运的是,在我的项目里这种 .btn 都只在 .btn-group 里面使用,所以我可以这么搞:

.btn-group {
  form, .btn {
    float: left;
  }
  form:first-child {
    .btn {
      border-left-width: 1px;
      @include border-top-left-radius(2px);
      @include border-bottom-left-radius(2px);
    }
  }
  form:last-child {
    .btn {
      @include border-top-right-radius(2px);
      @include border-bottom-right-radius(2px);
    }
  }
}

曲线救国吧。

另外,在 button.less 中有一些针对低版本 IE 的 hack,https://github.com/etaoux/brix/blob/master/src/style/buttons.less#L9 ,我在项目中并没能重现这些问题,所以都直接去掉了。或者,注释再详细一点?

还有一些细节问题,我迟些补充吧,光看代码想不起来了……

EOF

Brix Style 中,还有 avatar、tag、scrollbar 等,这些我都没有使用,不发表意见。

normalize的焦点框样式重置

PC(一丝)(yisibl) (2012-08-02 11:58:31):
EN 了解需求了,那么reset中就这样吧:

a:focus {
  outline: thin dotted #555;
  outline: 5px auto -webkit-focus-ring-color;
  outline-offset: -2px;
}
input:focus, textarea:focus, isindex:focus, keygen:focus, select:focus {
    outline-offset: -2px
}

关于为组件增加默认模板的建议

在组件目录下只有 js 和 css,模板是写在 demo 里的,建议把模板也到组件目录下作为默认模板,如果客户未指定模板,就采用默认模板。
这样做有几个好处:组件更加内聚、组件更加完整、方便上手、方便扩展(比如封装成 jsp 标签库方便 Java 攻城师使用)。

Input, Button 和 a 标签的高度不同

<input type="button" class="btn btn-red  btn-size45" value="红色按钮" />
<button class="btn btn-red  btn-size45">红色按钮</button>
<a href="#" class="btn btn-red btn-size45">红色</a>

同时,input 的时候宽度也是不同的

典型不爽模板收集

大家觉得mustache不太够用,请有意识的收集下mustache力不从心的地方,请写出数据输入和HTML输出,再配上大家觉得别扭的数据处理和模板等。

需要js辅助的UX控件设计讨论

Radio,Checkbox,Dropdown,Rating 等部分UX控件是需要js支持的。

但是 Radio,Checkbox 等控件可能书写的十分频繁,是否需要一种途径不写 bx- 前缀的属性也可以自动实例化这些控件?

组件名统一为 index.js/html/css/less 的疑问

组件名统一为 index.js/html/css/less,例如 dropdown,方便了 Brix 拼接组件路径和加载,对于组件开发者却不够友好,会有为什么要这么强制约定的疑问。这个疑问应该是可以避免的。

参考了下 SPM 源服务器 的目录结构,组件根目录 gallery 下有文件 info.json,用于描述所有组件的信息,包括目录、名称、版本(路径)、稳定版本等,每个组件下同样有一个文件 info.json,用于描述当前组件的信息,组件的名称和结构则保持不变。

每个组件事实上需要有自己 独立的版本号,并且,基于描述组件信息的文件 info.json 可以生成一份 推荐的组件配置

brix style的class是否需要约定加公用的前缀bx-

kissy组件有kissy-overlay kissy-suggest等
mui组件约定加同意的前缀ui-,如ui-tabs,ui-title
看到有人反馈命名不规范的问题,个人认为约定加个前缀bx-好,bx-是全新的也可以保证以后渐进替换线上不冲突哦,现在看到组件里面有的加bx-有的不加有的加etao-

加强组件在debug模式的log功能

比如 bx-config 格式错误,要在控制台明确告诉开发是 bx-config 格式错误,静默处理会让开发以为组件出了问题,然后无穷*扰前端。

可以考虑加入组件开发指南。

从剑平 KF Uploader 的客服经验想到的。

brix 的模板解析问题

问题

我们最早讨论brix对于获取子模板,实现局部刷新功能时候,定下的@逸才同学提出的在内存中创建dom结构,用操作dom的方式获取innerHTML来实现获取子模板。
在brix的具体实现中碰到了蛮多问题,主要是不同浏览器下对mustache模板解析成html结构时的不同处理,比如src,href等会编码、"{{/"这个会认为是一个html标签的结束等等坑,这些都在tmpler.js中一一解决了,然而,昨天,我们又遇到坑了,比如:

    <div bx-tmpl="list" bx-datakey="list">
        <table>
            <tbody>
            {{#list}}
                <tr>
                    <td>{{name}}<td>
                </tr>
            {{/list}}
            </tbody>
        </table>
    </div>

上面这个代码创建成dom时候,浏览器直接过滤了{{#list}}和{{/list}},我们无法取到正确的模板代码。

分析

那么,我们想从上面代码拿到什么样的信息呢?

首先是模板代码:

    <table>
        <tbody>
        {{#list}}
            <tr>
                <td>{{name}}<td>
            </tr>
        {{/list}}
        </tbody>
    </table>

然后是模板对应的数据key值,即:bx-datakey自定义属性

最后后是模板代码对应于哪个节点

    <div bx-tmpl="list" bx-datakey="list">
    </div>

有了这三个,我们就能在数据发生变化的时候重新渲染模板,实现局部刷新。

解决

既然innerHTML有这么多坑,而且已经碰到一个我无能为力的坑,那就换种思路。

我们能不能通过直接分析字符串的方式来获取?

如果模板变成:

    <div bx-tmpl="list" bx-datakey="list">
    {{#bx-tmpl="list" bx-datakey="list"}}
        <table>
            <tbody>
            {{#list}}
                <tr>
                    <td>{{name}}<td>
                </tr>
            {{/list}}
            </tbody>
        </table>
    {{/bx-tmpl="list"}}
    </div>

我们写一个这样的正则:

    /\{\{#bx-tmpl="(.*)?".*?bx-datakey="(.+)?"\}\}(\s*([\s\S]*)?\s*)\{\{\/bx-tmpl="\1"\}\}/ig

就能解决问题了。

坏处

看上面的代码就知道了,我们重复定义了两遍bx-tmpl和bx-datakey,似乎有点不优雅,暂时我也不知道要怎么改造:

    <div bx-tmpl="list" bx-datakey="list">
    {{#bx-tmpl="list" bx-datakey="list"}}
    {{/bx-tmpl="list"}}
    </div>

讨论

大家看看,这样的方案是否可行?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.