会JSX没什么了不起,你了解过 StyleX 么?

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

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

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

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

Meta内部使用,到大会对外宣传,这期间肯定已经经历大量内部项目的洗礼。而从做完宣传到最终开源,又经历了快5年时间。

那么,这款Meta出品、打磨这么长时间的CSS-in-JS库,到底有什么特点呢?

本文让我们来聊聊。

免费领取卡颂原创React教程(原价359)、加入人类高质量前端群

为什么需要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">

效果如下:

由于样式都是由不同的原子类名字符串组合而成,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,你怎么看?

技术前沿拓展

前端开发,你的认知不能仅局限于技术内,需要发散思维了解技术圈的前沿知识。细心的人会发现,开发内部工具的过程中,大量的页面、场景、组件等在不断重复,这种重复造轮子的工作,浪费工程师的大量时间。

介绍一款程序员都应该知道的软件 JNPF 快速开发平台,很多人都尝试用过它,它是功能的集大成者,任何信息化系统都可以基于它开发出来。

这是一个基于 Java Boot/.Net Core 构建的简单、跨平台快速开发框架。前后端封装了上千个常用类,方便扩展;集成了代码生成器,支持前后端业务代码生成,实现快速开发,提升工作效率;框架集成了表单、报表、图表、大屏等各种常用的 Demo 方便直接使用;后端框架支持 Vue2、Vue3。如果你有闲暇时间,可以做个知识拓展。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/218255.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

公众号怎么提高2个限制

一般可以申请多少个公众号&#xff1f;许多用户在申请公众号时可能会遇到“公众号显示主体已达上限”的问题。这是因为在2018年11月16日对公众号申请数量进行了调整&#xff0c;具体调整如下&#xff1a;1、个人主体申请公众号数量上限从2个调整为1个。2、企业主体申请公众号数…

【LeetCode:2697. 字典序最小回文串 | 双指针 + 贪心】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

静态HTTP应用:理解其工作原理与优势

随着互联网的普及和发展&#xff0c;Web应用已经成为人们日常生活和工作中不可或缺的一部分。而静态HTTP应用作为Web应用的一种重要形式&#xff0c;也越来越受到开发者的青睐。本文将带你了解静态HTTP应用的工作原理和优势&#xff0c;让你更好地理解这种应用形式。 一、静态…

binlog+mysqldump恢复数据(误删数据库或者表)

表删除恢复 1、准备数据 首先准备数据库环境&#xff0c;测试数据库为speech1&#xff0c;如下&#xff1a; 为test数据表添加3条记录&#xff0c;如下&#xff1a;三行为新加的记录&#xff0c;添加后将test表删除。 2、恢复数据 查看binlog日志状态 SHOW MASTER STATUS…

多线程案例-定时器(附完整代码)

定时器是什么 定时器是软件开发中的一个重要组件.类似于一个"闹钟".达到一个设定的时间之后,就执行某个指定好的代码. 定时器是一种实际开发中非常常用的组件. 比如网络通信种,如果对方500ms内没有返回数据,则断开尝试重连. 比如一个Map,希望里面的某个key在3s之后过…

uniapp+vite+ts+express踩坑总结

1 关于引入express包报 import express from "express"; ^^^^^^ SyntaxError: Cannot use import statement outside a module的问题。 解决方案&#xff1a; 在package.json中添加type&#xff1a;“module”选项 2 Response is a type and must be imported …

c语言 词法分析器 《编译原理》课程设计

设计、编制并调试一个词法分析程序&#xff0c;加深对词法分析原理的理解。 针对表达各类词语的一组正规表达式&#xff0c;设计一个确定化的最简的有限自动机&#xff0c;对输入的符号串进行单词划分及词类识别。 要求词法分析器的输入是字符串&#xff0c;输出是源程序中各…

安装odoo17 Windows版时,PostgreSQL Database无法被勾选

安装odoo17 Windows版时&#xff0c;PostgreSQL Database无法被勾选。 出现的原因是&#xff0c;曾经安装过PostgreSQL Database&#xff1b;虽然可能已被卸载&#xff0c;但注册表内还有残余信息&#xff0c;导致odoo认为PostgreSQL Database仍存在于系统之中。 解决方案 删…

三勾商城新功能-电子面单发货

