less学习笔记3-语言特性(extend)

extend这一部分真的看得我不知道要怎么说明好,难怪less中文网这一部分完全没有翻译。看着一部分的时候感觉无从下口啊,好些地方都觉得好违和,讲不清楚的感觉,所以文中用到extend的地方均使用英文的extend。在第三次阅读的时候,突然才发现extend有一些Java中继承的感觉,所以最后就决定将extend翻译成继承,有稍微了解过Java继承的简单概念的小伙伴,应该很容易就理解extend的作用和原理。也自行定义了两个选择器A和B,选择器A和B的引入方便文中解释的理解,也方便我的表达,所以要先记住选择器A和B的定义再看下面的内容会好理解很多,当然最好的就是结合英文原文一起学习,如果有更好的理解也欢迎多多提出。还是有部分解释讲解的不够清晰,争取全部学习结束后再次整理下。


继承(Extend)

Extend可以理解成一种less的伪类,形式为A:extend(B),其作用:使用这个伪类选择器(A)可以将符合其条件的选择器(B)的样式规则引用给自身用,即A会拥有B的样式规则。

(A:extend(B))下面会用A泛指使用extend伪类的选择器,用B泛指extend伪类所去匹配的选择器。

发布于v1.4.0

nav ul{
    &:extend(.inline);
    background: blue;
}

上面设置的规则中,:extend 这个伪类会把“使用extend的选择器”(nav ul)拥有 .inline 的规则。如果.inline这个选择器不存在,那么A选择器的声明代码块将会保持原样,但是extend语句将无效(因为extend不是css)

nav ul{
    &:extend(.inline);
    background: blue;
}
.inline{
    color: red;
}

编译为:

nav ul{
    background: blue;
}
.inline,nav ul{
    color: red;
}

注意到 nav ul:extend(.inline) 选择器编译成nav ul的过程 - 在编译之前,选择器中的extend伪类的那个语句会被移除,其余的语句保持原样。如果extend中的B选择器没有样式,那么extend在编译过程中会被移除(但是extend有可能会影响其他的选择器)。

Extend语法

Extend要么接在选择器后面要么放置在规则中。看起来很像是伪类选择器,并且拥有一个可选的参数 all

.a:extend(.b){ ... }
//上面的代码与下面的代码编译出来的一致
.a{
    &:extend(.b);
}

.c:extend(.d all){
    //包含了".d"的所有实例,例如:" .x.d"或者".d.x"
}
.c:extend(.d){
    //只包含一个实例,选择器只会被编译成 ".d"的实例
}

Extend中可以包含一个或者多个类,用逗号分隔

.e:extend(.f){...}
.e:extend(.g){...}
//上面和下面代码的编译结果一样
.e:extend(.f,.g){...}

Extend使用方式

Extend的使用方式就像使用普通的伪类一样,一个选择器可以包含多个Extend,但是所有Extend都要放置在这个选择器的末端。

  • Extend置于选择器后面: pre:hover:extend(div pre)
  • 选择器和Extend之间允许间隔空格:pre:hover :extend(div pre)
  • 允许多个Extend:pre:hover:extend(div pre):extend(.bucket tr) = pre:hover:extend(div pre, .bucket tr);
  • 以下的用法是错误的:pre:hover:extend(div pre).nth-child(odd),Extend必须放在最末端

当多个选择器拥有同一个样式规则,每个选择器都可以拥有独自的Extend关键词。下面为多个选择器拥有一个规则的情况:

.big-division,
.big-bag:extend(bag),
.big-bucket:extend(bucket){
  ...
}

在规则中的Extend

Extend可以通过使用&:extend(selector)这个语法将extend放置在规则内部。将Extend放在规则内部是将Extend单独作用在每个选择器的简化形式。

放在内部:
pre:hover,.some-class{
    &:extend(div pre);
    ...
}

等同于在每个选择器中单独添加Extend:
pre:hover:extend(div pre),
.some-class:extend(div pre){...}

Extend中使用嵌套选择器

Extend允许使用嵌套选择器(即B选择器为嵌套形选择器):

.bucket{
    tr{
        color: blue;
    }
}
.some-class:extend(.bucket tr){ ... }

编译为:
.bucket tr,
.some-class{
    color: blue;
}

