Sass sass:meta 與 sass:selector:型別檢查與選取器操作
這兩個模組平常用不到,但寫工具函式與元件庫時很關鍵:sass:meta 讓程式碼檢查自己的值與模組,sass:selector 讓你把選取器當資料操作。
sass:meta
scss
@use "sass:meta";1
type-of:檢查型別
scss
meta.type-of(16px) // number
meta.type-of("bold") // string
meta.type-of(#2965f1) // color
meta.type-of(true) // bool
meta.type-of(null) // null
meta.type-of((a, b)) // list
meta.type-of((a: 1)) // map1
2
3
4
5
6
7
2
3
4
5
6
7
寫給別人用的 混入 一定要做參數檢查:
scss
@mixin square($size) {
@if meta.type-of($size) != number {
@error "square() 的 $size 必須是數字,收到 #{meta.inspect($size)}。";
}
width: $size;
height: $size;
}1
2
3
4
5
6
7
2
3
4
5
6
7
inspect:看清楚一個值
scss
@debug meta.inspect("primary"); // "primary"(含引號)
@debug meta.inspect(primary); // primary
@debug meta.inspect((a: 1, b: (c: 2))); // (a: 1, b: (c: 2))1
2
3
2
3
@debug 印一般值時會去掉引號,很難分辨 "bold" 與 bold。inspect() 會保留原貌,除錯 map 與引號問題時一定要用它。
其他檢查
scss
meta.variable-exists("brand") // 目前範圍有沒有這個變數
meta.mixin-exists("center")
meta.function-exists("rem")
meta.global-variable-exists("brand")1
2
3
4
2
3
4
寫相容多種環境的程式碼時偶爾會用到。
get-function 與 call
把函式當值傳遞:
scss
@use "sass:meta";
@use "sass:math";
@function apply-all($list, $fn) {
$out: ();
@each $x in $list {
$out: list.append($out, meta.call($fn, $x));
}
@return $out;
}
$rounded: apply-all((1.2, 3.7), meta.get-function("round", $module: "math"));1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
load-css:動態輸出模組的 CSS
scss
@use "sass:meta";
$theme: "dark";
@include meta.load-css("themes/#{$theme}");1
2
3
4
5
2
3
4
5
@use | meta.load-css() | |
|---|---|---|
| 路徑 | 必須寫死 | 可以用變數組 |
| 位置 | 檔案最上方 | 任何地方,含條件與迴圈 |
| 拿得到成員嗎 | 拿得到 | 拿不到,只輸出 CSS |
| 可以帶設定嗎 | with | $with 參數 |
它只輸出 CSS
load-css() 不會讓你使用對方的變數或混入。需要成員就得另外 @use。
sass:selector
scss
@use "sass:selector";1
組合選取器
scss
selector.nest(".card", ".title") // .card .title
selector.nest(".a", "&:hover") // .a:hover
selector.append(".btn", "--primary") // .btn--primary
selector.replace(".a .b", ".b", ".c") // .a .c1
2
3
4
2
3
4
unify:兩者同時成立
scss
selector.unify("a", ".link") // a.link
selector.unify(".a", ".b") // .a.b
selector.unify("a", "span") // null,一個元素不可能同時是兩者1
2
3
2
3
判斷包含關係
scss
selector.is-superselector(".a", ".a.b") // true,.a 涵蓋 .a.b1
實際用途
寫元件庫時,混入需要程式化組出選取器:
scss
@use "sass:selector";
@mixin on-parent($parent) {
@at-root #{selector.nest($parent, &)} {
@content;
}
}
.card {
@include on-parent(".theme-dark") {
background: #1a1a1a;
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
css
.theme-dark .card { background: #1a1a1a; }1
常見問題
type-of 和 inspect 差在哪?
type-of() 回傳型別名稱,用來做參數檢查;inspect() 回傳值的原始樣貌字串,包括引號與 map 的完整結構,用來除錯時看清楚一個值到底長什麼樣。
load-css 和 @use 差在哪?
@use 是靜態的,路徑必須寫死且只能放在檔案最上方;load-css() 是函式,可以放在條件判斷或迴圈裡,路徑也能由變數組出來,但它只會輸出對方的 CSS,不會讓你拿到它的成員。
selector.unify 是做什麼的?
它把兩個選取器合併成一個同時符合兩者的選取器,例如把某個類別與 a 元素合併成 a 加上該類別。若兩者不可能同時成立,它會回傳 null。
什麼時候會用到 sass:selector?
寫元件庫、需要程式化組合選取器的時候,例如根據傳入的父選取器組出巢狀路徑。一般專案很少用到,多數情況用父選取器與插值就夠了。