精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

CSS TreeShking 原理揭秘: 手寫 PurgeCss

開發 前端
TreeShking 是通過靜態分析的方式找出源碼中不會被使用的代碼進行刪除,達到減小編譯打包產物的代碼體積的目的。

[[439953]]

TreeShking 是通過靜態分析的方式找出源碼中不會被使用的代碼進行刪除,達到減小編譯打包產物的代碼體積的目的。

JS 我們會用 Webpack、Terser 進行 Tree Shking,而 CSS 會用 PurgeCss。

PurgeCss 會分析 html 或其他代碼中 css 選擇器的使用情況,進而刪除沒有被使用的 css。

是否對 PurgeCss 怎么找到無用的 css 的原理比較好奇呢?今天我們就來手寫個簡易版 PurgeCss 來探究下吧。

思路分析

PurgeCss 要指定 css 應用到哪些 html,它會分析 html 中的 css 選擇器,根據分析結果來刪除沒有用到的 css:

  1. const { PurgeCSS } = require('purgecss'
  2. const purgeCSSResult = await new PurgeCSS().purge({ 
  3.   content: ['**/*.html'], 
  4.   css: ['**/*.css'
  5. }) 

我們要做的事情就可以分為兩部分:

  • 提取 html 中的可能的 css 選擇器,包括 id、class、tag 等
  • 分析 css 中的 rule,根據選擇器是否被 html 使用,刪掉沒被用到的部分

從 html 中提取信息的部分,叫做 html 提取器(extractor)。

我們可以基于 posthtml 來實現 html 的提取器,它可以做 html 的 parse、分析、轉換等,api 和 postcss 類似。

css 的部分使用 postcss,通過 ast 可以分析出每一條 rule。

遍歷 css 的 rule,對每個 rule 的選擇器都判斷下是否在從 html 中提取到選擇器中,如果沒有,就代表沒有被使用,就刪掉該選擇器。

如果一個 rule 的所有的選擇器都刪掉了,那么就把這個 rule 刪掉。

這就是 purgecss 的實現思路。我們來寫下代碼。

代碼實現

我們來寫一個 postcss 插件來做這件事情,postcss 插件就是基于 AST 做 css 的分析和轉換的。

  1. const purgePlugin = (options) => { 
  2.    
  3.     return { 
  4.         postcssPlugin: 'postcss-purge'
  5.         Rule (rule) {} 
  6.     } 
  7.  
  8. module.exports = purgePlugin; 

postcss 插件的形式是一個函數,接收插件的配置參數,返回一個對象。對象里聲明 Rule、AtRule、Decl 等的 listener,也就是對不同 AST 的處理函數。

這個 postcss 插件的名字叫做 purge,可以被這樣調用:

  1. const postcss = require('postcss'); 
  2. const purge = require('./src/index'); 
  3. const fs = require('fs'); 
  4. const path = require('path'); 
  5. const css = fs.readFileSync('./example/index.css'); 
  6.  
  7. postcss([purge({ 
  8.     html: path.resolve('./example/index.html'), 
  9. })]).process(css).then(result => { 
  10.     console.log(result.css); 
  11. }); 

通過參數傳入 html 的路徑,插件里可以通過 option.html 拿到。

接下來我們來實現下這個插件。

前面分析過,實現過程整體分為兩步:

  • 通過 posthtml 提取 html 中的 id、class、tag
  • 遍歷 css 的 ast,刪掉沒被 html 使用的部分

我們封裝一個 htmlExtractor 來做提取的事情:

  1. const purgePlugin = (options) => { 
  2.     const extractInfo = { 
  3.         id: [], 
  4.         class: [], 
  5.         tag: [] 
  6.     }; 
  7.  
  8.     htmlExtractor(options && options.html, extractInfo); 
  9.  
  10.     return { 
  11.         postcssPlugin: 'postcss-purge'
  12.         Rule (rule) {} 
  13.     } 
  14.  
  15. module.exports = purgePlugin; 

htmlExtractor 的具體實現就是讀取 html 的內容,對 html 做 parse 生成 AST,遍歷 AST,記錄 id、class、tag:

  1. function htmlExtractor(html, extractInfo) { 
  2.     const content = fs.readFileSync(html, 'utf-8'); 
  3.  
  4.     const extractPlugin = options => tree => {       
  5.         return tree.walk(node => { 
  6.             extractInfo.tag.push(node.tag); 
  7.             if (node.attrs) { 
  8.               extractInfo.id.push(node.attrs.id) 
  9.               extractInfo.class.push(node.attrs.class) 
  10.             } 
  11.             return node 
  12.         }); 
  13.     } 
  14.  
  15.     posthtml([extractPlugin()]).process(content); 
  16.  
  17.     // 過濾掉空值 
  18.     extractInfo.id = extractInfo.id.filter(Boolean); 
  19.     extractInfo.class = extractInfo.class.filter(Boolean); 
  20.     extractInfo.tag = extractInfo.tag.filter(Boolean); 

posthtml 的插件形式和 postcss 類似,我們在 posthtml 插件里遍歷 AST 并記錄了一些信息。

最后,過濾掉 id、class、tag 中的空值,就完成了提取。

我們先不著急做下一步,先來測試下現在的功能。

我們準備這樣一個 html:

  1. <!DOCTYPE html> 
  2. <html lang="en"
  3. <head> 
  4.     <meta charset="UTF-8"
  5.     <meta http-equiv="X-UA-Compatible" content="IE=edge"
  6.     <meta name="viewport" content="width=device-width, initial-scale=1.0"
  7.     <title>Document</title> 
  8. </head> 
  9. <body> 
  10.     <div class="aaa"></div> 
  11.  
  12.     <div id="ccc"></div> 
  13.  
  14.     <span></span> 
  15. </body> 
  16. </html> 

測試下提取的信息:

可以看到,id、class、tag 都正確的從 html 中提取了出來。

接下來,我們繼續做下一步:從 css 的 AST 中刪掉沒被使用的部分。

我們聲明了 Rule 的 listener,可以拿到 rule 的 AST。要分析的是 selector 部分,需要先根據 “,” 做拆分,然后對每一個選擇器做處理。

  1. Rule (rule) {                         
  2.      const newSelector = rule.selector.split(',').map(item => { 
  3.         // 對每個選擇器做轉換 
  4.     }).filter(Boolean).join(','); 
  5.  
  6.     if(newSelector === '') { 
  7.         rule.remove(); 
  8.     } else { 
  9.         rule.selector = newSelector; 
  10.     } 

選擇器可以用 postcss-selector-parser 來做 parse、分析和轉換。

處理以后的選擇器如果都被刪掉了,就說明這個 rule 的樣式就沒用了,就刪掉這個 rule。否則可能只是刪掉了部分選擇器,該樣式還會被用到。

  1. const newSelector = rule.selector.split(',').map(item => { 
  2.     const transformed = selectorParser(transformSelector).processSync(item); 
  3.     return transformed !== item ? '' : item; 
  4. }).filter(Boolean).join(','); 
  5.  
  6. if(newSelector === '') { 
  7.     rule.remove(); 
  8. else { 
  9.     rule.selector = newSelector; 

接下來實現對選擇器的分析和轉換,也就是 transformSelector 函數。

這部分的邏輯就是對每個選擇器判斷下是否在從 html 提取到的選擇器中,如果不在,就刪掉。

  1. const transformSelector = selectors => { 
  2.     selectors.walk(selector => { 
  3.         selector.nodes && selector.nodes.forEach(selectorNode => { 
  4.             let shouldRemove = false
  5.             switch(selectorNode.type) { 
  6.                 case 'tag'
  7.                     if (extractInfo.tag.indexOf(selectorNode.value) == -1) { 
  8.                         shouldRemove = true
  9.                     } 
  10.                     break; 
  11.                 case 'class'
  12.                     if (extractInfo.class.indexOf(selectorNode.value) == -1) { 
  13.                         shouldRemove = true
  14.                     } 
  15.                     break; 
  16.                 case 'id'
  17.                     if (extractInfo.id.indexOf(selectorNode.value) == -1) { 
  18.                         shouldRemove = true
  19.                     } 
  20.                     break; 
  21.             } 
  22.  
  23.             if(shouldRemove) { 
  24.                 selectorNode.remove(); 
  25.             } 
  26.         }); 
  27.     }); 
  28. }; 

我們完成了 html 中選擇器信息的提取,和 css 根據 html 提取的信息做無用 rule 的刪除,插件的功能就已經完成了。

我們來測試下效果:

css:

  1. .aaa, ee , ff{ 
  2.     color: red; 
  3.     font-size: 12px; 
  4. .bbb { 
  5.     color: red; 
  6.     font-size: 12px; 
  7.  
  8. #ccc { 
  9.     color: red; 
  10.     font-size: 12px; 
  11.  
  12. #ddd { 
  13.     color: red; 
  14.     font-size: 12px; 
  15.  
  16. p { 
  17.     color: red; 
  18.     font-size: 12px; 
  19. span { 
  20.     color: red; 
  21.     font-size: 12px; 

html:

  1. <!DOCTYPE html> 
  2. <html lang="en"
  3. <head> 
  4.     <meta charset="UTF-8"
  5.     <meta http-equiv="X-UA-Compatible" content="IE=edge"
  6.     <meta name="viewport" content="width=device-width, initial-scale=1.0"
  7.     <title>Document</title> 
  8. </head> 
  9. <body> 
  10.     <div class="aaa"></div> 
  11.  
  12.     <div id="ccc"></div> 
  13.  
  14.     <span></span> 
  15. </body> 
  16. </html> 

按理說, p、#ddd、.bbb 的選擇器和樣式,ee、ff 的選擇器都會被刪除。

我們使用下該插件:

  1. const postcss = require('postcss'); 
  2. const purge = require('./src/index'); 
  3. const fs = require('fs'); 
  4. const path = require('path'); 
  5. const css = fs.readFileSync('./example/index.css'); 
  6.  
  7. postcss([purge({ 
  8.     html: path.resolve('./example/index.html'), 
  9. })]).process(css).then(result => { 
  10.     console.log(result.css); 
  11. }); 

經測試,功能是對的:

這就是 PurgeCss 的實現原理。我們完成了 css 的 three shaking!

代碼上傳到了 github:https://github.com/QuarkGluonPlasma/postcss-plugin-exercize

當然,我們只是簡易版實現,有的地方做的不完善:

  • 只實現了 html 提取器,而 PurgeCss 還有 jsx、pug、tsx 等提取器(不過思路都是一樣的)
  • 只處理了單文件,沒有處理多文件(再加個循環就行)
  • 只處理了 id、class、tag 選擇器,沒處理屬性選擇器(屬性選擇器的處理稍微復雜一些)

雖然沒有做到很完善,但是 PurgeCss 的實現思路已經通了,不是么~

總結

JS 的 TreeShking 使用 Webpack、Terser,而 CSS 的 TreeShking 使用 PurgeCss。

我們實現了一個簡易版的 PurgeCss 來理清了它的實現原理:

通過 html 提取器提取 html 中的選擇器信息,然后對 CSS 的 AST 做過濾,根據 Rule 的 selector 是否被使用到來刪掉沒用到的 rule,達到 TreeShking 的目的。

實現這個工具的過程中,我們學習了 postcss 和 posthtml 插件的寫法,這兩者形式上很類似,只不過一個針對 css 做分析和轉換,一個針對 html。

Postcss 可以分析和轉換 CSS,比如這里的刪除無用 css 就是一個很好的應用。你還見過別的 postcss 的很棒的應用場景么,不妨一起來討論下吧~

 

責任編輯:姜華 來源: 神光的編程秘籍
相關推薦

2010-08-24 13:34:11

CSSpadding

2022-04-26 08:32:36

CSS前端

2020-11-02 09:35:04

ReactHook

2020-12-03 08:14:45

Axios核心Promise

2010-08-25 13:54:29

CSStop

2021-05-13 23:30:17

JavaScript 原理揭秘

2010-09-14 09:24:40

CSS實例

2010-08-26 10:33:27

CSSborder

2019-11-15 15:12:19

Windows激活KMS

2010-09-15 15:03:52

CSS positio

2010-09-06 09:50:34

id選擇器CSS

2010-08-23 10:43:21

DIVCSS

2010-09-17 15:25:03

JAVAJVM

2010-08-16 14:18:49

DIV+CSS

2023-07-05 10:11:02

2010-09-02 14:17:56

CSS浮動

2010-09-06 11:17:19

CSS相對定位CSS絕對定位

2010-09-07 12:56:49

id選擇器CSS

2010-09-14 15:32:51

CSSdisplay:inl

2010-08-31 15:07:45

CSS居中
點贊
收藏

51CTO技術棧公眾號

狠狠入ady亚洲精品| a成人v在线| 久久这里只有精品视频网| 国产精品久久9| 女性裸体视频网站| 91精品短视频| 在线看日韩精品电影| 中文字幕在线中文字幕日亚韩一区| www.五月婷| 日本中文在线一区| 久久99精品久久久久久琪琪| 国产毛片久久久久久久| 色婷婷成人网| 欧美日韩中文在线| 小说区视频区图片区| 天堂在线观看免费视频| 激情成人综合网| 日韩av日韩在线观看| 欧美成人精品欧美一| 久久综合影院| 精品福利一二区| www.超碰97.com| 88xx成人免费观看视频库 | 久久精品女人的天堂av| 国产又大又黑又粗| 久久精品一区二区国产| 久久6免费高清热精品| 无码人妻aⅴ一区二区三区69岛| 亚洲一区电影| 欧美老肥妇做.爰bbww| 激情五月开心婷婷| 精品精品导航| 17c精品麻豆一区二区免费| 看欧美日韩国产| 韩国av永久免费| 国产毛片精品视频| 国产日韩av高清| 国产美女www| 午夜在线观看免费一区| 国内精品久久久久影院优| 四虎永久免费在线| 国产精品久久观看| 色偷偷av一区二区三区| 欧美三级视频网站| 曰本一区二区三区视频| 日韩精品在线看| 中文文字幕文字幕高清| 美女视频亚洲色图| 亚洲国产成人精品一区二区| 亚洲性图第一页| 亚洲综合影院| 精品区一区二区| 成人啪啪18免费游戏链接| 久久wwww| 日韩欧美视频在线| 中文字幕99页| 久久av国产紧身裤| 日韩精品亚洲视频| 五月婷婷综合在线观看| 国产传媒欧美日韩成人精品大片| 亚洲男人av在线| 亚洲精品国产91| 成人av国产| 日韩中文字幕在线免费观看| 中文字幕第69页| 亚洲一区二区| 久久福利视频导航| 激情小说中文字幕| 日韩一级欧洲| 秋霞av国产精品一区| 亚洲高清视频免费观看| 免费成人美女在线观看| 亚洲一区二区三区乱码aⅴ蜜桃女| 国产精品九九九九| 成人深夜福利app| 久久国产精品-国产精品| 精品亚洲综合| 最新中文字幕一区二区三区| 欧美中文字幕在线观看视频 | 亚洲欧美日韩系列| 国产精品专区在线| 欧洲一级精品| 91精品在线免费| av网页在线观看| 欧美一级精品| 欧美国产乱视频| 国产无套丰满白嫩对白| 狠狠久久亚洲欧美| 国产综合动作在线观看| sese在线视频| 亚洲愉拍自拍另类高清精品| av片中文字幕| 久久wwww| 一区二区三区回区在观看免费视频| 福利视频第一页| 国产午夜久久| 成人性生交大片免费看小说| 性xxxxbbbb| 国产精品传媒入口麻豆| 国产精品宾馆在线精品酒店| 日韩欧乱色一区二区三区在线 | h视频在线免费| 一区二区高清在线| 色哟哟精品视频| 国产精品毛片av| 日韩最新中文字幕电影免费看| 日韩av在线电影| 久久国产精品免费| 美女亚洲精品| 懂色av一区| 欧美日韩激情一区二区| 一二三不卡视频| 国产精品porn| 国产乱肥老妇国产一区二 | 中文字幕免费精品一区| 亚洲一区二区91| 精品一区二区成人精品| 欧美日韩一区二区视频在线观看| 在线播放蜜桃麻豆| 欧美日韩亚洲高清一区二区| 久久午夜夜伦鲁鲁片| 午夜久久美女| 国产裸体写真av一区二区 | 久久精品电影一区二区| 中文字幕一区二区三区四区欧美| 99久久综合精品| a级黄色小视频| 韩国三级成人在线| 中文字幕在线日韩| 日本视频www色| 91看片淫黄大片一级在线观看| 国产精品igao激情视频| 久久综合给合| 久久伊人免费视频| 国产日产亚洲系列最新| 中文字幕在线不卡国产视频| 久久久久久久片| 精品日韩欧美一区| 国产精品福利在线观看| 大乳在线免费观看| 色欧美片视频在线观看| 久久人人爽人人爽人人片| 日韩一级精品| 免费99视频| 免费日韩电影| 影音先锋日韩有码| 中文无码精品一区二区三区| 欧美激情一区二区在线| 成人性做爰aaa片免费看不忠| 综合综合综合综合综合网| 26uuu亚洲伊人春色| 婷婷久久久久久| 欧美午夜影院在线视频| 三上悠亚影音先锋| 天堂久久一区二区三区| 亚洲国产精品123| 久久精品嫩草影院| 超碰97人人做人人爱少妇| 99久久精品国产色欲| 夜夜精品视频一区二区| 日本不卡视频一区| 免费亚洲一区| 日韩三级电影免费观看| 青娱乐极品盛宴一区二区| 久久夜色精品国产欧美乱| www香蕉视频| 婷婷开心激情综合| xxx在线播放| 精品在线一区二区| 超碰超碰超碰超碰超碰| 国产图片一区| 国产suv精品一区二区| 在线中文资源天堂| 欧美成人综合网站| 久久青青草视频| 国产精品午夜电影| 日本中文字幕在线不卡| 亚洲国产精品第一区二区三区| 欧美极品jizzhd欧美| 丁香久久综合| 欧美高清视频在线观看| 天天干天天色天天| 欧美日韩情趣电影| 久草中文在线视频| 国产日韩欧美精品在线| 九色91porny| 亚洲一级在线| 中文精品视频一区二区在线观看| 66精品视频在线观看| 欧美最猛性xxxxx免费| 国产淫片在线观看| 精品网站999www| 国产精品久久久国产盗摄| 五月综合激情婷婷六月色窝| 懂色av粉嫩av浪潮av| 成人高清视频在线观看| 天天爱天天操天天干| 激情久久五月| 亚洲一区二区精品在线| 国产精品任我爽爆在线播放| 国产精品久久久一区| 成人性生交大片免费看网站| 中文字幕免费国产精品| 午夜福利视频一区二区| 91精品啪在线观看国产60岁| 亚洲 欧美 中文字幕| 亚洲观看高清完整版在线观看| 亚洲女人毛茸茸高潮| 91在线视频免费观看| 欧美一区二区三区影院| 美女久久久精品| 18禁免费观看网站| 欧美三区美女| 亚洲欧洲一区二区福利| 亚洲影院天堂中文av色| 不卡日韩av| 成人av在线播放| 国产精品av电影| 日韩理论视频| 高清亚洲成在人网站天堂| 久久综合网导航| 中文字幕亚洲色图| 日韩精品福利| 日韩不卡在线观看| 国产18精品乱码免费看| 日韩午夜av一区| 91激情在线观看| 欧美日韩国产一级片| 亚洲第一网站在线观看| 黄色成人av在线| 国产在线综合网| 一区二区三区**美女毛片| 欧美日韩午夜视频| 国产精品国产三级国产普通话三级| 亚洲午夜久久久久久久久红桃 | 欧美精品乱码久久久久久| 久久久精品毛片| 色老汉av一区二区三区| www亚洲视频| 日韩欧美aⅴ综合网站发布| 久久久久久久久久影院| 午夜精品久久久久久久久久| 日本三级免费看| 午夜亚洲福利老司机| 久热精品在线观看| 亚洲成人资源在线| 国产午夜精品无码| 性做久久久久久久免费看| 久久精品国产亚洲AV无码麻豆| 亚洲一区二区欧美日韩| 久草免费在线观看视频| 黄色一区二区在线| 免费黄色网址在线| 色94色欧美sute亚洲线路二| 午夜视频网站在线观看| 欧美日韩一区三区| 国产乱淫av片免费| 日韩免费看网站| 天堂av手机版| 亚洲区中文字幕| h视频在线播放| 欧美成人精品h版在线观看| 天堂8中文在线| 91精品国产91久久久久久吃药| 免费成人在线电影| 国产精品久久久久久久久免费看| 国产第一亚洲| 国产精品久久久久久久久久久久冷| 美女视频亚洲色图| 日韩中文字幕一区| 亚洲久久久久| 国产中文字幕免费观看| 日本最新不卡在线| 日本少妇一区二区三区| 99久久99久久精品国产片果冻| 波多野结衣av在线观看| 国产精品白丝在线| 久久精品女人毛片国产| 色综合久久久久网| 国产剧情久久久| 亚洲精品久久久久久久久久久 | 国产精品网曝门| 清纯粉嫩极品夜夜嗨av| 欧美日韩综合视频| 国产一区二区三区中文字幕| 欧美xxxx在线观看| av在线播放免费| 欧美激情第三页| www.久久.com| 国产亚洲精品久久飘花| 日本道不卡免费一区| a级免费在线观看| 男女激情视频一区| 日本天堂在线播放| 国产精品白丝在线| youjizz在线视频| 日韩一区二区电影在线| 欧美女v视频| 欧美激情亚洲一区| 99久久久国产精品免费调教网站| 国产高清在线一区| 久久视频在线| 欧美视频第一区| 国产成人在线色| 国产真人做爰视频免费| 亚洲福利视频三区| 国产原创中文av| 国产午夜精品美女视频明星a级| 欧美xxx黑人xxx水蜜桃| 国产剧情久久久久久| 啪啪亚洲精品| 自拍日韩亚洲一区在线| 国产一区二区三区不卡在线观看| 免费人成又黄又爽又色| 欧美午夜激情在线| 人妻视频一区二区三区| 久久国产精品久久久久久| 欧美伊人亚洲伊人色综合动图| 久久99精品国产99久久| 欧美视频一区| 在线观看中文av| 国产精品女同一区二区三区| 黄色片网站在线免费观看| 亚洲激情视频网站| 超碰中文在线| 99re国产视频| 欧美.日韩.国产.一区.二区| 中文字幕 91| 中文字幕欧美激情| 久久久久亚洲视频| 亚洲色图综合久久| 在线中文字幕播放| 蜜桃av噜噜一区二区三区| 一区二区黄色| 亚洲制服丝袜在线播放| 亚洲成在人线免费| 国产香蕉在线观看| 久久久久久久影院| 嗯用力啊快一点好舒服小柔久久| 日韩久久久久久久久久久久| 国产精品一区免费视频| 久久久久久久久久一区二区三区 | 欧美视频亚洲图片| 成人免费一区二区三区视频| 国产精品视频第一页| 草民午夜欧美限制a级福利片| 亚洲精品66| 国产在线拍揄自揄拍无码| 国产高清亚洲一区| 国产一级片久久| 日韩电影中文字幕在线| 在线手机中文字幕| 亚洲mv在线看| 黄页网站大全一区二区| 黄色一级免费视频| 亚洲国产天堂网精品网站| 天堂网在线最新版www中文网| 欧美日韩综合另类| 青青草国产精品97视觉盛宴| 天天做夜夜爱爱爱| 欧美一区日韩一区| 国产91足控脚交在线观看| 精品欧美一区二区久久久伦| 男人的天堂成人在线| 一级肉体全黄裸片| 91精品国产综合久久福利软件| 欧美人与禽猛交乱配| 精品1区2区| 日本va欧美va欧美va精品| 91 在线视频| 亚洲成人黄色在线观看| 波多野结衣亚洲一二三| 亚洲人成77777| 国产成人午夜片在线观看高清观看| 久久久无码一区二区三区| 亚洲精品中文字幕av| 国产黄色精品| 日韩日韩日韩日韩日韩| 中文天堂在线一区| 好吊视频一二三区| 国产精品青青在线观看爽香蕉| 一个色综合网| 国产中文字幕一区二区| 欧美日韩大陆一区二区| 久久青青色综合| 午夜精品福利一区二区| 国产精一品亚洲二区在线视频| 亚洲黄色一区二区| 久久精品美女视频网站| 日韩黄色网络| 日本高清免费在线视频| 色婷婷久久综合| 日本天码aⅴ片在线电影网站| 久久av一区二区| 国产一区视频导航| 69视频免费在线观看| 欧美激情精品久久久| 全球成人免费直播| 亚洲第一黄色网址| 91精品欧美福利在线观看|