Extend准确匹配

Extend默认会在所有选择器中寻找与B选择器匹配的选择器,无论B选择器是否使用*(星号)。如果两个后代表达式(详细看下一段)对应同一个元素,但是匹配的时候也是要根据后代表达式中的格式进行匹配。一个唯一的例外就是属性选择器的,less知道它们意思相同并且能进行匹配。

.a.class,.class.a,.class>.a{
    color: blue;
}
.test:extend(.class){ ... }//匹配不到上面的任何选择器

*可以认为是任意选择器。 *.class和.class是对应同一个元素数组,但是Extend进行匹配的时候不会将二者认为是同一个。

*.class{
    color: blue;
}
.test:extend(.class){ ... }//不会匹配到*.class这个选择器

编译为:
*.class{
    color: blue;
}

匹配时会根据伪类的顺序。选择器link:hover:visitedlink:visited:hover匹配到的是同一个元素,但是Extend会区分它们。

link:visited:hover{
    color: blue;
}
.selector:extend(link:hover:visited){ ... }

编译为:
link:visited:hover{
    color: blue;
}

后代表达式

匹配会根据后代表达式的形式进行匹配。后代表达式1n+3n+3是相等的,但是Extend不会匹配二者。

:nth-child(1n+3){
    color: blue;
}
.child:extend(:nth-child(n+3)){ ... }

编译为:
:nth-child(1n+3){
    color: blue;
}

属性选择器的引用类型不会进行匹配。下面的情况都相等。

[title=identifier]{
    color: blue;
}
or
[title='identifier']{
    color: blue;
}
or
[title="identifier"]{
    color: blue;
}
.noQuote:extend([title=identifier]){}
.singleQuote:extend([title='identifier']){}
.doubleQuote:extend([title="identifier"]){}

编译为:
[title=indentifier],
.noQuote,
.singleQuote,
.doubleQuote{
    color: blue;
}
or
[title='identifier'],
.noQuote,
.singleQuote,
.doubleQuote {
  color: blue;
}
or
[title="identifier"],
.noQuote,
.singleQuote,
.doubleQuote {
  color: blue;
}

Extend"all"

当你指定了Extend的最后一个参数为all时,less将会匹配一些名字包含B选择器的名字的C选择器,类似模糊匹配那样。当匹配到选择器后,C选择器将会被复制,并且将C选择器名字中匹配到的那部分替换B选择器的名字,变成新的选择器。

.a.b.test,
.test.c{
    color: green;
}
.test{
    &:hover{
        color: red;
    }
}
.replace:extend(.test all){}

编译成:

.a.b.test,
.test.c,
.a.b.replace,
.replace.c{
    color: green;
}
.test:hover,
.replace:hover{
    color: red;
}

你可以将这个操作理解成做一个非破坏性的搜索和匹配

在Extend中使用选择器插入(Selector Interpolation with Extend)

Extend不能够匹配有变量的选择器,如果选择器包含变量,Extend将会将其忽略。
这是一个未定的特性,但是不会轻易改变。但是extend可以连接插入性选择器(包含变量的选择器A)。

包含变量的选择器将不会被匹配:

@var: .bucket;
@{var}{  //插入性选择器
    color: blue;
}
.some-class:extend(.bucket){}//不做任何事

在目标选择器进行extend中使用变量将不会被匹配:

.bucket{
    color: blue;
}
.some-class:extend(@{var}){}//匹配不到选择器
@var: .bucket;

上面两个都会编译成:

.bucket{
    color: blue;
}

然而,:extend可以连接到插入性选择器:

.bucket{
    color: blue;
}
@{var}:extend(.bucket){}
@var: .test;

编译为:
.bucket,.test{
    color: blue;
}

总结就是:A选择器可以包含变量,但是B选择器不能包含变量。

作用范围/@media里面的extend

写在一个media声明中的extend只能匹配在同一个media里面的选择器:

@media print{
    .screenClass:extend(.selector){}
    .selector{
        color: black;
    }
}
.selector{
    color: red;
}
@media screen{
    .selector{
        color: blue;
    }
}

编译为:

@meida print{
    .screenClass,.selector{
        color: black;
    }
}
.selector{
    color: red;
}
@media screen{
    .selector{
        color: blue;
    }
}

