日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > CSS >内容正文

CSS

再谈 CSS 预处理器

發布時間:2025/1/21 CSS 146 豆豆
生活随笔 收集整理的這篇文章主要介紹了 再谈 CSS 预处理器 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

CSS 預處理器是什么?一般來說,它們基于 CSS 擴展了一套屬于自己的 DSL,來解決我們書寫 CSS 時難以解決的問題:

  • 語法不夠強大,比如無法嵌套書寫導致模塊化開發中需要書寫很多重復的選擇器;

  • 沒有變量和合理的樣式復用機制,使得邏輯上相關的屬性值必須以字面量的形式重復輸出,導致難以維護。

所以這就決定了 CSS 預處理器的主要目標:提供 CSS 缺失的樣式層復用機制、減少冗余代碼,提高樣式代碼的可維護性。這不是錦上添花,而恰恰是雪中送炭。

網上已經有不少對比目前最主流的三個預處理器 Less、Sass 和 Stylus(按字母順序排名)的文章了,但是似乎都不是很詳細,或者內容有些過時。下面我會更詳細地探討一下這三種預處理器的特性和它們的差異。

下面主要會分為如下幾方面來討論:

  • 基本語法

  • 嵌套語法

  • 變量

  • @import

  • 混入

  • 繼承

  • 函數

  • 邏輯控制

事先聲明一下,平時我在開發中主要使用的是 Less,所以可能對 Sass 和 Stylus 的熟悉程度稍差一些,比較時主要參考三者官網的語言特性說明,有一些正在開發的功能可能會遺漏。

本文中對 CSS 語法的話術與 MDN 的 CSS 語法介紹一致。

基本語法

Less 的基本語法屬于「CSS 風格」,而 Sass、Stylus 相比之下激進一些,利用縮進、空格和換行來減少需要輸入的字符。不過區別在于 Sass、Stylus 同時也兼容「CSS 風格」代碼。多一種選擇在更靈活的同時,在團隊開發中也免不了增加更多約定來保持風格統一。而對個人而言,語法風格按自己口味選擇即可。

注:后面的 Sass 代碼會用被更多人接受的 SCSS 風格給出。

Less & SCSS:

.box {
?display: block;
}

Sass:

.box
?display: block

Stylus:

.box
?display: block

嵌套語法

三者的嵌套語法都是一致的,甚至連引用父級選擇器的標記 & 也相同。區別只是 Sass 和 Stylus 可以用沒有大括號的方式書寫。以 Less 為例:

.a {
?&.b {
? ?color: red;
?}
}

生成的 CSS 為:

.a .b {
?color: red;
}

除了規則集的嵌套,Sass 額外提供了一個我個人認為比較另(jī)類(lèi)的「屬性嵌套」:

.funky {
?font: {
? ?family: fantasy;

? ?size: 30em;
? ?weight: bold;
?}
}

選擇器引用

三者都支持用 & 在嵌套的規則集中引用上層的選擇器,這可以是嵌套書寫 CSS 時的「慣例」了。語法相同,但是邏輯上有些許差異。在一個選擇器中用兩次以上 & 且父選擇器是一個列表時,Less 會對選擇器進行排列組合,而 Sass 和 Stylus 不會這么做。

也就是說,假設上層選擇器為 .a, .b,則內部的 & & 在 Less 中會成為 .a .a, .a .b, .b .a, .b .b,而 Sass 和 Stylus 則輸出 .a .a, .b .b。

假設我們要用預處理器書寫 WHATWG 推薦的 section 標題樣式,在 Less 中可以方便地書寫為:

article, aside, nav, section {
?h1 {
? ?margin-top: 0.83em; margin-bottom: 0.83em; font-size: 1.50em;
?}
?& & h1 {
? ?margin-top: 1.00em; margin-bottom: 1.00em; font-size: 1.17em;
?}
?& & & h1 {
? ?margin-top: 1.33em; margin-bottom: 1.33em; font-size: 1.00em;
?}
?& & & & h1 {
? ?margin-top: 1.67em; margin-bottom: 1.67em; font-size: 0.83em;
?}
?& & & & & h1 {
? ?margin-top: 2.33em; margin-bottom: 2.33em; font-size: 0.67em;
?}
}

當然,這個推薦樣式十分腦殘,編譯出來的結果會有 47KB 之巨,根本不可用,這里只是借來演示一下。

除了 &,Sass 和 Stylus 更進一步,分別用 @at-root 和 / 符號作為嵌套時「根」規則集的選擇器引用。這有什么用呢?舉個例子,假設 HTML 結構是這樣的:

<article class="post">
?<h1>我是一篇文章</h1>
?<section>
? ?<h1 class="section-title"><a href="#s1" class="section-link">#</a>我是章節標題</h1>
? ?<p>我只是一個<em>例子</em></p>
?</section>
</article>

如果我這么寫 Sass 代碼,是完全符合業務的嵌套關系的:

.post {
?section {
? ?.section-title {
? ? ?color: #333;
? ? ?.section-link {
? ? ? ?color: #999;
? ? ?}
? ?}
? ?/* other section styles */
?}
?/* other post styles */
}

但是這樣生成出來的選擇器會有 .post section .section-title .section-link,很多時候我們覺得寫成 .post .section-link 就夠了。

于是我們在 Stylus 中可以這么寫:

.post
?section
? ?.section-title
? ? ?color #333
? ? ?/.post .section-link
? ? ? ?color #999
? ?/* other section styles */

?/* other post styles */

這樣輸出的 CSS 就會是:

.post section .section-title {
?color: #333;
}

.post .section-link {
?color: #999;
}



這就是我們想要的樣子了。當然也可以這樣寫:

.post
?section
? ?.section-title
? ? ?color #333
? ?/* other section styles */

?.section-link
? ?color #999
?/* other post styles */

我個人是推薦這種寫法(不使用 root 引用)的,因為當你確定 .section-link 的樣式不依賴于它位于 section 或 .section-title 下時,就不應該嵌套于此。否則如果為了一點點性能上的考慮(還不一定會是優化),使得設計意圖變得更不準確,我覺得得不償失。

變量

變量無疑為 CSS 增加了一種有效的復用方式,減少了原來在 CSS 中無法避免的重復「硬編碼」。

Less:

@red: #c00;

strong {
?color: @red;
}

Sass:

$red: #c00;

strong {
?color: $red;
}


Stylus:

red = #c00

strong
?color: red

Less 的選擇有一個問題:@ 規則在 CSS 中可以算是一種「原生」的擴展方式,變量名用 @ 開頭很可能會和以后的新 @ 規則沖突。(當然理論上只要 CSS 規范不引入 @a: b 這樣的規則,問題也不大。而且規范制定的時候也會參考很多現有的實現。)

相比之下 Sass 的選擇中規中矩,而 Stylus 就不同了,不需要額外的標志符。這意味著:在 Stylus 中,我們可以覆寫 CSS 原生的屬性值!Stylus 的設計讓人有一種「你以為你在寫 CSS,但其實你不是」的感覺,后面會有更多這樣的例子。

順便說一下,CSS 規范也有關于變量實現的草案,目前的方案是這個樣子的:

/* global scope */
:root {
?--red: #c00;
}


strong {
?color: var(--red);
}

不管語法槽點如何,原生 CSS 變量可以通過 DOM 結構來繼承,也就是說是代碼真正「運行」時(runtime)決定的。元素引用一個變量時會按 DOM 向上查找定義在上層元素上的同名變量。這一點是任何預處理語言都無法做到的。可以用 Firefox 31+ 看一下這個 demo。至于這種機制是不是好用,暫時還沒研究過。不過從開發的思維慣性來看,還很難一下子適應這種方式。

變量作用域

三種預處理器的變量作用域都是按嵌套的規則集劃分,并且在當前規則集下找不到對應變量時會逐級向上查找,注意這個和原生 CSS 的邏輯是完全不同的。

如果我們在代碼中重寫某個已經定義的變量的值,Less 的處理邏輯和其他兩者有非常關鍵的區別。在 Less 中,這個行為被稱為「懶加載(Lazy Loading)」。所有 Less 變量的計算,都是以這個變量最后一次被定義的值為準。舉一個例子更容易說清楚:

Less:

@size: 10px;
.box {
? ?width: @size;
}

@size: 20px;
.ball {
? ?width: @size;
}

輸出:

.box {
?width: 20px;
}

.ball {
?width: 20px;
}

而在 Stylus 中:

size = 10px
.box
?width: size

size = 20px
.ball
?width: size

輸出:

.box {
?width: 10px;
}

.ball {
?width: 20px;
}

Sass 的處理方式和 Stylus 相同,變量值輸出時根據之前最近的一次定義計算。這其實代表了兩種理念:Less 更傾向接近 CSS 的聲明式,計算過程弱化調用時機;而 Sass 和 Stylus 更傾向于指令式。這兩種方式會導致怎樣的結果呢?

