美文网首页Web前端之路程序员
less学习笔记3-语言特性(extend)

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

作者: 程恺 | 来源:发表于2017-09-04 17:59 被阅读134次

    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);
    }
    

    相关文章

      网友评论

        本文标题:less学习笔记3-语言特性(extend)

        本文链接:https://www.haomeiwen.com/subject/pebsjxtx.html