写在一个media声明中的extend不会匹配到嵌套在里面的media声明里面的选择器:

@media screen{
    .selectorClass:extend(.selector){}
    @media (min-width: 768px){
        .selector{
            color: blue;
        }    
    }
}

编译为:

@media screen and (min-width: 768px){
    .selector{
        color: blue;
    }
}

外部extend可以匹配范围无限制,包括内部的嵌套media里面的选择器:

@media screen{
    .selector{
        color: blue;
    }
    @media (min-width: 768px){
        .selector{
            color: red;
        }
    }
}
.topLevel:extend(.selector){}
编译为:
@media screen{
    .selector,
    .topLevel{
        color: blue;
    }
}
@media screen and (min-width: 768px){
    .selector,
    .topLevel{
        color: red;
    }
}

重复检测

现在是没有重复检测的功能。

.alert,.widget{ ... }
.test:extend(.alert, .widget){}

编译为:

.alert,.widget,.test,.test{ ... }

所以在使用extend的时候需要注意不要extend具有相同规则的选择器

extend的使用情况

  • 典型使用情况

典型的使用情况是为了避免增加一个类:

如果你有一个类animal
.animal{
    background-color: black;
    color: white;
}
然后你想要通过复写background-color这个属性来得到一个animal的子类,那么HTML就会变成这样:
<a class="animal bear">bear</a>
css样式就会变成这样:
.animal{
    background-color: black;
    color: white;
}
.bear{
    background-color: grey;
}
不然你可以在less中使用extend,那样你的HTML就会变得很简单:
<a class="bear">bear</a>
less就会为:
.animal{
    background-color: black;
    color: white;
}
.bear{
    &:extend(.animal);
    background-color: grey;
}
  • 减少css大小

mixin将所有的属性都复制到新的选择器中,从而导致了不必要的重复。因此你可以使用extend去代替mixin将你想要用的属性添加到新的选择器中,从而减少css代码。
使用mixin:

.mine{
    color: #fff;
    font-size: 16px;
}
.test1{
    .mine;
}
.test2{
    .mine;
}

编译为:
.mine{
    color: #fff;
    font-size: 16px;
}
.test1{
    color: #fff;
    font-size: 16px;
}
.test2{
    color: #fff;
    font-size: 16px;
}

使用extend:

.mine{
    color: #fff;
    font-size: 16px;
}
.test1{
    &:extend(.mine);
}
.test2{
    &:extend(.mine);
}

编译为:
.mine,
.test1,
.test2{
    color: #fff;
    font-size: 16px;
}
  • 组合样式/更先进的mixin

另一种使用情况是作为mixin的一种替代方法,因为mixin只能用在建档的选择器,如果在HTML中有两个不同的块(block),但是需要应用同一个样式,那么你就可以使用extend去链接两个块元素。

li.list >a{ ... }
button.list-style{
    &:extend(li.list>a);
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,744评论 6 502
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,505评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,105评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,242评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,269评论 6 389
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,215评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,096评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,939评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,354评论 1 311
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,573评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,745评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,448评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,048评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,683评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,838评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,776评论 2 369
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,652评论 2 354

推荐阅读更多精彩内容

  • Less作为 CSS 的一种扩展,不仅完全兼容 CSS 语法,而且连新增的特性也是使用 CSS 语法,你可以在任何...
    zhangivon阅读 572评论 0 1
  • 花了这两天上班的空闲时间把mixins的大部分的相关内容写完了,但是还有两小块内容还没写,预计放在下一篇当中,下一...
    程恺阅读 2,407评论 0 1
  • <a name='html'>HTML</a> Doctype作用?标准模式与兼容模式各有什么区别? (1)、<...
    clark124阅读 3,474评论 1 19
  • 午夜梦回。村头的桂花树下,披头散发的母亲,对着一只狗傻笑。 我又想我的母亲了。 我不知道母亲的名字,也不知道她来自...
    西川紫阅读 793评论 5 6
  • -1- 其实,对于别人所说的缘分但凭命中注定,自己是从来都没有相信过的。只是遇见你之后,我多么希望这说法是对的,而...
    夜落y阅读 509评论 0 1