來源: css-tricks.com
作者:Marko Ilic
編譯:大道至簡
JavaScript 與 CSS 已經(jīng)相生相伴 20 年了,但是要在它們之間共享數(shù)據(jù)卻非常困難踊东。當(dāng)然蒲稳,這方面肯定有過一些嘗試胖翰,不過我想到的是簡單而又直觀的做法:不需要做代碼結(jié)構(gòu)上的改動(dòng)荧缘,而是利用 CSS 自定義屬性帕膜,甚至是 Sass 變量枣氧。
CSS 自定義屬性
CSS 自定義屬性現(xiàn)在也不算什么稀罕物了。自從瀏覽器開始支持以來垮刹,就能通過 JavaScript 操作自定義屬性值达吞。
具體來說,用 JavaScript 操作自定義屬性有以下幾種方式荒典。第一個(gè)是 setProperty
:
document.documentElement.style.setProperty("--padding", 124 + "px"); // 124px
還可以用getComputedStyle
酪劫,原因很簡單:自定義屬性也是樣式的一部分,因此也屬于計(jì)算樣式的一部分寺董。
getComputedStyle(document.documentElement).getPropertyValue('--padding') // 124px
同樣覆糟,還可以用getPropertyValue
。它可以獲取 HTML 元素的行內(nèi)樣式值:
document.documentElement.style.getPropertyValue("--padding'"); // 124px
注意遮咖,自定義屬性是有作用域的滩字。也就是說必須從指定元素獲取計(jì)算后的樣式。前面由于我們是 在
:root
里定義的變量御吞,因此要從這個(gè) HTML 元素上獲取踢械。
Sass 變量
Sass 是預(yù)處理語言,最終要轉(zhuǎn)換成 CSS 才能應(yīng)用到網(wǎng)站頁面上魄藕。所以,像 CSS 自定義屬性那樣用 JavaScript 直接操作是行不通的撵术。
為此背率,我們需要修改下構(gòu)建流程。這一步可能不是必須的,因?yàn)榇蟛糠謽?gòu)建流程配置都已經(jīng)包含了這些 loader寝姿。如果你的項(xiàng)目配置里沒有的話交排,就需要加上如下的 webpack 配置:
module.exports = {
// ...
module: {
rules: [
{
test: /\.scss$/,
use: ["style-loader", "css-loader", "sass-loader"]
},
// ...
]
}
};
為了讓 Sass(準(zhǔn)確地說這里是 SCSS)變量在 JavaScript 里可用,我們需要將其導(dǎo)出(export
):
// variables.scss
$primary-color: #fe4e5e;
$background-color: #fefefe;
$padding: 124px;
:export {
primaryColor: $primary-color;
backgroundColor: $background-color;
padding: $padding;
}
這里的 :export
部分是黑魔法所在饵筑,webpack 就是用它來導(dǎo)入變量的埃篓。這種方法的妙處是可以用 camelCase 格式重命名變量,并可以選擇要導(dǎo)出的變量根资。
然后把 Sass 文件(variables.scss
)導(dǎo)入到 JavaScript架专,這樣就可以訪問文件里的變量了。神不神奇玄帕,意不意外部脚?
import variables from './variables.scss';
/*
{
primaryColor: "#fe4e5e"
backgroundColor: "#fefefe"
padding: "124px"
}
*/
document.getElementById("app").style.padding = variables.padding;
值得一提的是,:export
語法有一些限制:
- 可以在文件里的任何位置裤纹,但必須位于頂層
- 如果文件里有多個(gè)委刘,這些鍵和值會(huì)合并在一起導(dǎo)出
- 如果某個(gè)
exportedKey
有重復(fù),后面的會(huì)覆蓋前面的 -
exportedValue
可以包含 CSS 聲明中的任意有效字符(包括空格) -
exportedValue
不需要加引號鹰椒,因?yàn)樗呀?jīng)被處理成字符串了锡移。
在 JavaScript 中訪問 Sass 變量的應(yīng)用場景有哪些呢?其中一個(gè)是共享媒體查詢中的斷點(diǎn)配置漆际。比如這里的breakpoints.scs
文件淆珊,可以用于 JavaScript 中的 matchMedia()
方法,來保持?jǐn)帱c(diǎn)設(shè)置的一致性灿椅。
//定義斷點(diǎn)的 Sass 變量
$breakpoints: (
mobile: 375px,
tablet: 768px,
// etc.
);
// 用于媒體查詢的 Sass variables
$media: (
mobile: '(max-width: #{map-get($breakpoints, mobile)})',
tablet: '(max-width: #{map-get($breakpoints, tablet)})',
// etc.
);
// 導(dǎo)出部分
:export {
breakpointMobile: unquote(map-get($media, mobile));
breakpointTablet: unquote(map-get($media, tablet));
// etc.
}
動(dòng)畫是另一個(gè)應(yīng)用場景套蒂。動(dòng)畫的持續(xù)時(shí)間通常保存在 CSS 中,但是更復(fù)雜的動(dòng)畫可能需要 JavaScript 來實(shí)現(xiàn)茫蛹。
// animation.scss
$global-animation-duration: 300ms;
$global-animation-easing: ease-in-out;
:export {
animationDuration: strip-unit($global-animation-duration);
animationEasing: $global-animation-easing;
}
注意操刀,這里在導(dǎo)出變量時(shí)用了strip-unit
函數(shù),目的是為了去掉單位婴洼,方便在 JavaScript 里轉(zhuǎn)換數(shù)字骨坑。
// main.js
document.getElementById('image').animate([
{ transform: 'scale(1)', opacity: 1, offset: 0 },
{ transform: 'scale(.6)', opacity: .6, offset: 1 }
], {
duration: Number(variables.animationDuration),
easing: variables.animationEasing,
});
還有一個(gè)是 echarts 圖系列的顏色列表。比如餅圖的各個(gè)部分用的顏色序列柬采,可能也要在圖之外使用欢唾。為了便于維護(hù),最好是定義在同一個(gè)地方粉捻。
總之礁遣,這樣就可以輕松地實(shí)現(xiàn) CSS、Sass 和 JavaScript 之間交換數(shù)據(jù)肩刃,確實(shí)挺不錯(cuò)祟霍。變量共享讓代碼變得更簡單杏头,實(shí)現(xiàn)了 DRY(Dont' Repeat Yourself)。