首页 > 其他分享 >了解 StyleX 么?

了解 StyleX 么?

时间:2024-02-06 11:01:32浏览次数:37  
标签:StyleX 样式 stylex JS color 了解 CSS red

近日,Meta开源了一款CSS-in-JS库 —— StyleX。看命名方式,Style - X是不是有点像JS - X,他们有关系么?当然有。

JSX是一种用JS描述HTML的语法规范,广泛应用于前端框架中(比如ReactSolidJS...),由Meta公司提出。

同样的,按照Meta的设想,StyleX是一种用JS描述CSS的语法规范。

早在React Conf 2019Meta工程师Frank就介绍了这种Meta内部使用的CSS-in-JS库

为什么需要CSS解决方案

市面上有非常多CSS解决方案,比如:

  • BEM命名规范
  • CSS Module规范
  • 原子CSS(比如TailwindCSS
  • CSS-in-JS(比如emotion

为什么需要这些方案?原生CSS哪里不好?在这里,我们举个小例子(例子来源于React Conf 2019)。考虑如下代码:

CSS文件如下:

.blue {color: blue;}
.red {color: red;}

HTML文件如下:

<p class="red blue">我是什么颜色?</p>

请问p标签是什么颜色的?

class来看,bluered后面,p应该是蓝色的么?

实际上,样式取决于他们在样式表中定义的顺序,.red的定义在.blue后面,所以p应该是红色的。

是不是已经有点晕了?再增加点难度。如果.red.blue分别在两个文件中定义呢?

# css文件1
.blue {color: blue;}
# css文件2
.red {color: red;}

p的样式就取决于最终打包代码中样式文件的加载顺序。

上面只是原生CSS选择器优先级相关的一个缺陷(除此外还有其他缺陷,比如作用域缺失...)。随着项目体积增大、项目维护时间变长、项目维护人员更迭,这些缺陷会被逐渐放大。

正是由于这些原因,才出现了各种CSS解决方案

StyleX的基本使用

StyleXAPI很少,掌握下面两个就能上手使用:

  • stylex.create,创建样式
  • stylex.props,定义props

比如:

import * as stylex from 'stylex';

// 创建样式
const styles = stylex.create({
  red: {color: 'red'},
});

// 定义props
const redStyleProps = stylex.props(styles.red);

使用时:

<div {...redStyleProps}>文字颜色是红色</div>

stylex是如何解决上面提到的red blue优先级问题呢?其实很简单,考虑如下代码:

import * as stylex from 'stylex';

// 创建样式
const styles = stylex.create({
  red: {color: 'red'},
  blue: {color: 'blue'}
});

// 使用
<p {...styles.props(styles.red, styles.blue)}></p>

样式的优先级只需要考虑styles.props中的定义顺序(bluered后面,所以颜色为blue),不需要考虑样式表的存在。

有些同学会说,看起来和常见的CSS-in-JS没啥区别啊。那stylex相比于他们的优势是啥呢?

相比其他CSS-in-JS的优势

首先要明确,stylex虽然以CSS-in-JS的形式存在,但本质上他是一种用JS描述CSS的规范。文章开头也提到,他的定位类似JSX

既然是规范,那他就不是对CSS的简单封装、增强,而是一套自定义的样式编写规范,只不过这套规范最终会被编译为CSS

作为对比,LessSass这样的CSS预处理器就是对CSS语法的封装、增强

那么,stylex都有哪些规范呢?

比如,stylex鼓励将样式与组件写在同一个文件,类似VueSFC(单文件组件)。这么做除了让组件的样式与逻辑更方便维护,也减少了stylex编译的实现难度。

再比如,CSS中各种选择器的复杂组合增强了选择器的灵活性。但同时也增强了不确定性。举个例子,考虑如下三个选择器:

  • .className > *
  • .className ~ *
  • .className:hover > div:first-child

这些对.className应用的选择器将影响.className的某些后代。当这样的选择器多了后,很可能会在开发者不知道的情况下改变某些后代元素的样式。

遇到这种情况我们一般会怎么处理呢?正确的选择当然是找到上述影响后代的选择器,再修改他。

但大家工作都这么忙,遇到这种问题,多半就是用新的选择器覆写样式,必要的时候还会加!important后缀。久而久之,这代码就没法维护了。

为了规避这种情况,在stylex中,除了可继承样式(指当父元素应用后,子孙元素默认会继承的样式,比如color)外,不支持这些可以改变子孙后代样式的选择器

那我该如何让子孙组件获得父组件同样的样式呢?通过props透传啊~

也就是说,stylex禁用了CSS中可能造成混淆的选择器,用JS的灵活性弥补这部分功能的缺失。

有些同学可能会说:这些功能,其他CSS-in-JS库也能做啊。

这就要谈到CSS-in-JS库最大的劣势 —— 为了计算出最终样式,在运行时会造成额外的样式计算开销。

stylex通过编译来减少运行时的开销。比如对于上面提到过的stylex的代码:

import * as stylex from 'stylex';

// 创建样式
const styles = stylex.create({
  red: {color: 'red'},
});

// 定义props
const redStyleProps = stylex.props(styles.red);

编译后的产物包括如下两部分:

JS的编译产物:

import * as stylex from 'stylex';
const redStyleProps = {className: 'x1e2nbdu'};

CSS的编译产物:

.x1e2nbdu {
  color: red;
}

所以,运行时实际运行的代码始终为:

<div {...{className: 'x1e2nbdu'}}>...</div>

对于再复杂的样式,stylex都会通过编译生成可复用的原子类名

即使是跨文件使用样式,比如我们在另一个文件也定义个使用color: 'red'样式的stylex属性foo

import * as stylex from '@stylexjs/stylex';

const styles = stylex.create({
  foo: {
    color: 'red',
  },
  bar: {
    backgroundColor: 'blue',
  },
});

会得到如下编译结果,其中x1e2nbdu是一个原子类名,他是上一个文件中styles.red的编译产物:

import * as stylex from '@stylexjs/stylex';

const styles = {
  foo: {
    color: 'x1e2nbdu',
    $$css: true,
  },
  bar: {
    backgroundColor: 'x1t391ir',
    $$css: true,
  },
};

随着项目体积增大,样式表的体积也能控制在合理的范围内。这种对原子类名的控制粒度是其他CSS-in-JS库办不到的。

相比于原子CSS的优势

stylex相比TailwindCSS这样的原子CSS有什么优势呢?

这就要谈到原子CSS的一个特点 —— 使用约定好的字符串实现样式。比如,使用TailwindCSS定义图片的样式:

<img class="w-24 h-24 rounded-full mx-auto" src="/sarah-dayan.jpg" alt="" width="384" height="512">

效果如下:

了解 StyleX 么?_选择器

由于样式都是由不同的原子类名字符串组合而成,TS没法分析,这就没法实现样式的类型安全

什么叫样式的类型安全?通俗的讲,如果我实现一个组件,组件通过style props定义样式,我只希望使用者能够改变colorfontSize两个样式属性,不能修改其他属性。如果能实现这一点,就是样式的类型安全

样式的类型安全有什么意义呢?举个例子:设想开发基础组件库的团队使用stylex。那么当业务团队使用该组件库时,就只能自定义组件的一些样式(由组件库团队约束)。

当基础组件库升级时,组件库团队能很好对组件样式向下兼容(因为知道只有哪些样式允许被修改)。

stylex中,由于stylex.create的产物本质是对象,所以我们可以为每个产物定义类型声明。比如在如下代码中,我们限制了组件style props只能接受如下stylex样式

import type {StyleXStyles} from '@stylexjs/stylex';

type Props = {
  // ...
  style?: StyleXStyles<{
    color?: string;
    backgroundColor?: string;
    borderColor?: string;
    borderTopColor?: string;
    borderEndColor?: string;
    borderBottomColor?: string;
    borderStartColor?: string;
  }>;
};

总结

我猜想,当更多人知道stylex后,他会收到比当初TailwindCSS火时更多的两级分化的评价。

毕竟,stylex的设计初衷是为了解决Meta内部复杂应用的样式管理。如果:

  • 你项目没有达到Meta这样的体量
  • 你项目没有多年的迭代周期
  • 你项目前前后后没有多个工程师经手

那大概率是不能接受stylex设计理念中的这些约束。


标签:StyleX,样式,stylex,JS,color,了解,CSS,red
From: https://blog.51cto.com/u_11365839/9617887

相关文章

  • 2月摸鱼计划03 从并发编程本质了解Go高性能的本质
    1.0从并发编程本质了解Go高性能的本质1.1Goroutine协程可以理解为轻量级线程;Go更适合高并发场景原因之一:Go语言一次可以创建上万协成;“快速”:开多个协成打印。gofunc():在函数前加go代表创建协程;time.Sleep():协程阻塞,使主协程在子协程结束前阻塞不退出;乱序输出说......
  • 为什么要进行FTP替代?专业的FTP替代传输方案了解一下!
    FTP(FileTransferProtocol,文件传输协议)的历史可以追溯到20世纪70年代,这是一个由美国国防部资助的早期计算机网络,后来发展成为互联网的前身。随着时间的推移,FTP经历了多次迭代和改进,以适应不断变化的网络环境和用户需求。FTP协议允许用户以文件操作的方式(如文件的增、删、改、查、......
  • Zookeeper快速了解
    初识ZookeeperZookeeper是ApacheHadoop项目下的一个子项目,是一个树形目录服务。Zookeeper翻译过来就是动物园管理员,他是用来管Hadoop(大象)、Hive(蜜蜂)、Pig(小猪)的管理员。简称zkZookeeper是一个分布式的、开源的分布式应用程序的协调服务。Zookeeper提供的......
  • 11 - 初步了解Python
    初步了解Python参考资料:菜鸟教程:Python3基础语法PEP8:StyleGuideforPythonCodePythonDocs:SourceCodeEncoding菜鸟教程:Python3命令行参数PythonDocs:ExecutablePythonScripts知乎:#!/usr/bin/envpython有什么用?编程规范:PEP8在没有额外编程规范的前提下,建议翻阅并......
  • 注册表监控工具可以近乎实时地监控注册表更改情况,让您不会错过任何问题。通过可自定义
    注册表监控工具可以近乎实时地监控注册表更改情况,让您不会错过任何问题。通过可自定义通知系统,您可以更轻松地及时了解用户操作或软件安装所引起的注册表更改。会在更改发生的当下显示更改(并让您进行检查和分析),而不是按特定间隔汇总活动数据,它还提供逐行精细数据,以更准确地查看注......
  • 【面试】你了解过 TOGAF 标准吗?请谈谈你的认知。
    先说结论,本人对TOGAF标准的认知只是略懂皮毛。个人认为TOGAF在中小型企业中要有一定的使用范围。没有必要做到全面覆盖,保持企业扁平和敏捷才是最重要的。<br>TOGAF,全称是“TheOpenGroupArchitectureFramework”(开放组织体系结构框架),是一个由开放组织(TheOpenGroup)......
  • 二进制详解 —— 从十进制入手,学习了解二进制
    目录二进制与整数之间的转换二进制转化为十进制十进制转化为二进制与浮点数之间的转换二进制小数➡️十进制小数十进制小数➡️二进制小数二进制我认为想要降低对新事物的恐惧,快速学会新知识,最重要的是学会类比旧事物、推理和举一反三。二进制也不例外,所以再学习二进制之前,我们先......
  • 《深入了解计算机系统》观后感
    第六章的链接,更是对程序文件进行了详细的解释,让我等学习编程的人懂了很多程序运行、编写时的知识,以前就不明白,也没有想过的东西,让我突然明白了,真是很开心!后面还有并发和网络编程等方面的知识,对于一些常犯的错误也进行了简单的概括,并且介绍了一些方法。尤其是这些方法,真是很重要,......
  • 数据库MySQL8.0.29安装与备份||了解和掌握MySQL的安装和简单使用和备份数据
    内容:了解和掌握MySQL的安装和简单使用:(1) 了解安装MySQL的软硬件环境和安装方法;(2) 熟悉MySQL的相关基本使用;(3) 熟悉MySQL的构成和相关工具;(4) 通过MySQL的使用来理解数据库系统的基本概念。要求:1. 在微机上安装MySQL数据库系统,为后续实验搭建实验环境,提供前期准备;2. 完成实......
  • 深入了解java对象分配
    1.对象的创建在语言层面上,创建对象通常仅仅是一个new关键字而已,而在虚拟机中,对象(对象限于普通Java对象,不包括数组和Class对象等)的创建又是怎样一个过程呢?当Java虚拟机遇到一条字节码new指令时,①首先将去检査这个指令的参数是否能在常量池中定位到一个类的符号引用,并且......