舉個例子來說,對于 Less,如果項目中引入了這樣一個文件:

@error-color: #c00;
@success-color: #0c0;
.error {
?color: @error-color;
?background-color: lighten(@error-color, 40%);
}
.success {
?color: @success-color;
?background-color: lighten(@success-color, 40%);
}

在業務代碼中,在不修改外部引入文件的情況下,如果我想重寫這兩種狀態的配色,只需要重新配置 @error-color 和 @success-color 這兩個變量,就能改變 .error 和 .success 的樣式。

而在 Stylus 中,如果引入的第三方樣式庫中有這樣的代碼:

error-color = #c00
success-color = #0c0

.error
?color: error-color
?background-color: lighten(error-color, 40%)

.success
?color: success-color
?background-color: lighten(success-color, 40%)

這種情況下后面的代碼就無法通過重寫變量值來覆蓋樣式了。Sass 也是如此。優點是 Stylus 和 Sass 這樣的處理會不容易受多個第三方庫變量名沖突的影響,因為一個變量不能影響在定義它以前的輸出樣式。

由于 Sass 和 Stylus 變量在「運行」過程中使用完可以修改后再使用輸出不同的值,所以這兩者還提供了「僅當變量不存在時才賦值」的功能:

Sass:

$x: 1;
$x: 5 !default;
$y: 3 !default;

// $x = 1, $y = 3

Stylus:

x = 1
x := 5 // or x ?= 5
y = 3

// x = 1, y = 3

因為變量只能在輸出前修改才能生效,所以如果要定制第三方庫的樣式,用戶代碼理論上得插入第三方庫的配置與樣式之間才能生效。而有了 !default,第三方庫在提供默認配置時可以將開發給用戶修改的變量設置為 !default,這樣只要用戶提前引入配置進行覆蓋,就可以按需重寫默認配置了:

// lib.scss
$alert-color: red !default;
.alert {
?color: $alert-color;
}// var.scss
$alert-color: #c00;// page.scss
@import var
@import lib

這樣最終頁面輸出的效果就是被用戶重定義過的內容了。

/* page.css */
.alert {
?color: #c00;
}

由于 Less 處理變量的方式,如果我們要引入多個外部樣式庫或在多個團隊進行合作開發時,如果不能確保開發過程可控,那為變量添加模塊前綴就變得很有必要。

此外,Sass 中提供一個 !global 的語法來讓局部變量變成全局變量,也就是說 Sass 代碼可以在內層覆蓋全局變量的值。輸出一段局部的樣式可能使得后續所有樣式都受到全局變量變化的影響。(這其實是 Sass 開始時默認的邏輯,Sass 3.3 以前所有變量都是全局的,之后改成了和 Less 和 Stylus 一樣有嵌套作用域,全局變量要顯式指定 !global。)

插值

預處理器都有定義變量的功能,除了在最常見的屬性值中使用,其他還有哪些地方能用變量來增強對樣式的抽象、復用呢?

變量名插值

Less 中支持 @@foo 的形式引用變量,即該變量的名字是由 @foo 的值決定的。比如我們可以利用它簡化更清晰地調用 mixin:

// some icon font lib

// variables with prefix to prevent conflicts
@content-apple: "A";
@content-google: "G";

// clearer argument values
.icon-content(@icon) {
?@var: ~"content-@{icon}";
?&::before {
? ?content: @@var;
?}
}

.icon-apple {
?.icon-content(apple); // "A"
}

.icon-google {
?.icon-content(google); // "G"
}

選擇器插值

選擇器是樣式表和 DOM 的紐帶,是我們實際暴露給 HTML 的接口。支持插值顯然可以讓接口更不容易和其他內容沖突。假設我們在開發一個 UI 庫,生成的組件類名希望有一個可配置的前綴,這時選擇器插值就變得相當重要。初看下來,三者用法類似:

Less:

@prefix: ui;
.@{prefix}-button {
?color: #333;
}

Sass:

$prefix: ui
.#{$prefix}-button
?color: #333;

Stylus:

prefix = ui
.{prefix}-button
?color #333

但是在 Less 中,有一個很嚴重的問題:通過選擇器插值生成的規則無法被繼承(Extend dynamically generated selectors)!當然,如果有類似 Placeholder 的機制,這都不是事兒了。問題是 Less 沒有!未來的方案看來可能是通過 :extend(.mixin()) 的方式實現類似功能(:extend mixins)。雖然用 :extend 本身的語法說不過去,但是在現有機制上來看還算可以接受。關于樣式的繼承復用,后面會詳細講到。

@import 語句插值

Sass 中只能在使用 url() 表達式引入時進行變量插值:

$device: mobile;
@import url(styles.#{$device}.css);

Less 中可以在字符串中進行插值:

@device: mobile;
@import "styles.@{device}.css";

Stylus 中在這里插值不管用,但是可以利用其字符串拼接的功能實現:

device = "mobile"
@import "styles." + device + ".css"

注意由于 Less 的 Lazy Load 特性,即使是 @import 也是可以在后面的文件內容中進行覆蓋的,修改掉變量就可以在前面引入不同的外部文件。而 Sass 與 Stylus 一旦輸出語句,就無法通過變量改變了。

屬性名插值

三個預處理器的目前版本都支持屬性名插值,用法也類似。這里僅以 Stylus 為例:

red-border(sides)
?for side in sides
? ?border-{side}-color: red // property name interpolation

.x
?red-border(top right)

輸出:

.x {
?border-top-color: #f00;
?border-right-color: #f00;
}

其他 @ 規則插值

三種預處理器均支持在 @media、@keyframes、@counter-style 等規則中進行插值。@media 插值主要用來做響應式的配置,而 @keyframes 這樣帶名稱名稱的 @ 規則則可以通過插值來避免命名沖突。

Less:

@m: screen;
@orient: landscape;
@media @m and (orientation: @orient) {
?body {
? ?width: 960px;
?}
}

@prefix: ui;
@keyframes ~"@{prefix}-fade-in" {
?0% {
? ?opacity: 0;
?}
?100% {
? ?opacity: 1;
?}
}

Sass:

$m: screen;
$orient: landscape;
@media #{$m} and (orientation: $orient) {
?body {
? ?width: 1000px;

?}
}

$prefix: ui;
@keyframes #{$prefix}-fade-in {
?0% {
? ?opacity: 0;
?}
?100% {
? ?opacity: 1;
?}
}

Stylus:

m = screen
orient = landscape
mq = m + " and (orientation: " + orient + ")"
@media mq
?body
? ?width: 960px

vendors = official
prefix = ui;
@keyframes {prefix}-fade-in {
?0% {
? ?opacity: 0;
?}
?100% {
? ?opacity: 1;
?}
}

三者均會輸出如下 CSS:

@media screen and (orientation: landscape) {
?body {
? ?width: 960px;
?}

}
@keyframes ui-fade-in {
?0% {
? ?opacity: 0;
?}

?100% {
? ?opacity: 1;
?}

}

Stylus 中似乎有 and 時由于表達式計算的邏輯不能直接像 Less 與 Sass 那樣寫插值,所以這里采用了字符串拼接的方式。

@import

@import 對于模塊化開發來說非常有幫助,但就這個功能來說,三種預處理器的行為各不相同。

