<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Facebook 重構(gòu):拋棄 Sass / Less ,迎接原子化 CSS 時(shí)代

          共 7994字,需瀏覽 16分鐘

           ·

          2021-01-27 05:20

          此文由 ssh 翻譯 / 潤(rùn)色,原文見(jiàn)「閱讀原文」

          作者?Sebastien Lorber

          隨著 Facebook 和 Twitter 最近的產(chǎn)品部署,我認(rèn)為一個(gè)新的趨勢(shì)正在緩慢增長(zhǎng):Atomic CSS-in-JS。

          在這篇文章中,我們將看到什么是Atomic CSS(原子 CSS),它如何與 Tailwind CSS 這種實(shí)用工具優(yōu)先的樣式庫(kù)聯(lián)系起來(lái),目前很多大公司在 React 代碼倉(cāng)庫(kù)中使用它們。

          由于我不是這方面的專家,所以我不會(huì)去深入探討它的利弊。我只是希望能幫助你了解它的大致內(nèi)容。

          先拋出一個(gè)令人開(kāi)心的結(jié)論,新的 CSS 編寫(xiě)和構(gòu)建方式讓 Facebook 的主頁(yè)減少了 80% 的 CSS 體積。

          什么是原子 CSS?

          你可能聽(tīng)說(shuō)過(guò)各種 CSS 方法,如 BEM, OOCSS…

          <button?class="button?button--state-danger">Danger?buttonbutton>

          現(xiàn)在,人們真的很喜歡 Tailwind CSS[1] 和它的 實(shí)用工具優(yōu)先(utility-first)[2] 的概念。這與 Functional CSS 和 Tachyon[3] 這個(gè)庫(kù)的理念非常接近。

          <button
          ??class="bg-blue-500?hover:bg-blue-700?text-white?font-bold?py-2?px-4?rounded"
          >

          ??Button
          button>

          用海量的實(shí)用工具類(utility classes)組成的樣式表,讓我們可以在網(wǎng)頁(yè)里大顯身手。

          原子 CSS 就像是實(shí)用工具優(yōu)先(utility-first)CSS 的一個(gè)極端版本: 所有 CSS 類都有一個(gè)唯一的 CSS 規(guī)則。原子 CSS 最初是由 Thierry Koblentz (Yahoo!)在 2013 年挑戰(zhàn) CSS 最佳實(shí)踐[4]時(shí)使用的。

          /*?原子?CSS?*/
          .bw-2x?{
          ??border-width:?2px;
          }
          .bss?{
          ??border-style:?solid;
          }
          .sans?{
          ??font-style:?sans-serif;
          }
          .p-1x?{
          ??padding:?10px;
          }
          /*?不是原子?CSS?因?yàn)檫@個(gè)類包含了兩個(gè)規(guī)則?*/
          .p-1x-sans?{
          ??padding:?10px;
          ??font-style:?sans-serif;
          }

          使用實(shí)用工具/原子 CSS,我們可以把結(jié)構(gòu)層和表示層結(jié)合起來(lái):當(dāng)我們需要改變按鈕顏色時(shí),我們直接修改 HTML,而不是 CSS!

          這種緊密耦合在現(xiàn)代 CSS-in-JS 的 React 代碼庫(kù)中也得到了承認(rèn),但似乎 是 CSS 世界里最先對(duì)傳統(tǒng)的關(guān)注點(diǎn)分離有一些異議。

          CSS 權(quán)重也不是什么問(wèn)題,因?yàn)槲覀兪褂玫氖亲詈?jiǎn)單的類選擇器。

          我們現(xiàn)在通過(guò) html 標(biāo)簽來(lái)添加樣式,發(fā)現(xiàn)了一些有趣的事兒:

          • 我們?cè)黾有鹿δ艿臅r(shí)候,樣式表的增長(zhǎng)減緩了。
          • 我們可以到處移動(dòng) html 標(biāo)簽,并且能確保樣式也同樣生效。
          • 我們可以刪除新特性,并且確保樣式也同時(shí)被刪掉了。

          可以肯定的缺點(diǎn)是,html 有點(diǎn)臃腫。對(duì)于服務(wù)器渲染的 web 應(yīng)用程序來(lái)說(shuō)可能是個(gè)缺點(diǎn),但是類名中的高冗余使得 gzip 可以壓縮得很好。同時(shí)它可以很好地處理之前重復(fù)的 css 規(guī)則。

          一旦你的實(shí)用工具/原子 CSS 準(zhǔn)備好了,它將不會(huì)有太大的變化或增長(zhǎng)。可以更有效地緩存它(你可以將它附加到 vendor.css 中,重新部署的時(shí)候它也不會(huì)失效)。它還具有相當(dāng)好的可移植性,可以在任意其他應(yīng)用程序中使用。

          實(shí)用工具/原子 CSS 的限制

          實(shí)用工具/原子 CSS 看起來(lái)很有趣,但它們也帶來(lái)了一些挑戰(zhàn)。

          人們通常手工編寫(xiě)實(shí)用工具/原子 CSS,精心制定命名約定。但是很難保證這個(gè)約定易于使用、保持一致性,而且不會(huì)隨著時(shí)間的推移而變得臃腫。

          這個(gè) CSS 可以團(tuán)隊(duì)協(xié)作開(kāi)發(fā)并保持一致性嗎?它受巴士因子[5]的影響嗎?

          巴士系數(shù)是軟件開(kāi)發(fā)中關(guān)于軟件專案成員之間訊息與能力集中、未被共享的衡量指標(biāo),也有些人稱作“貨車因子”、“卡車因子”(lottery factor/truck factor)。一個(gè)專案或計(jì)劃至少失去若干關(guān)鍵成員的參與(“被巴士撞了”,指代職業(yè)和生活方式變動(dòng)、婚育、意外傷亡等任意導(dǎo)致缺席的緣由)即導(dǎo)致專案陷入混亂、癱瘓而無(wú)法存續(xù)時(shí),這些成員的數(shù)量即為巴士系數(shù)。

          你還需要預(yù)先開(kāi)發(fā)好一個(gè)不錯(cuò)的實(shí)用工具/原子樣式表,然后才能開(kāi)始開(kāi)發(fā)新功能。

          如果實(shí)用工具/原子 CSS 是由別人制作的,你將不得不首先學(xué)習(xí)類命名約定(即使你知道 CSS 的一切)。這種約定是有主觀性的,很可能你不喜歡它。

          有時(shí),你需要一些額外的 CSS,而實(shí)用工具/原子 CSS 并不提供這些 CSS。沒(méi)有約定好的方法來(lái)提供這些一次性樣式。

          Tailwind 趕來(lái)支援

          Tailwind 使用的方法是非常便捷的,并且解決了上述一些問(wèn)題。

          它通過(guò) Utility-First 的理念來(lái)解決 CSS 的一些缺點(diǎn),通過(guò)抽象出一組類名 -> 原子功能的集合,來(lái)避免你為每個(gè) div 都寫(xiě)一個(gè)專有的 class,然后整個(gè)網(wǎng)站重復(fù)寫(xiě)很多重復(fù)的樣式。

          傳統(tǒng)卡片樣式寫(xiě)法:

          Tailwind 卡片樣式寫(xiě)法:

          它并不是真的為所有網(wǎng)站提供一些唯一的實(shí)用工具 CSS,取而代之的是,它提供了一些公用的命名約定。通過(guò)一個(gè)配置文件[6],你可以為你的網(wǎng)站生成一套專屬的實(shí)用工具 CSS。

          ssh 注:這里原作者沒(méi)有深入介紹,為什么說(shuō)是一套命名約定呢而不是生成一些定死的 CSS 呢?

          舉幾個(gè)例子讓大家感受一些,Tailwind 提供了一套強(qiáng)大的構(gòu)建系統(tǒng),比如默認(rèn)情況下它提供了一些響應(yīng)式的斷點(diǎn)值:

          //?tailwind.config.js
          module.exports?=?{
          ??theme:?{
          ????screens:?{
          ??????'sm':?'640px',
          ??????//?=>?@media?(min-width:?640px)?{?...?}

          ??????'md':?'768px',
          ??????//?=>?@media?(min-width:?768px)?{?...?}

          ??????'lg':?'1024px',
          ??????//?=>?@media?(min-width:?1024px)?{?...?}

          ??????'xl':?'1280px',
          ??????//?=>?@media?(min-width:?1280px)?{?...?}
          ????}
          ??}
          }

          你可以隨時(shí)在配置文件中更改這些斷點(diǎn),比如你所需要的小屏幕 sm 可能指的是更小的 320px,那么你想要在小屏幕時(shí)候采用 flex 布局,還是照常寫(xiě) sm:flex,遵循同樣的約定,只是這個(gè) sm 已經(jīng)被你修改成適合于項(xiàng)目需求的值了。

          在比如說(shuō),Tailwind 里的 spacing 掌管了 margin、padding、width 等各個(gè)屬性里的代表空間占用的值,默認(rèn)是采用了 rem 單位,當(dāng)你在配置里這樣覆寫(xiě)后:

          //?tailwind.config.js
          module.exports?=?{
          ??theme:?{
          ????spacing:?{
          ??????'1':?'8px',
          ??????'2':?'12px',
          ??????'3':?'16px',
          ??????'4':?'24px',
          ??????'5':?'32px',
          ??????'6':?'48px',
          ????}
          ??}
          }

          你再去寫(xiě) h-6(height), m-2(margin), mb-4(margin-bottom),后面數(shù)字的意義就被你改變了。

          也許從桌面端換到移動(dòng)端項(xiàng)目,這個(gè) 6 代表的含義變成了 6rem,但是這套約定卻深深的印在你的腦海里,成為你知識(shí)的一部分了。

          Tailwind 的知識(shí)可以遷移到其他應(yīng)用程序,即使它們使用的類名并不完全相同。這讓我想起了 React 的「一次學(xué)習(xí),到處編寫(xiě)」理念。

          我看到一些用戶反饋說(shuō),Tailwind 提供的類名能覆蓋他們 90% - 95% 的需求。這個(gè)覆蓋面似乎已經(jīng)足夠廣了,并不需要經(jīng)常寫(xiě)一次性的 CSS 了。

          此時(shí),你可能想知道為什么要使用原子 CSS 而不是 Tailwind CSS?強(qiáng)制執(zhí)行原子 CSS 規(guī)則的一個(gè)規(guī)則,一個(gè)類名,有什么好處?你最終會(huì)得到更大的 html 標(biāo)簽和更煩人的命名約定嗎?Tailwind 已經(jīng)有了足夠多的原子類了啊。

          那么,我們是否應(yīng)該放棄原子 CSS 的想法,而僅僅使用 Tailwind CSS?

          Tailwind 是一個(gè)優(yōu)秀的解決方案,但仍然有一些問(wèn)題沒(méi)有解決:

          • 需要學(xué)習(xí)一套主觀的命名約定

          • CSS 規(guī)則插入順序仍然很重要

          • 未使用的規(guī)則可以輕松刪除嗎?

          • 我們?nèi)绾翁幚硎O碌囊淮涡詷邮?

          與 Tailwind 相比,手寫(xiě)原子 CSS 可能不是最方便的。

          和 CSS-in-JS 比較

          CSS-in-JS 和實(shí)用工具/原子 CSS 有密切關(guān)系。這兩種方法都提倡使用標(biāo)簽進(jìn)行樣式化。以某種方式試圖模仿內(nèi)聯(lián)樣式,這讓它們有了很多相似的特性(比如在移動(dòng)某些功能的時(shí)候更有信心)。

          Christopher Chedeau[7] 一直致力于推廣 React 生態(tài)系統(tǒng)中 CSS-in-JS 理念。在很多次演講中,他都解釋了 CSS 的問(wèn)題:

          1. 全局命名空間
          2. 依賴
          3. 無(wú)用代碼消除
          4. 代碼壓縮
          5. 共享常量
          6. 非確定性(Non-Deterministic)解析
          7. 隔離

          實(shí)用工具/原子 CSS 也解決了其中的一些問(wèn)題,但也確實(shí)沒(méi)法解決所有問(wèn)題(特別是樣式的非確定性解析)。

          如果它們有很多相似之處,那我們能否同時(shí)使用它們呢?

          探索原子 CSS-in-JS

          原子 CSS-in-JS 可以被視為是“自動(dòng)化的原子 CSS”:

          • 你不再需要?jiǎng)?chuàng)建一個(gè) class 類名約定

          • 通用樣式和一次性樣式的處理方式是一樣的

          • 能夠提取頁(yè)面所需要的的關(guān)鍵 CSS,并進(jìn)行代碼拆分

          • 有機(jī)會(huì)修復(fù) JS 中 CSS 規(guī)則插入順序的問(wèn)題

          我想強(qiáng)調(diào)兩個(gè)特定的解決方案,它們最近推動(dòng)了兩個(gè)大規(guī)模的原子 CSS-in-JS 的部署使用,來(lái)源于以下兩個(gè)演講。

          • React-Native-Web at Twitter (更多細(xì)節(jié)在Nicolas Gallagher 的演講[8])。

          • Stylex at Facebook (更多細(xì)節(jié)在Frank Yan 的演講[9])。

          也可以看看這些庫(kù):

          • Styletron
          • Fela
          • Style-Sheet
          • cxs
          • otion
          • css-zero
          • ui-box
          • style9
          • stitches
          • catom

          React-Native-Web

          React-Native-Web 是一個(gè)非常有趣的庫(kù),讓瀏覽器也可以渲染 React-Native 原語(yǔ)。不過(guò)我們這里并不討論跨平臺(tái)開(kāi)發(fā)(演講里有更多細(xì)節(jié))。

          作為 web 開(kāi)發(fā)人員,你只需要理解 React-Native-Web 是一個(gè)常規(guī)的 CSS-in-JS 庫(kù),它自帶一些原始的 React 組件。所有你寫(xiě) View 組件的地方,都可以用 div 替換。

          React-Native-Web 的作者是 Nicolas Gallagher,他致力于開(kāi)發(fā) Twitter 移動(dòng)版。他們逐漸把它部署到移動(dòng)設(shè)備上,不太確定具體時(shí)間,大概在 2017/2018 年左右。

          從那以后,很多公司都在用它(美國(guó)職業(yè)足球大聯(lián)盟、Flipkart、Uber、紐約時(shí)報(bào)……),但最重要的一次部署,則是由 Paul Armstrong 領(lǐng)導(dǎo)的團(tuán)隊(duì)在 2019 年推出的新的 Twitter 桌面應(yīng)用。

          Stylex

          Stylex 是一個(gè)新的 CSS-in-JS 庫(kù),F(xiàn)acebook 團(tuán)隊(duì)為了 2020 年的 Facebook 應(yīng)用重構(gòu)而開(kāi)發(fā)它。未來(lái)可能會(huì)開(kāi)源,有可能用另一個(gè)名字。

          值得一提的是,React-Native-Web 的作者 Nicolas Gallagher 被 Facebook 招安。所以里面出現(xiàn)一些熟悉的概念一點(diǎn)也不奇怪。

          我的所有信息都來(lái)自演講 :),還需要等待更多的細(xì)節(jié)。

          可擴(kuò)展性

          不出所料,在 Atomic CSS 的加成下,Twitter 和 Facebook 的 CSS體積都大幅減少了,現(xiàn)在它的增長(zhǎng)遵循的是對(duì)數(shù)曲線。不過(guò),簡(jiǎn)單的應(yīng)用則會(huì)多了一些 初始體積。

          Facebook 分享了具體數(shù)字:

          • 舊的網(wǎng)站僅僅首頁(yè)就用了 413Kb 的 CSS
          • 新的網(wǎng)站整個(gè)站點(diǎn)只用了 74Kb,包括暗黑模式

          源碼和輸出

          這兩個(gè)庫(kù)的 API 看起來(lái)很相似,但也很難說(shuō),因?yàn)槲覀儗?duì) Stylex 了解不多。

          值得強(qiáng)調(diào)的是,React-Native-Web 會(huì)擴(kuò)展 CSS 語(yǔ)法糖,比如 margin: 0,會(huì)被輸出為 4 個(gè)方向的 margin 原子規(guī)則。

          以一個(gè)組件為例,來(lái)看看舊版?zhèn)鹘y(tǒng) CSS 和新版原子 CSS 輸出的區(qū)別。

          <Component1?classNames="class1"?/>?<Component2?classNames="class2"?/>
          .class1?{
          ??background-color:?mediumseagreen;
          ??cursor:?default;
          ??margin-left:?0px;
          }
          .class2?{
          ??background-color:?thistle;
          ??cursor:?default;
          ??jusify-content:?flex-start;
          ??margin-left:?0px;
          }

          可以看出這兩個(gè)樣式中 cursormargin-left 是一模一樣的,但它在輸出中都會(huì)占體積。

          再來(lái)看看原子 CSS 的輸出:

          <Component1?classNames="classA?classC?classD"?/>
          <Component2?classNames="classA?classB?classD?classE"?/>
          class?a?{
          ??cursor:?default;
          }
          class?b?{
          ??background-color:?mediumseagreen;
          }
          class?C?{
          ??background-color:?thistle;
          }
          class?D?{
          ??margin-left:?0px;
          }
          class?E?{
          ??jusify-content:?flex-start;
          }

          可以看出,雖然標(biāo)簽上的類名變多了,但是 CSS 的輸出體積會(huì)隨著功能的增多而減緩增長(zhǎng),因?yàn)槌霈F(xiàn)過(guò)一次的 CSS Rule 就不會(huì)再重復(fù)出現(xiàn)了。

          生產(chǎn)環(huán)境驗(yàn)證

          我們看看 Twitter 上的標(biāo)簽是什么樣子的:

          現(xiàn)在,讓我們來(lái)看看新 Facebook:

          很多人可能會(huì)被嚇到,但是其實(shí)它很好用,而且保持了 可訪問(wèn)性[10]。

          在 Chrome 里檢查樣式可能有點(diǎn)難,但 devtools 里就看得很清楚了:

          CSS 規(guī)則順序

          與手寫(xiě)的工具/原子 CSS 不同,JS 庫(kù)能讓樣式不依賴于 CSS 規(guī)則的插入順序。

          在規(guī)則沖突的情況下,生效的不是標(biāo)簽上 class attribute 中的最后一個(gè)類,而是樣式表中最后插入的規(guī)則。

          以這張圖為例,我們期望的是書(shū)寫(xiě)在后blue 類覆蓋前面的類,但實(shí)際上 CSS 會(huì)以樣式表中的順序來(lái)決定優(yōu)先級(jí),最后我們看到的是紅色的文字。

          在實(shí)際場(chǎng)景中,這些庫(kù)避免在同一個(gè)元素上寫(xiě)入多個(gè)規(guī)則沖突的類。它們會(huì)確保標(biāo)簽上書(shū)寫(xiě)在最后的類名生效。其他的被覆蓋的類名則被規(guī)律掉,甚至壓根不會(huì)出現(xiàn)在 DOM 上。

          const?styles?=?pseudoLib.create({
          ??red:?{color:?"red"},
          ??blue:?{color:?"blue"},
          });

          //?只會(huì)輸出?blue?相關(guān)的?CSS
          <div?style={[styles.red,?styles.blue]}>
          ??Always?blue!
          div>


          //?只會(huì)輸出?red?相關(guān)的?CSS
          <div?style={[styles.blue,?styles.red]}>
          ??Always?red!
          div>

          注意:只有使用最嚴(yán)格的原子 CSS 庫(kù)才能實(shí)現(xiàn)這種可預(yù)測(cè)的行為。

          如果一個(gè)類里有多個(gè) CSS 規(guī)則,并且只有其中的一個(gè) CSS 規(guī)則被覆蓋,那么 CSS-in-JS 庫(kù)沒(méi)辦法進(jìn)行相關(guān)的過(guò)濾,這也是原子 CSS 的優(yōu)勢(shì)之一。

          如果一個(gè)類只有一個(gè)簡(jiǎn)單的 CSS 規(guī)則,如 margin: 0,而覆蓋的是 marginTop: 10。像 margin: 0 這樣的簡(jiǎn)寫(xiě)語(yǔ)法被擴(kuò)展為 4 個(gè)不同的原子類,這個(gè)庫(kù)就能更加輕松的過(guò)濾掉不該出現(xiàn)在 DOM 上的類名。

          仍然喜歡 Tailwind?

          只要你熟悉所有的 Tailwind 命名約定,你就可以很高效的完成 UI 編寫(xiě)。一旦你熟悉了這個(gè)設(shè)定,就很難回到手寫(xiě)每個(gè) CSS 規(guī)則的時(shí)代了,就像你寫(xiě) CSS-in-JS 那樣。

          沒(méi)什么能阻止你在原子 CSS-in-JS 的框架上建立你自己的抽象 CSS 規(guī)則,Styled-system[11] 就能在 CSS-in-JS 庫(kù)里完成一些類似的事情。它基于一些約定創(chuàng)造出一些原子規(guī)則,在 emotion 中使用它試試:

          import?styled?from?'@emotion/styled';
          import?{?typography,?space,?color?}?from?'styled-system';

          const?Box?=?styled('div')(typography,?space,?color);

          等效于:

          ??fontSize={4}
          ??fontWeight="bold"
          ??p={3}
          ??mb={[4,?5]}
          ??color="white"
          ??bg="primary"
          >
          ??Hello
          </Box>

          甚至有可能在 JS 里復(fù)用一些 Tailwind 的命名約定,如果你喜歡的話。

          先看些 Tailwind 的代碼:

          <div?className="absolute?inset-0?p-4?bg-blue-500"?/>

          我們?cè)诠雀枭想S便找一個(gè)方案,比如我剛剛發(fā)現(xiàn) react-native-web-tailwindcss[12]

          import?{?t?}?from?'react-native-tailwindcss';

          <View?style={[t.absolute,?t.inset0,?t.p4,?t.bgBlue500]}?/>;

          就生產(chǎn)力的角度而言,并沒(méi)有太大的不同。甚至可以用 TS 來(lái)避免錯(cuò)別字。

          結(jié)論

          這就是我要說(shuō)的關(guān)于原子 CSS-in-JS 所有內(nèi)容。

          我從來(lái)沒(méi)有在任何大型生產(chǎn)部署中使用過(guò)原子 CSS、原子 CSS-in-JS 或 Tailwind。我可能在某些方面是錯(cuò)的,請(qǐng)隨時(shí)糾正我。

          我覺(jué)得在 React 生態(tài)系統(tǒng)中,原子 CSS-in-JS 是一個(gè)非常值得關(guān)注的趨勢(shì),我希望你能從這篇文章中學(xué)到一些有用的東西。

          感謝閱讀。

          參考資料

          [1]

          Tailwind CSS: https://tailwindcss.com/

          [2]

          實(shí)用工具優(yōu)先(utility-first): https://tailwindcss.com/docs/utility-first

          [3]

          Tachyon: https://github.com/tachyons-css/tachyons

          [4]

          挑戰(zhàn) CSS 最佳實(shí)踐: https://www.smashingmagazine.com/2013/10/challenging-css-best-practices-atomic-approach/

          [5]

          巴士因子: https://zh.wikipedia.org/wiki/%E5%B7%B4%E5%A3%AB%E5%9B%A0%E5%AD%90

          [6]

          配置文件: https://tailwindcss.com/docs/configuration

          [7]

          Christopher Chedeau: https://twitter.com/vjeux

          [8]

          Nicolas Gallagher 的演講: https://www.youtube.com/watch?v=tFFn39lLO-U

          [9]

          Frank Yan 的演講: https://www.youtube.com/watch?v=9JZHodNR184

          [10]

          可訪問(wèn)性: https://github.com/necolas/react-native-web/blob/master/packages/docs/src/guides/accessibility.stories.mdx

          [11]

          Styled-system: https://styled-system.com/

          [12]

          react-native-web-tailwindcss: https://www.npmjs.com/package/react-native-web-tailwindcss

          瀏覽 101
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  人人摸人人看人人草 | 色老板视频在线观看 | 日韩欧美123 | 暧暧在线国产 | 小早川怜子爆乿护士中文 |