Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

组件设计之BEM法则 #30

Open
kuitos opened this issue Nov 26, 2015 · 6 comments
Open

组件设计之BEM法则 #30

kuitos opened this issue Nov 26, 2015 · 6 comments

Comments

@kuitos
Copy link
Owner

kuitos commented Nov 26, 2015

组件设计之BEM法则

BEM定义

Block Element Modifier is a methodology, that helps you to achieve reusable components and code sharing in the front-end

BEM概念

原义:一个css编写规范

B(block): 独立的页面及逻辑单元,我们通常意义上的component
E(element): 块中的组成部分,不能脱离块单独存在
M(modifier): 修饰符,可修饰块或元素

它提出来一种命名规范:

block__element--modifier

example:

<div class="header header--blink">
    <div class="header__title header__title--red-border">title</div>
</div>

这段html表达的意思是:一个header组件(block),其中包括了一个title元素(element),同时header块具备闪烁(blink)特性,title元素具备红边框特性。

但是我们今天要讲的并不是这个

BEM的这种命名方式看似美妙,但实则是与标准相悖的解决方案(后面讲)。所以我不会推荐这种css规范,我想说的是从BEM这种思路,我们可以将它作为我们组件粒度划分的方法论。

从BEM划分策略看页面:
a

  1. Block是一个完整独立的逻辑单元,是一个概念完备的组件,它包含完整的逻辑单元(js),模版(template)及样式(css)
  2. Element是Block的组成部分,Block是它的宿主,Element无法脱离宿主存在
  3. Modifier是块/元素的修饰符

以一个tab列表组件为例:

我们的目录结构应该这样去组织

代码可能这样去写

// tabset
app.directive('tabset', function(){
    return {
        restrict:'E',
        templateUrl:'tab-set.html',
        scope:{
            tabs:'='
        }
    };
});
<!-- tab-set.html -->
<div ng-repeat="tab in tabs track by $index">
    <tab info="tab"></tab>
</div>
<div class="tab-border"></div>
// tab
app.directive('tab', function(){
    return {
        restrict:'E',
        require:'^tabset',
        templateUrl:'tab.html',
        scope:{
            tab:'=info'
        }
    };

});
<!-- tab.html -->
<div>
    <span ng-bind="tab.title"></span>
</div>

调用时这么去用

<tabset tabs="tabs"></tabset>
app.controller('ctrl', ctrl);

ctrl.$inject = ['$scope'];
function ctrl($scope){
    $scope.tabs = [{title:'tab1'}, {title:'tab2'}];
}

Tab组件作为TabSet的一部分是没办法独立存在的,它必须依托于TabSet才有意义。
对调用者而言,暴露给它的是TabSet组件,TabSet才是一个Block(组件),Tab是一个Element。

在components这一层,我们能看到的都是一个个完整的Block,而且每个Block都是独立存在不会互相依赖的平级关系。

总结来讲就是

组件与组件之间的关系,是组合,不是依赖

如果你在components层级发现了存在相互依赖的两个组件,赶紧重新想想你的组件规划是不是有问题

我们可以将 ‘组件之间的关系是组合而不是依赖’ 作为我们开发设计组件的guideline,基于此,我们需要确立的思想就是,在现如今的web开发模式下,我们更应该采用 面向组件(COP) 的方式开发组件而不是以前流行的 面向对象(OOP) 的方式(以ExtJs为代表),组件之间更多的是组合关系,继承的场景在组件开发领域很少而且大多时候可以用其他方式实现(组合或者修饰符的方式)。

拓展章节:

  1. web语义化标准解读
@junhuif
Copy link

junhuif commented Dec 25, 2015

拓展章节:

  1. web语义化标准解读

链接指向 #30 了,应该是错了。

@kuitos
Copy link
Owner Author

kuitos commented Dec 25, 2015

@fengjh 多谢提醒。
不过这里并不是链接错了,而是我临时占坑,因为这篇文章还没开始写😂

@leozdgao
Copy link

BEM的这种命名方式看似美妙,但实则是与标准相悖的解决方案(后面讲)。

这个地方不是很明白,期待之后的解读。:smile:

@kuitos
Copy link
Owner Author

kuitos commented Dec 26, 2015

@leozdgao 简单来说BEM的这种命名方式是违背语义化标准的,后面有时间我会整理一篇文章出来描述一下这部分的内容😄

@zx1986
Copy link

zx1986 commented Jan 14, 2016

BEM的这种命名方式看似美妙,但实则是与标准相悖的解决方案(后面讲)。所以我不会推荐这种css规范,我想说的是从BEM这种思路,我们可以将它作为我们组件粒度划分的方法论。

是指 sematic 不夠好的意思?
http://semantic-ui.com/

感謝,期待。

@kuitos
Copy link
Owner Author

kuitos commented Jan 14, 2016

@zx1986 是的,不是面向语义的。
semantic-ui名字是叫语义化ui,但感觉其实做的并不够好,同样问题的还有bootstrap

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants