在 Houdini 实现的过程中(什么是 Houdini?),Chrome 已经在 66 中已经实现了一部分 CSS 样式的 Typed Object Modal 支持(支持的列表可以参考这里)。
实现之后,在 JavaScript 中就可以通过 window.CSS
对象上的各类属性 API,生成指定类型的 CSS 属性值。看一个简单的例子:
在以前的实现中,往往需要这么写代码:
const fontSize = +(element.style.fontSize.replace('px', ''));
element.style.fontSize = `${fontSize * 2}px`;
element.style.opacity = 0.1;
这样写,会存在几个问题:
- 读取和设置带单位数值的时候,需要在字符串和数字之间进行转化;
- CSS 的属性名称是用
-
连接的,但是在 CSSStyleDeclaration
中却需要写成小驼峰的形式(font-size
变成 fontSize
);
- 如果设置违法的值,代码会默默失败,没有任何错误提示;
element.style.opacity = 0.1;
element.style.opacity = '?';
console.log(element.style.opacity);
- 即使设置的属性值是数字,但是实际拿到的时候,值又变成了字符串
如,上例中的 element.style.opacity
,虽然设置的值是 1
,但如果运行 typeof element.style.opacity
结果却是 string
element.style.opacity = 0.1;
console.log(typeof element.style.opacity);
如果试图直接进行运算,则可能得不到预料中的结果。比如,下面的输出依然是 0.1
而不是 0.6
,因为 element.style.opacity += 0.5
的结果是 0.10.5
(字符串拼接),作为一个非法值,直接被浏览器抛弃了(见第三点)
element.style.opacity = 0.1;
element.style.opacity += 0.5;
console.log(element.style.opacity);
有了 CSS Typed Object Model 之后,代码可以改写成这样:
const fontSize = element.attributeStyleMap.get('font-size').value;
element.attributeStyleMap.set('font-size', CSS.px(fontSize * 2));
element.attributeStyleMap.set('opacity', 1);
不难看出,这样的写法,基本解决了上面提到的几个问题:
- 读取和设置带单位数值的时候,不再需要手动进行字符串和数值的转化。
CSS.px
这个函数可以将数值转化成一个带单位的对象,用于给 attributeStyleMap
赋值。另外,由于这个值 toString
之后就是类似 16px
的字符串,因此也可以直接给 element.style.fontSize
进行赋值。同时,从 attributeStyleMap
中拿到的数据,也是带单位的对象,对象中的 value
就是数值,unit
是字符串,表示单位,不再需要手动解析;
attributeStyleMap
的属性名称和 CSS 的属性名称是一致的,不需要像以前一样在 JavaScript 中手动改成小驼峰的写法;
- 如果设置了违法的值,代码会报错:
try {
element.attributeStyleMap.set('opacity', '?');
} catch (e) {
console.log(e);
}
以上代码会输出报错:TypeError: Failed to execute 'set' on 'StylePropertyMap': Invalid type for property
。
- 应该是数值的结果,拿到的时候也是数值,而不是字符串(因此数值计算也不会出错):
element.attributeStyleMap.set('opacity', 1);
console.log(typeof element.attributeStyleMap.get('opacity').value);
当然,这里如果这么些,结果依然是数字:
element.attributeStyleMap.set('opacity', '1');
console.log(typeof element.attributeStyleMap.get('opacity').value);
另外,使用 CSS Typed OM 还有一些其他额外的好处,比如,浏览器不需要序列化和反序列化结果,因此性能更好(一个简单的性能检测可以查看这里,大概有 30% 左右的提升)。
更多更详细关于 CSS Typed OM 的介绍,可以参考 Google 的这篇 Blog。
P.S. 目前,其他的浏览器支持情况依然不理想,可以参考 Is Houdini ready yet? 网站上最新的支持情况了解详情。就实际情况来看,可以在 Electron 3 (基于 Chrome 66,见这里)或以上版本使用,但暂时不建议在 Web 项目中引入。