先說 Less,Less 擴展了語法,為 @import 增加了多種選項:

  • @import (less) somefile.ext

  • 會將無論什么擴展名的文件都作為 Less 文件引入、一起編譯;

  • @import (css) somefile.ext

  • 直接編譯生成 @import somefile.ext,當做原生 @import;

  • @import (inline) somefile.ext

  • 直接將外部文件拷貝進輸出文件的這個位置,但不會參與編譯;

  • @import (reference) somefile.ext

  • 外部文件參與編譯,但不輸出內容,僅用來被本文件中的樣式繼承;

  • @import (optional) somefile.ext

  • 引入文件但在文件不存在時不報錯,靜默失敗。

    上面的選項是可以聯合使用的,比如可以這樣寫:

    @import?(less,?optional)?somefile.ext;

    除此之外還有 once 和 multiple 選項分別用來表示去重和不去重的引入方式,默認為 once。在不寫任何選項時,Less 會根據擴展名進行推斷來決定引入邏輯。

    Sass 沒有擴展語法,而是自己推斷引入的方式。.css 后綴、絕對路徑、url() 表達式和帶有 media query 的 @import 會直接用原生 @import,其他都會作為 Sass 代碼參與編譯。相比之下 Less 更靈活也更復雜。Sass 有個特有的功能叫做「partial」,因為 Sass 默認的編譯工具可以編譯整個目錄下的文件,所以當一些文件不需要編譯時,可以在文件名前加上 _ 表明這是一個被別的模塊引入本身不需要編譯的代碼片段。Less 的 lessc 由于本來就只處理一個文件,所以這件事就交給用戶自己去寫編譯腳本了。Sass 中有一個比較棘手的問題是,@import 不會被去重,多次引入會導致一個樣式文件被多次輸出到編譯結果中。為了解決這個問題,Foundation 做了如下的 hack:

    // IMPORT ONCE
    // We use this to prevent styles from being loaded multiple times for components that rely on other components.
    $modules: () !default;

    @mixin exports($name) {
    ?// Import from global scope
    ?$modules: $modules !global;
    ?// Check if a module is already on the list
    ?$module_index: index($modules, $name);
    ?@if (($module_index == null) or ($module_index == false)) {
    ? ?$modules: append($modules, $name) !global;
    ? ?@content;
    ?}
    }

    然后在定義樣式時都調用 exports 這個 mixin 來輸出,起到只輸出一次的效果。

    Stylus 和 Sass 比較接近,也使用隱性推斷的方式,但在處理重復輸出的問題上,Stylus 給出了一個自定義指令 @require,用法和 @import 完全一樣,但只會輸出一次。Stylus 還支持通配符,比如 @import 'product/*' 會引入 product 目錄下的所有 .styl 文件,但因為一般引入樣式都要顯式指定順序,所以這個功能實用性不高。

    三者相比較之下,Sass 的引入功能似乎有點殘缺,不能去重是很大的硬傷。雖然能用 Foundation 那種方式「解決」,但實際上這是語言本身應該解決的問題。

    混入

    混入(mixin)應該說是預處理器最精髓的功能之一了。它提供了 CSS 缺失的最關鍵的東西:樣式層面的抽象。從語法上來說,三種預處理器的差異也比較大,這甚至會直接影響到我們的開發方式。

    Less 的混入有兩種方式:

  • 直接在目標位置混入另一個類樣式(輸出已經確定,無法使用參數);

  • 定義一個不輸出的樣式片段(可以輸入參數),在目標位置輸出。(注:后面如無特殊說明,mixin 均用來指代此類混入。

  • 舉例來說:

    .alert {
    ?font-weight: 700;
    }

    .highlight(@color: red) {
    ?font-size: 1.2em;
    ?color: @color;
    }

    .heads-up {
    ?.alert;
    ?.highlight(red);
    }


    最后輸出:


    .alert {
    ?font-weight: 700;
    }

    .heads-up {
    ?font-weight: 700;
    ?font-size: 1.2em;
    ?color: red;
    }


    可以混入已有類樣式這一點很值得商榷。在上面的例子中,.alert 樣式在被混入時甚至可以是 .alert();;.highlight() 混入時也可以寫成 .highlight;。那么我們遇到這樣的代碼時根本不知道 alert 會不會是一個 HTML class。但由于這一點是在 Less 還不支持 extend 時就有的,所以也能夠理解作者可能就是將這作為 extend 來用了。所以目前比較好的實踐是:用代碼規范規約開發者不得使用直接混入已有類樣式的方式,而是先定義 mixin 然后在輸出的類樣式中進行調用,調用時必須顯式加上 () 來表明這不是一個 class(事實上百度 EFE 已有的 Less 編碼規范就是這么定義的)。繼承則應該直接通過 Less 的 :extend 來實現。

    另外需要注意的是,Less 在進行混入時,會找到所有符合調用參數的「mixin 簽名」的樣式一起輸出。比如:


    .mixin(dark; @color) {
    ?color: darken(@color, 10%);
    }
    .mixin(light; @color) {
    ?color: lighten(@color, 10%);
    }
    .mixin(@_; @color) {
    ?display: block;
    }

    @switch: light;
    .class {
    ?.mixin(@switch; #888);
    }


    這個例子中,第二個和第三個 mixin 都匹配了調用時的參數,于是它們的規則都會被輸出:


    .class {
    ?color: #a2a2a2;
    ?display: block;
    }


    也就是說同名的 mixin 不是后面覆蓋前面,而是會累加輸出。只要參數符合定義,就會將 mixin 內部的樣式規則、甚至變量全部拷貝到目標作用域下。

    這一點同樣會帶來一個問題:如果存在和 mixin 同名的 class 樣式,如果 mixin 沒有參數則在調用時會把對應的 class 樣式一起輸出,這顯然是不符合預期的。

    假設有個叫 .clearfix 的 mixin,有兩個 class 樣式調用了它(其中一個也叫 clearfix):


    .clearfix() {
    ?*zoom: 1;
    ?&:before,
    ?&:after {
    ? ?display: table;
    ? ?content: "";
    ?}
    }

    .clearfix {
    ?.clearfix();
    }

    .list {
    ?.clearfix();
    }


    得到的輸出是:


    .clearfix {
    ?*zoom: 1;
    }

    .clearfix:before,
    .clearfix:after {
    ?display: table;
    ?content: "";
    }

    .clearfix:after {
    ?clear: both;
    }

    .list {
    ?*zoom: 1;
    }

    .list:before,
    .list:after {
    ?display: table;
    ?content: "";
    }

    .list:after {
    ?clear: both;
    }

    .list:before,
    .list:after {
    ?display: table;
    ?content: "";
    }

    .list:after {
    ?clear: both;
    }


    .list 的樣式調用了兩次!這一點在開發中一定要注意,不要給和非輸出型 mixin 同名的類定義樣式。

    對于 Sass,語義非常明確:


    @mixin large-text {
    ?font: {
    ? ?family: Arial;

    ? ?size: 20px;
    ? ?weight: bold;
    ?}
    ?color: #ff0000;
    }

    .page-title {
    ?@include large-text;
    ?padding: 4px;
    ?margin-top: 10px;
    }


    Sass 用 @mixin 和 @include 兩個指令清楚地描述了語義,不存在混入類樣式的情況,但是書寫時略顯繁瑣一些。當然,用 Sass 語法 而非 SCSS 語法的話可以簡單地用 = 定義 mixin,用 + 引入 mixin:


    =large-textfont:family:?Arialsize:?20pxweight:?boldcolor:?#ff0000.page-title+large-textpadding:?4pxmargin-top:?10px


    和 Less 不同,同名的 mixin 可以覆蓋之前的定義,作用機制類似變量。

    Stylus 和 Sass 類似,但不用什么特殊的標記來引入:


    border-radius(n)
    ?-webkit-border-radius: n
    ?-moz-border-radius: n
    ?border-radius: n

    .circle
    ?border-radius(50%)


    Stylus 中還有一個「透明 mixin」的功能,也就是說引入 mixin 完全可以和引入普通屬性一樣!例如上面的這個 mixin,也可以這樣引入:

    .circle
    ?border-radius: 50%


    這意味著可以把兼容性上的處理隱藏在 mixin 中,直接用標準屬性同名的 mixin 按普通屬性的方式輸出。當不需要兼容老瀏覽器時,直接把 mixin 定義刪除仍然能夠正常輸出。不過這種寫法雖然感覺非常「爽快」,但要求開發者必須能很好地區分原生屬性和某個樣式庫中提供的 mixin 功能(對于有經驗的開發者問題不大),而且透明意味著看到一個普通屬性開發者不能判斷是否已經在某處用 mixin 進行了重寫,無法明確知道這里的代碼最后輸出會不會發生變化。在可控條件下,這個功能應該說是非常誘人的。

    將聲明塊作為混入參數

    如果說調用時想傳入一組樣式聲明而非單個值,三種預處理器都提供了相應的功能,但實現方式各有不同。

    在 Less 中需要先定義一個「規則集變量」(detached ruleset,其實就是 CSS 聲明塊,即規則集去掉選擇器的部分),然后在調用 mixin 時把它作為參數傳進去,然后在 mixin 中用 @var() 的方式輸出:

    .red(@custom) {
    ?color: red;
    ?@custom();
    }

    .alert {
    ?@styles: {
    ? ?font-weight: 700;
    ? ?font-size: 1.5em;
    ?}

    ?.red(@styles);
    }

    在 Sass 和 Stylus 中,都支持直接在 mixin 調用下層傳入聲明塊:

    Sass 下直接跟一個聲明塊即可,然后用關鍵字 @content 來進行輸出:

    @mixin red() {
    ?color: red;
    ?@content;
    }

    .alert {
    ?@include red() {
    ? ?font-weight: 700;
    ? ?font-size: 1.5em;
    ?}
    }

    Stylus 支持兩種方法,首先是 Less 那樣的「具名」聲明塊,調用時當做變量:

    red(foo)
    ?color: red
    ?{foo}

    .alert
    ?foo =
    ? ?font-weight: 700
    ? ?font-size: 1.5em
    ?red(foo)

    第二種是 Sass 那樣類似傳入「字面量」,并且用關鍵詞 block 輸出的方式。這種方式需要為要傳入聲明塊的 mixin 前添加一個 + 符號(可能是來自 SCSS 的對應功能):

    red()
    ?color: red
    ?{block}

    .alert
    ?+red()
    ? ?font-weight: 700
    ? ?font-size: 1.5em

    第二種方式可以看做是第一種方式的語法糖,在 mixin 只需要傳入一個聲明塊時可以免去起名字帶來的困擾。

    相比之下 Less 只支持先定義變量后傳入的方式,優點是可以傳入多個聲明塊;而 Sass 只支持傳入一個「匿名」聲明塊但是更簡單;Stylus 則是兩種方式都支持。這個功能在抽象「需要應用樣式的條件」時非常有用,比如我們基于 Stylus 的樣式庫 rider 中就用它來實現對 media query 的抽象封裝。

    繼承

    混入很好用,可也有問題:如果多個地方都混入同樣的代碼,會造成輸出代碼的多次重復。比如在 Stylus 下:

    message()
    ?padding: 10px
    ?border: 1px solid #eee

    .message
    ?message()

    .warning
    ?message()
    ?color: #e2e21e

    會輸出:

    .message {
    ?padding: 10px;
    ?border: 1px solid #eee;
    }

    .warning {
    ?padding: 10px;
    ?border: 1px solid #eee;
    ?color: #e2e21e;
    }

    而我們可能期望的輸出是:

    .message,
    .warning {
    ?padding: 10px;
    ?border: 1px solid #eee;
    }

    .warning {
    ?color: #e2e21e;
    }

    也許大家會說可以這么寫:

    message()
    ?padding: 10px
    ?border: 1px solid #eee

    .message,
    .warning
    ?message()

    .warning
    ?color: #e2e21e

    這樣就可以按需要輸出了。但其實預處理器的一個好處就是可以方便我們進行模塊化開發。上面的例子中,.message 和 .warning 的樣式如果是分布在兩個模塊中的,我合并過的選擇器組樣式寫在哪里呢?情況更復雜的時候就更棘手了。

    這個時候就該繼承出場了:

    .message
    ?padding: 10px
    ?border: 1px solid #eee

    .warning
    ?@extend .message
    ?color: #e2e21e

    這樣就可以按模塊進行開發(不管是分文件還是在同一文件中按業務功能安排樣式的順序),同時兼顧輸出的效率了。

    Stylus 的繼承方式來自 Sass,兩者如出一轍。 而 Less 則又「獨樹一幟」地用偽類來描述繼承關系:

    .message {
    ?padding: 10px;
    ?border: 1px solid #eee;
    }

    .warning {
    ?&:extend(.message);
    ?color: #e2e21e;
    }
    /* Or:
    .warning:extend(.message) {
    ?color: #e2e21e;
    }
    */

    同時,Less 默認只繼承父類本身的樣式,如果要同時繼承嵌套定義在父類作用域下的樣式,得使用關鍵字 all,比如 &:extend(.message all);。

    關于使用偽類描述繼承關系,Hax 在 Less 的另一個 issue 下曾經言辭激烈地提出了批評,同時也遭到了 Less 項目組毫不客氣的回應。我個人完全贊同 Hax 的看法,因為選擇器是用來在樹結構中找到元素的,和樣式本身完全無關。但 Less 社區在當時卻對這個語法表示了一致的贊同,不禁讓人對其感到擔憂。

    不管語法如何,繼承功能還有一個潛在的問題:繼承會影響輸出的順序。假設有如下的 Sass 代碼:

    .active {
    ? color: red;
    }
    button.primary {
    ? color: green;
    }
    button.active {
    ? @extend .active;
    }

    而對應的 HTML 代碼是:

    <button?class="primary?active">Submit</button>

    很容易誤以為效果是紅色的。而其實生成的 CSS 順序如下:

    .active, button.active {
    ?color: red;
    }


    button.primary {
    ?color: green;
    }

    由于合并選擇器的關系 .active 被移到了 .primary 之前,所以依賴順序而非選擇器 specificity 時可能會遇到陷阱。

    placeholder

    Placeholder 是什么?簡單來說就是一個聲明塊(預處理器 DSL 中的聲明塊,包含其下嵌套規則),但是不會在最終的 CSS 中輸出。其實這是一組「抽象」樣式,只存在于預處理器的編譯過程中(類似 mixin),但不同之處是它可以被繼承。這樣我們就可以在純樣式層為聲明塊起與樣式強耦合的名稱而不怕它出現在 CSS 與 HTML 的「接口」——選擇器之中了。

    Sass:

    %red-card {
    ?border: 1px solid #300;
    ?background-color: #ecc;
    ?color: #c00;
    }

    .alert {
    ?@extend %red-card;
    }

    Stylus:

    $red-card
    ?border: 1px solid #300
    ?background-color: #ecc
    ?color: #c00

    .alert
    ?@extend $red-card

    均輸出:

    .alert {
    ?border: 1px solid #300;
    ?background-color: #ecc;
    ?color: #c00;
    }

    Less 目前不支持這個功能,但開發組目前的共識是可能會用繼承 mixin 的方式來實現,比如上面的這個例子未來可能可以通過如下方法實現:

    .red-card() {
    ?border: 1px solid #300;
    ?background-color: #ecc;
    ?color: #c00;
    }

    .alert {
    ?&:extend(.red-card());
    }

    當前在 Less 下也有一個 hack 來模擬 placeholder 功能,原理是利用 @import (reference) 來實現「placeholder」不輸出的功能:

    // placeholder.less
    .red-card {
    ?border: 1px solid #300;
    ?background-color: #ecc;
    ?color: #c00;
    }

    // style.less
    @import (reference) "placeholder.less";
    .alert {
    ?&:extend(.red-card);
    }

    不過 @import (reference) 在復雜一些的情況下(被引入的文件有 @import、有 :extend 等)可能會遇到一些 bug,比如:#1851、#1878、#1896。目前以 reference 方式引入 Bootstrap 時就會直接產生代碼輸出。

    函數

    先說說原生函數。三種預處理器都自帶了諸如色彩處理、類型判斷、數值計算等內置函數,目前版本的數量都在 80 個左右。由于 Sass 和 Stylus 都內置腳本語言,所以自帶函數中包括了很多處理不同數據類型、修改選擇器的函數。Sass 更是提供了不少特性檢測函數比如 feature-exists($feature)、variable-exists($name) 等,這為第三方庫的兼容性提供了很好的保障。因為有了這些函數可以方便地對不同版本的 Sass 編譯器有針對性地提供兼容,而不怕在老版本的編譯環境中直接報錯。

    三者調用函數的方式幾乎一致,不同之處在于 Sass 和 Stylus 支持直接指定參數名的方式傳入參數。以 Stylus 為例:

    subtract(a, b)
    ?a - b

    subtract(b: 10, a: 25) // same as substract(25, 10)

    這樣做的好處是,如果參數列表比較長,Stylus 可以直接為列表后面的參數賦值,而不需要一路將之前的參數填上 null 或默認值。Stylus 將這個特性稱為「Named parameters」,而 Sass 稱為「Keyword arguments」。

    關于函數,真正的區別在于:Sass 和 Stylus 都支持用 DSL 直接添加自定義函數,而 Less 中如果要添加自定義函數必須通過使用插件(2.0.0 以后的版本才支持插件)。這決定了用 Sass 和 Stylus 書寫的代碼可移植性更高,不需要編譯環境有插件即可運行,而 Less 則需要額外添加編譯時的依賴。

    Sass 中自定義函數需要使用 @function 指令,并用 @return 指令返回結果:

    @function golden-ratio($n) {
    ?@return $n * 0.618;
    }

    .golden-box {
    ?width: 200px;
    ?height: golden-ratio(200px);
    }

    在 Stylus 中,這些都是隱含的,最后一個表達式的值會作為返回值:

    golden-ratio(n)
    ?n * 0.618

    .golden-box
    ?width: 200px
    ?height: golden-ratio(@width)

    這種寫法和 mixin 有什么區別?當把函數作為 mixin 調用時,如果其中有 prop: value 這樣格式的內容,就會被當做樣式規則輸出。Stylus 中大量的內容都是根據調用時的 context 去隱式推斷該使用什么邏輯進行輸出,而非 Less 和 Sass 那樣使用關鍵字去顯式地進行區分。

    邏輯控制

    Sass 中通過常見的 @if、@else if、@else 實現條件分支,通過 @for、@each、@while 實現循環,配合 map 和 list 這兩種數據類型可以輕松地實現多數編程語言提供的功能。

    在 Stylus 中,不需要使用 @ 規則,提供了 if、else if、else、unless、for...in 來實現類似功能,語法比 Sass 更簡潔靈活。

    再來看 Less,上面說到的功能 Less 都沒有提供。那在 Less 中如何進行邏輯控制呢?Less 中只有一個方式:使用 mixin。

    Less 中的 mixin 通過「guard」的方式支持簡單的條件分支控制。比如我們要實現一個控制 ::placeholder 樣式的 mixin,當傳入顏色時只設置顏色,當傳入聲明塊時輸出對應的樣式規則,其他情況輸出一個默認的 color:

    .mixin(@val) when (iscolor(@val)) {
    ?color: @val;
    }
    .mixin(@val) when (isruleset(@val)) {
    ?@val();
    }
    .mixin(@val) when (default()) {
    ?// default() in guards acts as else
    ?color: #666;
    }

    Guard 語句中的語法非常類似 CSS media query 中的對應功能,事實上這也是 Less 一直以來的理念:保持聲明式語法,弱化指令和流程。但是事實上,這為書寫需要提供靈活接口的樣式庫造成了非常大的不便。最簡單的三元表達式在 Less 中也需要先定義一個 mixin,根據判斷條件寫對應的 guard 表達式,然后再輸出。

    而對于循環,Less 本身并不支持。但官網給出了一個使用 mixin 遞歸調用模擬循環的例子:

    .loop(@counter) when (@counter > 0) {
    ?.loop((@counter - 1)); ? ?// next iteration
    ?width: (10px * @counter); // code for each iteration
    }

    div {
    ?.loop(5); // launch the loop
    }

    編譯結果為:

    div {
    ?width: 10px;
    ?width: 20px;
    ?width: 30px;
    ?width: 40px;
    ?width: 50px;
    }

    這是一種非常別(dàn)扭(téng)的實現方式,但從 Less 開發團隊的態度來看,未來并沒什么可能在 Less 中見到真正的條件分支和循環——因為「Less 不是 Sass」。

    由于邏輯處理能力不能與 Sass 和 Stylus 相比,所以在 Less 中可能還會需要借助 JS 表達式來進行 mixin 參數的解析處理。這個功能 Less 官方已經是不推薦使用的了(已經從官網文檔中移除)——因為使用這一功能也會導致 Less 代碼的可移植性變低,因為直接內嵌 JS 代碼,所以無法使用 dotless 等其他語言的 Less 編譯器進行處理。而且不同 JS 引擎還可能有兼容性差異。

    總結

    我個人認為,Less 從語言特性的設計到功能的健壯程度和另外兩者相比都有一些缺陷,但因為 Bootstrap 引入了 Less,導致 Less 在今天還是有很多用戶。用 Less 可以滿足大多數場景的需求,但相比另外兩者,基于 Less 開發類庫會復雜得多,實現的代碼會比較臟,能實現的功能也會受到 DSL 的制約。比 Stylus 語義更清晰、比 Sass 更接近 CSS 語法,使得剛剛轉用 CSS 預編譯的開發者能夠更平滑地進行切換。當初 Sass 并不支持 SCSS 語法,使得轉投 Sass 成本較高,所以 Alexis Sellier 才萌生開發一個更「CSS」的預處理器的念頭。大獲成功以后反過來影響到了 Sass,迫使其也支持類似 CSS 語法的 SCSS。另外,Less 支持瀏覽器端編譯,這無疑降低了開發門檻,使得很多非專業的開發者能夠更快地上手(對于一些個人項目來說,能讓項目跑起來就行,對前端的性能并沒有專業工程師那么高的要求)。

    Sass 在三者之中歷史最久,也吸收了其他兩者的一些優點。從功能上來說 Sass 大而全,語義明晰但是代碼很容易顯得累贅。主項目基于 Ruby 可能也是一部分人不選擇它的理由(Less 開始也是基于 Ruby 開發,后來逐漸轉到 less.js 項目中)。 Sass 有一個「事實標準」庫——Compass,于是對于很多開發者而言省去了選擇類庫的煩惱,對于提升開發效率也有不小的幫助。

    Stylus 的語法非常靈活,很多語義都是根據上下文隱含的。基于 Stylus 可以寫出非常簡潔的代碼,但對使用團隊的開發素養要求也更高,更需要有良好的開發規范或約定。Stylus 是前 Node.js 圈第一大神 TJ Holowaychuk 的作品,雖然他已經棄坑了,但是仍然有不小的號召力。和 Sass 有 Compass 類似,Stylus 有一個官方開發的樣式庫 nib,同樣提供了不少好用的 mixin。對于比較有經驗的開發者,用 Stylus 可能更會有一種暢快的感覺。總的來說用一個詞形容 Stylus 的話,我會用「sexy」。

    總的來說,三種預處理器百分之七八十的功能是類似的。Less 適合幫助團隊更快地上手預處理代碼的開發,而 Sass 和 Stylus 的差異更在于口味。比如有的人喜歡 jQuery 用一個 $ 做大部分的事,而另一些人覺得不一樣的功能就該有明確的語義上的差別。在這里我不會做具體的推薦。當然,再次聲明一下由于我個人接觸 Less 開發比較多,所以可能遇到的坑也多一些,文中沒有列出 Sass 和 Stylus 的問題并不代表他們沒有。


    轉載于:https://blog.51cto.com/xhtml/1682628

    總結

    以上是生活随笔為你收集整理的再谈 CSS 预处理器的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    免费观看黄 | 91亚洲网站 | 国内精品久久久久久久久 | 91视频在线播放视频 | 91日韩免费 | 国产高清不卡在线 | 欧美性大战久久久久 | 中文字幕第一页在线视频 | av女优中文字幕在线观看 | 亚洲精品在线观看免费 | 日韩精品视频免费在线观看 | 天天操天天干天天操天天干 | 中文国产字幕在线观看 | 中文超碰字幕 | 成年人黄色免费视频 | 麻豆免费看片 | 久久激情视频免费观看 | 久久福利| 五月婷婷亚洲 | 中文字幕在线播放第一页 | 亚洲综合欧美激情 | 九色精品免费永久在线 | 免费成人在线视频网站 | 久久久久精 | 婷婷色网站| 国产一区二区久久久 | 日韩激情在线视频 | 成年人免费在线播放 | 日韩和的一区二在线 | 米奇影视7777 | 爱av在线网 | 蜜臀av性久久久久蜜臀aⅴ四虎 | 国产福利a | 日韩激情视频在线观看 | 天天操夜夜操天天射 | 国内精品免费 | 91污视频在线 | 欧美成年网站 | 国产精品18久久久久vr手机版特色 | 色在线亚洲 | 亚洲精品久久久久www | 网站在线观看日韩 | 一区二区三区四区精品视频 | 成年人免费在线 | 日韩在线 | 狠狠色狠狠色综合日日92 | 91av网站在线观看 | 91亚洲网| 国产精品久久久久久久久久久久午夜片 | 国产99久 | 国产精品成人一区二区 | 中文字幕欲求不满 | 伊人色综合网 | 日韩精品中文字幕一区二区 | 二区在线播放 | 日日日日 | 国产日产av | 色婷婷精品大在线视频 | 中文在线字幕免费观看 | av在线电影播放 | 国产xxxx| 国产精品入口麻豆 | 伊人激情综合 | 视频直播国产精品 | 女人18精品一区二区三区 | 狠狠色丁香久久婷婷综合五月 | h视频日本 | 日本久久中文字幕 | 亚洲日本韩国一区二区 | 久久www免费视频 | 69精品久久 | 精品一二三四五区 | 日韩av高清在线观看 | 欧美在线一二 | 欧美日韩免费观看一区二区三区 | 国产精品久久久久久一区二区三区 | 99精品黄色片免费大全 | 日韩伦理一区二区三区av在线 | 日韩欧美在线视频一区二区三区 | 精品久久国产 | 亚洲精选久久 | 狠狠色狠狠色综合日日小说 | 欧美一级专区免费大片 | 久久精品久久99 | 九九视频在线播放 | 欧美日韩视频 | 91精品婷婷国产综合久久蝌蚪 | 国产美女精彩久久 | 色噜噜在线观看 | 国产又粗又猛又黄 | 精品久久久久久亚洲综合网站 | 免费在线观看成年人视频 | 婷婷久月 | 久久成人麻豆午夜电影 | 国产裸体无遮挡 | 国产精品网红直播 | 久久久久久久免费观看 | 99视频免费在线观看 | 激情婷婷 | 国产精品成人自产拍在线观看 | 免费久久99精品国产婷婷六月 | www,黄视频| 在线免费观看国产视频 | 四虎视频| 亚洲精品小区久久久久久 | 91丨九色丨蝌蚪丨对白 | www久久com| 久久久免费精品视频 | 中文字幕一区二区三区在线视频 | 亚洲精品午夜国产va久久成人 | 999视频在线观看 | 国产黄视频在线观看 | japanesexxxhd奶水| 久久精品国产亚洲aⅴ | 久久这里只有精品23 | 成人免费色 | 91亚洲在线观看 | 欧美日韩国产区 | 韩日精品在线 | 国产精品成人免费一区久久羞羞 | 久草免费资源 | 西西444www大胆高清视频 | 日黄网站 | 国产网红在线 | 久久曰视频 | 97超视频 | 久久男人免费视频 | 久久久久久久久电影 | 8x成人免费视频 | 欧美日韩在线观看一区二区 | 日韩三级av | 韩日在线一区 | 丁香婷婷久久 | 精品婷婷 | 欧美性生活免费 | 成人午夜电影免费在线观看 | 亚洲人成人在线 | 欧美巨大 | 青青久草在线视频 | 久操久| 亚洲美女精品视频 | 日韩大片免费观看 | 深爱激情五月网 | 日日夜夜狠狠 | 免费h在线观看 | 色综合 久久精品 | 中文字幕久久精品一区 | 免费视频 你懂的 | 精油按摩av| 特级免费毛片 | 精品久久久久_ | 岛国av在线 | 又黄又爽免费视频 | 99久久99久久精品国产片果冰 | 婷婷视频在线观看 | 免费观看一级特黄欧美大片 | 欧美日韩69 | 免费在线观看不卡av | 在线观看欧美成人 | 久久久久中文字幕 | 久久狠狠一本精品综合网 | 波多野结衣在线中文字幕 | 亚洲人成在线观看 | 国产精品一区二区在线免费观看 | 91亚洲影院 | 国产午夜亚洲精品 | 91精品国产麻豆 | 日韩在线网址 | 欧美一区二区三区在线视频观看 | 国产探花在线看 | 麻豆国产网站入口 | 国产在线欧美 | 国产一级h| 国产黄色片在线 | 久草在线视频精品 | 日韩电影一区二区三区 | 国产黄色精品在线 | 综合国产视频 | 免费av免费观看 | 亚洲乱码精品久久久 | 国产 日韩 欧美 自拍 | 日本丶国产丶欧美色综合 | 亚洲 综合 精品 | 激情欧美一区二区三区 | www.黄色网.com| 天天色天 | 手机版av在线 | 狠狠色2019综合网 | 91高清视频免费 | 亚洲专区 国产精品 | 麻豆视频免费在线 | 天天干视频在线 | 精品国精品自拍自在线 | 国产视频网站在线观看 | 国产v在线 | 在线精品视频免费播放 | 精品一区二区av | 一区二区三区在线观看免费视频 | 中文字幕免费一区二区 | 国产一区二区三区免费视频 | 久久成人毛片 | 色99之美女主播在线视频 | 国产精品久久久久久久久久久久午夜 | 亚洲春色综合另类校园电影 | 四虎国产永久在线精品 | 香蕉视频在线免费 | 精品主播网红福利资源观看 | 五月激情视频 | 尤物九九久久国产精品的分类 | 久草资源免费 | 91专区在线观看 | 久久艹国产 | 免费国产黄线在线观看视频 | 在线观看国产亚洲 | 成人在线视频免费观看 | 欧美亚洲精品在线观看 | 一区二区av | 欧美日韩中文国产一区发布 | 91精品婷婷国产综合久久蝌蚪 | 在线亚洲午夜片av大片 | 亚洲人天堂 | 国产精品久久久久久久99 | 国产精品成人国产乱 | 中文字幕av播放 | 免费日韩电影 | 在线视频婷婷 | 麻豆视频免费 | 91精品一区国产高清在线gif | 国产精品 中文字幕 亚洲 欧美 | 成人av电影在线播放 | 成年人网站免费观看 | 日本久久久久久久久 | 美女网站在线 | 国产亚洲在 | 国产午夜精品久久 | 中文字幕日本特黄aa毛片 | 国产午夜精品一区二区三区 | 在线观看91网站 | 亚洲国产字幕 | 免费一级片观看 | 日韩久久影院 | 99热高清| 亚洲丝袜中文 | 一级黄色片在线播放 | 在线观看国产亚洲 | 久久免费福利视频 | 色婷婷丁香| 亚洲国产精品久久久久婷婷884 | 午夜视频免费在线观看 | 成年人视频免费在线播放 | 国产精久久久久久久 | 黄色精品久久 | 天天操天天玩 | 天天躁天天躁天天躁婷 | 亚洲精品国产精品久久99热 | 国产精品观看在线亚洲人成网 | a v在线观看 | 婷婷综合伊人 | 中文字幕人成人 | 国产在线精品观看 | 免费观看第二部31集 | 韩国av免费| 99久久99久久精品国产片果冰 | 亚洲综合小说电影qvod | av在观看 | 精品国产欧美 | 亚洲成人二区 | 欧美乱熟臀69xxxxxx | www.久艹 | www.夜色321.com | 一区二区成人国产精品 | 国产精品久久久久久五月尺 | 日本三级吹潮在线 | 久草视频精品 | 一区中文字幕电影 | www.com操| 久久免费国产精品1 | 伊人婷婷久久 | 国产视频在线观看一区 | 久久综合免费视频 | 成年人视频在线免费 | 在线视频18在线视频4k | 91麻豆精品国产91久久久久久 | 一区二区三区国产欧美 | 五月开心六月伊人色婷婷 | 一本一道波多野毛片中文在线 | av在线播放不卡 | 97在线观看免费观看高清 | av三级av| 亚洲国产中文字幕在线视频综合 | 色偷偷人人澡久久超碰69 | 久久国产成人午夜av影院潦草 | 国产91精品一区二区绿帽 | 久久综合久久久 | 欧美成亚洲 | 日韩在线一级 | 国产综合在线观看视频 | 美腿丝袜av | 国产精品乱码久久 | 亚洲动漫在线观看 | 永久免费观看视频 | 国产视频在线观看一区二区 | 国产99色 | 久久免费视频在线观看30 | 99精品黄色片免费大全 | 国产不卡毛片 | 美女网站视频久久 | 亚洲爽爽网 | 91福利在线观看 | 婷婷干五月 | 日韩福利在线观看 | 一区二区网 | 久久成熟 | 免费观看完整版无人区 | 欧美极品一区二区三区 | 在线观看视频一区二区三区 | 国产视频资源在线观看 | 婷婷日| 久久精品二区 | 亚洲视频精品在线 | 日本夜夜草视频网站 | 中文字幕免费一区 | 免费在线观看不卡av | 欧美日韩性视频在线 | 一区二区观看 | 亚洲高清免费在线 | 91精品视频免费看 | 狠狠色狠狠色 | 日日天天干 | 天天激情综合 | 日韩v在线91成人自拍 | 亚洲无吗av | 欧美性生活小视频 | 久久香蕉电影 | 国产精品久久久久久久久久东京 | 久久在线精品 | 免费裸体视频网 | 99免费在线视频 | 婷婷久久一区 | 精产嫩模国品一二三区 | 日韩欧美在线中文字幕 | 在线播放 日韩专区 | 国产精品免费在线视频 | 国产欧美综合视频 | 亚洲综合成人婷婷小说 | 欧美片网站yy | 欧美孕交vivoestv另类 | 午夜精品一区二区三区在线播放 | 国产精品免费视频网站 | 91成人黄色 | 国产精品观看在线亚洲人成网 | 久久久久免费精品视频 | 久久综合免费视频影院 | 永久免费看av | 国产又黄又爽无遮挡 | 久久99网 | 美女黄久久 | 国产 日韩 在线 亚洲 字幕 中文 | 97超碰人人模人人人爽人人爱 | 成人av一区二区在线观看 | 久久99国产精品自在自在app | 国产精品一区二区在线看 | 少妇av网| 丁香5月婷婷 | 久久久视屏 | 999成人精品| 久久草草热国产精品直播 | 狠狠干夜夜操天天爽 | 久久久精品在线观看 | 精品国产自在精品国产精野外直播 | 手机看片99 | 丁香激情婷婷 | 欧美成人性战久久 | 99中文视频在线 | 在线观看视频99 | 狠狠干天天 | 久久久久99精品成人片三人毛片 | 国产精品精品久久久久久 | 欧美性久久久久久 | 国产精品女同一区二区三区久久夜 | 激情五月激情综合网 | 国产精品原创视频 | 成人午夜电影在线 | 精精国产xxxx视频在线播放 | 在线综合 亚洲 欧美在线视频 | 久久中文字幕导航 | 在线免费黄色av | 久久综合五月天 | 啪啪肉肉污av国网站 | 欧美日韩超碰 | 免费看一级片 | 久久久免费毛片 | 亚洲精品在线电影 | 天天草天天 | 区一区二区三区中文字幕 | 国产精品av一区二区 | 亚洲国产手机在线 | 中文字幕亚洲欧美 | 欧美日韩18| 欧美一区二区三区在线视频观看 | 久久男人视频 | 人人精品久久 | 激情av资源网 | 久久精品国产一区二区三 | 美女久久99| 日韩毛片在线播放 | 天天操天天干天天操天天干 | 欧美成亚洲 | 久久国产91 | 99亚洲天堂| 天天干天天天 | 国产高清在线 | 91色网址 | 日韩二区精品 | 亚洲综合激情小说 | 精品亚洲免费视频 | 久久蜜桃av | 国产一区二区不卡视频 | 九九视频在线观看视频6 | 久久久久国产精品免费网站 | 久视频在线| 久久高清毛片 | 视频在线观看91 | 日韩免费一区二区在线观看 | 99热这里只有精品国产首页 | 国产一级免费在线 | 免费视频网 | 欧美成人黄色 | 中文字幕日韩免费视频 | 久久伊人八月婷婷综合激情 | 亚洲精品视频免费在线观看 | 在线观看精品一区 | av在线等| 久久精品aaa | 操操碰 | 久久av在线播放 | 在线观看不卡的av | 久久免费福利 | 久久字幕精品一区 | 91精品在线免费观看视频 | 国产精品一区二区三区免费视频 | 91尤物国产尤物福利在线播放 | 国产成人精品不卡 | 一区 二区电影免费在线观看 | 色婷婷亚洲婷婷 | 免费观看久久 | 久草免费新视频 | 国产剧在线观看片 | 美女免费网站 | 99久久婷婷国产综合精品 | 伊甸园av在线| 久久精品激情 | 国产精品青草综合久久久久99 | 伊甸园永久入口www 99热 精品在线 | 日本一区二区不卡高清 | av电影一区 | 国产视频一| 久久综合电影 | 免费h在线观看 | 日本少妇久久久 | 五月天激情综合 | 西西人体4444www高清视频 | 国产精品久久久一区二区三区网站 | 久久久国产毛片 | 久久久久国产精品免费 | 狠狠色噜噜狠狠狠狠 | 亚洲视频 中文字幕 | 日韩国产精品久久久久久亚洲 | 一级性av | 91视频免费看 | 国产亚洲激情视频在线 | 免费看wwwwwwwwwww的视频 久久久久久99精品 91中文字幕视频 | 人人讲下载 | 色香蕉在线视频 | 亚洲精品午夜国产va久久成人 | 91丨九色丨国产丨porny精品 | 91大神精品视频在线观看 | 精品96久久久久久中文字幕无 | 日日摸日日添夜夜爽97 | 欧美特一级 | 中文字幕在线视频网站 | 99久久精品无免国产免费 | 日韩一级电影网站 | 国产免费一区二区三区网站免费 | 久久夜色精品国产欧美乱极品 | 亚洲天堂香蕉 | 国产不卡一 | 亚一亚二国产专区 | 久久婷婷激情 | 中文字幕在线观看视频一区二区三区 | 99免费看片 | 婷婷丁香久久五月婷婷 | 欧美男同网站 | 黄色大全免费观看 | 免费久久99精品国产婷婷六月 | 久久久久久久久亚洲精品 | 91视频 - x99av| 国精产品满18岁在线 | 久久精品国产免费 | 在线国产日韩 | 日韩免费高清在线观看 | 婷婷99| 亚洲 欧洲 国产 精品 | 91视频在线看 | 久久久久久草 | 国产精品久久久久久久久久久久久久 | 亚洲国产精品电影在线观看 | 久久国语露脸国产精品电影 | 欧美一级黄色网 | sesese图片 | 国产精品不卡视频 | 99热国产在线 | 午夜精品一区二区三区在线视频 | 国产成人福利在线观看 | 久久亚洲精品电影 | 91精品视频免费看 | 成人av高清 | 美女久久网站 | 久久99亚洲精品久久 | 99热最新精品 | 午夜久久网 | 国产在线高清精品 | 久久精品国产免费观看 | 粉嫩高清一区二区三区 | 久久躁日日躁aaaaxxxx | 亚洲夜夜网 | 中文字幕欧美日韩va免费视频 | 天天综合网国产 | 成人av在线网址 | 黄色av大片 | 欧美激情视频在线免费观看 | 久久久久久免费视频 | 日韩在线字幕 | 亚洲a网 | 国产成人一区二区三区免费看 | 国内小视频 | 又黄又爽又色无遮挡免费 | 久久免费视频6 | 亚洲午夜精品久久久 | 国产区精品在线观看 | 午夜av在线播放 | 香蕉网在线播放 | 亚洲国产精品成人va在线观看 | 精一区二区| 亚洲免费成人av电影 | 99国产视频 | 久久视频在线免费观看 | 日韩一区二区三区高清免费看看 | 亚洲va欧美va人人爽 | 日韩在观看线 | 中文字幕2021 | 激情偷乱人伦小说视频在线观看 | 亚洲蜜桃av | 婷婷在线视频 | 久久久污 | 久草免费在线观看视频 | 亚洲 欧美 变态 国产 另类 | 激情欧美一区二区三区 | 久草久 | 美女视频黄的免费的 | 在线观看中文字幕dvd播放 | 日本性xxx | 亚洲精品美女久久久久网站 | 日本不卡一区二区 | 国产色在线视频 | 日韩欧美在线高清 | 亚洲日本国产 | 人人讲下载 | 五月激情综合婷婷 | 欧美成人中文字幕 | 色婷婷激情 | 精久久久久 | 国产精品久久久久久高潮 | 国产精品久久久久影院日本 | 四虎国产精品永久在线国在线 | 日韩免费视频一区二区 | av一区在线播放 | 免费观看的黄色片 | 国产日韩欧美网站 | 91亚洲在线观看 | 免费看高清毛片 | 丁香六月综合网 | 亚洲美女免费精品视频在线观看 | 久久久www免费电影网 | 天天在线视频色 | 日本一区二区三区免费看 | 中国一级片在线观看 | 伊人婷婷网 | 国产精品18久久久久久首页狼 | 99精品在线观看 | 色婷婷欧美 | 亚洲日本va午夜在线电影 | 黄色在线观看www | 欧美一级久久久久 | 黄色在线网站噜噜噜 | 亚洲精品在线视频播放 | 天天插天天操天天干 | 丁香婷婷激情啪啪 | 91av在线免费播放 | 蜜臀av性久久久久av蜜臀三区 | 最近中文字幕免费av | 伊人永久在线 | 久久超 | www.国产毛片 | 久久久综合电影 | 涩涩资源网 | 在线免费视频 你懂得 | 四虎影视精品 | www.eeuss影院av撸 | 日韩理论在线视频 | 久久国产精品电影 | 在线va网站 | 一级黄色片在线 | 97**国产露脸精品国产 | 婷婷草| 午夜精品久久久久久 | 国产精品久久久久久电影 | 国产精品一区二区美女视频免费看 | 伊人久久av | 国产手机av在线 | 国产一二区在线观看 | 国产精品原创 | 亚洲劲爆av| 国内精品久久久久久久久久 | 国产乱老熟视频网88av | 亚洲激情校园春色 | 国产精品免费观看国产网曝瓜 | 综合在线色 | 久久国产精品免费 | 在线观看免费一级片 | 一区二区三区国 | 亚洲国产精品va在线 | 婷婷在线播放 | 久久永久免费视频 | 婷婷丁香色 | 亚洲视频在线看 | 欧美日韩另类在线 | 男女拍拍免费视频 | 午夜精品视频在线 | 亚洲综合激情五月 | 精品国产一区二区三区四区vr | 波多野结衣最新 | 久久久久一区二区三区四区 | 韩国三级一区 | 97在线播放| 国产成人av电影在线观看 | 99亚洲精品视频 | 狠狠操在线| 激情网色 | www黄色com | 日韩精品久久久免费观看夜色 | 日韩欧美91| 在线视频观看成人 | 国产精品三级视频 | 久草在线91 | 99精品福利视频 | 亚州欧美视频 | 午夜av免费观看 | 欧美日韩精品在线免费观看 | 日韩欧美国产精品 | 欧美激情第八页 | 国产婷婷在线观看 | 亚洲激情在线观看 | 在线91色| 最新的av网站 | 97av免费视频 | 中文字幕网址 | 99re国产视频 | 天堂av观看 | 天天干天天干天天 | 三级av在线| 丝袜美腿在线 | 在线国产一区二区三区 | 久久 精品一区 | 一区二区三区在线视频观看58 | 国产99一区二区 | 黄色特级毛片 | 国产资源免费在线观看 | 欧美成人影音 | 久久国产欧美日韩精品 | 91完整版在线观看 | 久草在线视频免费资源观看 | 日韩免费一区二区在线观看 | 美女搞黄国产视频网站 | 亚洲成av片人久久久 | 日韩欧美xxx| 91在线视频免费播放 | 国产资源精品在线观看 | 日韩欧美精品一区二区三区经典 | 日本久久成人中文字幕电影 | 天天射网站| 天天操夜夜曰 | 四虎8848免费高清在线观看 | 国产视频1| 亚洲精品视频免费看 | 亚洲国产97在线精品一区 | 欧美久久久久久久久久久久久 | 怡红院av久久久久久久 | 97碰碰精品嫩模在线播放 | 三级黄色a | 在线视频成人 | 精品一区二区6 | 国产精品扒开做爽爽的视频 | 国内久久精品视频 | 国产精品美女久久久久久免费 | 国产高清小视频 | 日日夜夜人人精品 | 91成人在线网站 | 91麻豆精品| 欧美成年网站 | 亚洲免费视频在线观看 | 日本二区三区在线 | 成片免费观看视频999 | 久久久久久久久久久免费 | 日韩在线国产精品 | 九九av | 99久久一区 | 成人毛片100免费观看 | 国产精在线 | 久久黄色小说视频 | 韩国三级av在线 | 在线观看国产一区 | 草久久久久 | 色综合天天色 | 国产精品一区二区在线播放 | 麻豆久久| 伊人久操 | 夜夜婷婷 | 制服丝袜天堂 | 中文av一区二区 | 婷婷新五月 | 国产精品久久久久久久久久直播 | 看毛片网站 | 综合色站 | 黄色三级视频片 | 欧美日韩三级 | 国产在线高清精品 | 在线看av的网址 | 最近日本字幕mv免费观看在线 | 99精品视频在线观看视频 | 91成年人在线观看 | 成人在线免费观看网站 | 国产精品久久久久久a | 免费在线黄色av | 免费av试看 | 中文字幕在线观看资源 | 国产精品对白一区二区三区 | 中文字幕在线观看视频免费 | a级国产毛片 | 在线观看亚洲免费视频 | 国产午夜在线 | 亚洲精品在线观看不卡 | 午夜精品久久久久久久99热影院 | 国产99久久精品一区二区300 | 久久99精品久久久久婷婷 | 久久精品一区二区三区视频 | 亚洲精品字幕在线观看 | 97人人澡人人爽人人模亚洲 | 免费在线精品视频 | 欧美大码xxxx| 伊人av综合 | 久久开心激情 | 成人av一区二区在线观看 | 国产a国产| 中文字幕一二 | 日韩激情中文字幕 | 国产精品久久久久久久久软件 | 在线影视 一区 二区 三区 | 亚洲国产一区二区精品专区 | 久久精品免费播放 | 婷婷色五 | 婷婷www | 精品福利网 | 日韩在线视频网址 | 91豆麻精品91久久久久久 | 欧美激情第28页 | 免费观看国产精品 | 超碰人人av | 国产精品k频道 | 国产高清在线观看 | 一级片免费在线 | 日韩欧美精品在线观看 | 999超碰| 亚洲精品系列 | www.97色.com | 日韩精品短视频 | 97av视频在线观看 | 久久精品国产精品亚洲 | 狠狠操天天射 | 中文字幕日韩伦理 | 国产一级电影网 | 亚洲日韩中文字幕在线播放 | 日韩精品久久一区二区三区 | www.久久精品视频 | 久久99热久久99精品 | 欧美俄罗斯性视频 | 香蕉视频啪啪 | 五月天丁香视频 | 丁香国产视频 | 免费av网址在线观看 | 中文字幕一区二区三区四区 | 91成人精品国产刺激国语对白 | 国产免费一区二区三区网站免费 | 欧美精品免费一区二区 | 国产精品男女视频 | 欧美成人一区二区 | 日韩在线中文字幕 | www.69xx| 国产一区二区三区在线免费观看 | 深夜免费福利网站 | 在线观看免费视频 | 97视频在线观看成人 | 国产黄色大全 | 成人免费看视频 | 精品亚洲va在线va天堂资源站 | 亚洲欧美日本国产 | 午夜国产成人 | 国内精品久久久 | 日本中文一级片 | 狠狠的干狠狠的操 | 成人国产精品一区二区 | 九九热精品视频在线观看 | 狠狠操狠狠干天天操 | 欧美日韩免费观看一区=区三区 | 四虎影视4hu4虎成人 | 亚洲视频精品在线 | 天天射天天射天天 | 麻豆一区二区 | 精精国产xxxx视频在线播放 | 女人久久久久 | 91精品国产99久久久久久久 | 久久久久久97三级 | 97免费视频在线播放 | 久久久久久国产精品 | 亚洲精品在线观看中文字幕 | 欧美日韩在线观看一区二区 | 国产黄色理论片 | 亚洲成人在线免费 | 精品美女久久久久久免费 | 在线视频免费观看 | 欧美一二在线 | 日韩a在线观看 | av黄色成人 | 亚洲成av人片在线观看 | 欧美日韩国产一区二区三区在线观看 | 曰本免费av | 国产精品久久久久久久久久久免费看 | 91自拍视频在线观看 | 久久天天躁狠狠躁亚洲综合公司 | 2019中文最近的2019中文在线 | 在线视频1卡二卡三卡 | 欧美专区日韩专区 | 91黄色在线视频 | 色欲综合视频天天天 | 蜜臀91丨九色丨蝌蚪老版 | 婷婷激情欧美 | 国产日产欧美在线观看 | 日韩欧美在线第一页 | 99热这里是精品 | 97超碰免费在线观看 | 一区二区影视 | 又色又爽又黄高潮的免费视频 | 99在线热播精品免费99热 | 国产成人综合在线观看 | 日韩欧美一区二区三区免费观看 | 中文字幕中文中文字幕 | 黄色亚洲片 | 青青河边草免费直播 | 国产破处在线视频 | 91看片淫黄大片在线播放 | 又湿又紧又大又爽a视频国产 | 特级毛片在线观看 | 成年人免费看片 | 在线天堂中文www视软件 | 天天色天天 | 久艹在线观看视频 | www.亚洲激情.com | 亚洲国产精品成人av | 欧美黄色高清 | 美女很黄免费网站 | 中文字幕色综合网 | 亚洲美女免费精品视频在线观看 | 国产又粗又猛又黄 | 日韩网站一区二区 | 久久激情五月丁香伊人 | 久久伊人爱 | 成人影视免费看 | 在线观看久久 | 五月天精品视频 | 国产精品久久久久久久电影 | 日韩精品免费专区 | 正在播放国产一区 | 国产女教师精品久久av | 在线观看视频一区二区三区 | 天天搞天天 | 亚洲涩涩一区 | 91av看片 | 亚洲区精品视频 | 精品人人人 | 色婷婷国产在线 | 日韩黄色免费在线观看 | 精品久久视频 | 久久免费看毛片 | 黄色三级在线观看 | 欧美analxxxx | 亚洲欧洲国产视频 | 激情丁香5月 | av软件在线观看 | 亚洲视频久久 | 精品久久一区二区三区 | 国产成人精品久久亚洲高清不卡 | 五月天伊人 | 伊人久久在线观看 | 六月丁香综合网 | 国产视频在线一区二区 | 日韩理论片在线 | 免费91在线| 五月婷婷在线观看视频 | 亚洲国产片色 | 亚洲综合情 | 丁香婷婷基地 | 青草视频网 | 黄色av网站在线免费观看 | a视频免费在线观看 | 天天摸天天操天天舔 | 天天爱天天干天天爽 | 日韩成人不卡 | 国产剧情一区二区在线观看 | 日韩中文字幕在线不卡 | 久草在在线视频 | 色综合a| 综合网婷婷 | 黄色软件大全网站 | 国产一区二区三区在线 | 亚洲精品高清视频 | 热久久这里只有精品 | 久久日韩精品 | 精品久久电影 | 免费精品在线观看 | 夜夜躁狠狠躁日日躁视频黑人 | 国产精品国产三级在线专区 | 色噜噜在线观看视频 | 五月综合色婷婷 | 亚洲精品国产综合99久久夜夜嗨 | 免费欧美 | 蜜桃av久久久亚洲精品 | 激情视频免费观看 | 日韩免费视频在线观看 | 高清中文字幕av | 日本久久电影网 | 亚洲欧美日韩精品久久久 | 久久精品福利 | 最近中文字幕在线播放 | www.天天操 | 国产视频黄| 青青啪| 日韩精品久久久 | 天海冀一区二区三区 | 久久久精品国产一区二区三区 | 国产小视频福利在线 | 男女日麻批| 亚洲美女免费精品视频在线观看 | 天天操天天爱天天爽 | av中文资源在线 | 精品 激情 | 久久久网站 | 日韩网站免费观看 | 免费三级网| 99久久久久久久 | 特黄特色特刺激视频免费播放 | 色视频网站在线 | 精品亚洲一区二区 | 久久夜av | 天天艹| 国产理伦在线 | 久av电影| 超碰在线观看av | 中文字幕在线一区二区三区 | 欧美一区二区免费在线观看 | 久久精品成人 | 亚洲午夜精品久久久久久久久久久久 | 欧美国产精品久久久久久免费 | 国产一二三区av | 国产精品麻豆视频 | av资源在线观看 | 日韩精品高清不卡 | 五月婷影院 | 久久99精品久久久久蜜臀 | 怡红院av久久久久久久 | 2018亚洲男人天堂 | 久久精品国产亚洲精品2020 | 精品欧美日韩 | 欧美少妇bbwhd | 在线99视频 | 婷婷亚洲五月色综合 | 午夜av在线免费 | 91精品国自产拍天天拍 | 欧美在线视频一区二区 |