商家快递发货时可以选择在线下单,在线获取和打印电子面单。免去手写面单信息以及避免填写运单号填错,系统会自动填写对应发货商品的运单信息 快递100电子面单1、进入快递100&#xff0c;点击登录 2、登录成功后&#xff0c;点击“电子面单与云打印” 3、进入电子面单与云打印后…

AI全栈大模型工程师(二十七)如何部署自己 fine-tune 的模型

服务器价格计算器 火山引擎提供的这个价格计算器很方便&#xff0c;做个大概的云服务器 GPU 选型价格参考。其它服务厂商价格相差不是很多。 https://www.volcengine.com/pricing?productECS&tab2 高稳定和高可用地部署模型 序号模块名称描述1负载均衡将流入的请求分发到多…

基于Java SSM框架实现沙县小吃门店连锁点餐订餐系统项目【项目源码+论文说明】

基于java的SSM框架实现县小吃门店连锁点餐订餐系统演示 摘要 随着社会的发展&#xff0c;社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 沙县小吃点餐系统&#xff0c;主要的模块包括实现管理员&#xff1b;个人中心、用户管…

Linux 安装图形界面 “startx”

———————————————— 报错&#xff0c;如下&#xff1a; bash :startx command not found ———————————————— 解决方法&#xff1a; 1.先安装 — X Windows System&#xff0c;输入以下命令&#xff1a; yum groupinstall “X Window System”…

盘点2023年低代码平台TOP10

盘点2023年低代码平台TOP10 1 什么是低代码平台2 十大低代码平台2.1 IVX2.2 简道云2.3 伙伴云2.4 企名片one2.5 明道云2.6 轻流2.7 速融云2.8 轻舟——网易2.9 钉钉宜搭2.10 腾讯云-微搭 1 什么是低代码平台 低代码平台是一种开发软件的方法&#xff0c;它可以通过简单的拖放和…

【Anaconda】Ubuntu anaconda使用(新建环境、最小化安装Tensorflow)

Ubuntu anaconda使用&#xff08;新建环境、最小化安装Tensorflow&#xff09; 清华源地址&#xff1a; https://pypi.tuna.tsinghua.edu.cn/simplepip安装使用的时候&#xff0c; pip install xxx(库名) -i https://pypi.tuna.tsinghua.edu.cn/simple请先安装好anaconda&am…

Python 递归及目录遍历

递归调用&#xff1a;一个函数&#xff0c;调用了自身&#xff0c;称为递归调用 递归函数&#xff1a;一个会调用自身的函数 凡是循环能做的事&#xff0c;递归都能做。 目录 递归示例 普通方法实现 递归方式实现 计算分析&#xff1a; 递归遍历目录 引入os 遍历目录 执…

基于SSM的小儿肺炎知识管理系统设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;Vue 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是 目录…

MobileNet网络

介绍 MobileNet 网络专注于移动端或者嵌入式设备中的轻量级CNN网络&#xff0c;相比传统卷积神经网络&#xff0c;在准确率小幅降低的前提下大大减少模型参数与运算量&#xff08;相比VGG16准确率减少了0.9%&#xff0c;但模型参数只有VGG的1/32&#xff09; 网络中的亮点&am…

利用知识付费小程序,我有才打造高效的知识传播渠道

在当今信息爆炸的时代&#xff0c;知识管理已经成为了每个人必须面对的问题。然而&#xff0c;市面上的知识付费平台大多数都是通用的&#xff0c;无法满足个性化需求。 因此&#xff0c;我有才提供了一款专属定制的适合个人的知识付费平台。核心产品能力如下&#xff1a; 一…

Java:TCP 通信方法(基本发送 + 接收)并 实现文件传输且反馈

TCP 通信编程 TCP:是一种可靠的网络协议&#xff0c;再通信两端都建立一个Socket对象。 通信之前要保证连接已经建立。 通过Socket产生IO流进行通信。 创建对象时&#xff0c;会连接服务器&#xff0c;连接不上&#xff0c;会报错。 所以&#xff0c;先运行服务端&#xff0c;再…

6大最佳目标进度管理软件盘点——团队/个人

在当今快节奏的生活和工作中&#xff0c;有效地管理目标和任务对于每个人来说都至关重要。在工作中&#xff0c;我们需要清晰地规划项目目标、安排任务和追踪进度&#xff1b;在生活中&#xff0c;我们也需要合理安排时间、记录重要事项以及追踪个人目标的实现进度。为了更好地…