盘点 Solid.js 源码中的那些迷惑行为

本文详细探讨了Solid.js源码中的一些令人困惑的设计,包括DOM Expressions、谜之叹号和迷之ref。作者指出,DOM Expressions是Solid.js的编译器,其编译策略与React的JSX有所不同。谜之叹号涉及到的空注释节点实际上是编译过程中用于定位的占位符。至于迷之ref,Solid.js的ref处理方式与React类似但有创新,可以接受函数或普通变量。文章总结了源码中的一些巧妙设计和不严谨之处,强调了Solid.js与React在灵活性和编译策略上的差异。
摘要由CSDN通过智能技术生成

前言

我研究 Solid.js 源码已经有一段时间了,在钻研的过程中我发现了其中的一些迷惑行为,在搞懂之后终于恍然大悟,忍不住想要分享给大家。不过这么说其实也不太准确,因为在严格意义上来讲 Solid.js 其实是被划分为了两个部分的。我只认真钻研了其中一个部分,所以也不能说钻研 Solid.js 源码,因为另外一个部分压根就不叫 Solid

有些同学看到这可能就会感到疑惑了,哪两个部分?Solid.js?其实是这样:大家应该都听说过 Solid.js 是一个重编译、轻运行的框架吧,所以它可以被分为编译器和运行时两个部分。那有人可能会问:你要是这么说的话那岂不是 Vue 也可以被分为两部分,毕竟 Vue 也有编译器和运行时,为什么从来没有人说过 Vue 是两部分组成的呢?是这样,Vue 的编译器和运行时全都放在了同一仓库内的 Monorepo 中:

你可以说 Vue2Vue3 是两个部分,因为它俩被放在了两个不同的仓库中:

虽然它俩已经是两个不同的仓库了,但好歹也都是 vuejs 名下的吧:

Solid.js 的两部分不仅不在同一个仓库内,甚至连组织名都不一样:

一个是 solidjs/solid

而另一个则是 ryansolid/dom-expressions

ryanSolid.js 作者的名字,所以 ryan + solid = ryansolid(有点迷,为啥不放在 solidjs 旗下非要单独开一个 ryansolid

这个 dom-expressions 就是 Solid.js 的编译器,那为啥不像 Vue 编译器似的都放在同一个仓库内呢?因为 Vue 的编译器就是专门为 Vue 设计的,你啥时候看非 Vue 项目中使用 xxx.vue 这样的写法过?.vue 这种单文件组件就只有 Vue 使用,虽说其他框架也有单文件组件的概念并且有着类似的写法(如:xxx.svelte)但人家 Svelte 也不会去用 Vue 的编译器去编译人家的 Svelte 组件。不过 Solid 不一样,Solid 没自创一个 xxx.solid,而是明智的选择了 xxx.jsx

单文件组件和 jsx 各有利弊,不能说哪一方就一定比另一方更好。但对于一个声明式框架作者而言,选择单文件组件的好处是可以自定义各种语法,并且还可以牺牲一定的灵活性来换取更优的编译策略。缺点就是成本太高了,单单语法高亮和 TS 支持度这一方面就得写一个非常复杂的插件才能填平。好在 Vue 的单文件组件插件 Volar 已经可以支持自定义自己的单文件组件插件了,这有效的降低了框架作者的开发成本。但 Solid 刚开始的时候还没有 Volar 呢(可以去看看 Volar 的源码有多复杂 这还仅仅只是一个插件就需要花费那么多时间和精力),甚至直到现在 Volar 也没个文档,就只有 Vue 那帮人在用 Volar(毕竟是他们自己研究的):

并且人家选择 jsx 也有可能并非是为了降低开发成本,而是单纯的钟意于 jsx 语法而已。那么为什么选择 jsx 会降低开发成本呢?首先就是不用自己写 parsergenerator 等一堆编译相关的东西了,一个 babel 插件就能识别 jsx 语法。语法高亮、TS 支持度这方面更是不用操心,甚至用户都不需要为编辑器安装任何插件(何时听过 jsx 插件)。并且由于 React 是全球占有率最高的框架,jsx 已被广泛接受(甚至连 Vue 都支持 jsx)但如果选择单文件组件的话又会产生有人喜欢这种写法有人喜欢那种写法的问题,比方说同样使用 sfcVueSvelteif-else 写法分别是这样:

<!-- Vue -->
<template>
  <h1 v-if="xxx" />
  <div v-else />
</template>
<!-- Svelte -->
{#if xxx}
  <h1 />
{:else}
  <div />
{/if}

有人喜欢上面那种写法就有人喜欢下面那种写法,众口难调,无论选择哪种写法可能都会导致另一部分的用户失望。而 jsx 就灵活的多了,if-else 想写成什么样都可以根据自己的喜好来:

if (xxx) {
   
  return <h1 />
} else {
   
  return <div />
}
// 或者
return xxx ? <h1 /> : <div />
// 亦或
let Title = 'h1'
if (xxx) Title = 'div'
return <Title />

jsx 最大程度的融合了 js,正是因为它对 js 良好的兼容性才导致它的适用范围更广,而不是像 VueSvelte 那样只适用于自己的框架。毕竟每种模板语言的 if-else、循环等功能写法都不太一样,当然 jsx 里的 if-else 也可以有各种千奇百怪的写法,但毕竟还是 js 写法,而不是自创的 ng-ifv-else{:else if} {% for i in xxx %}等各种不互通的写法。

正是由于 jsx 的这个优势导致了很多非 React 框架(如:Preact、Stancil、Solid 等)用 jsx 也照样用的飞起,那么既然 jsx 可以不跟 React 绑定,那 Ryan 自创的 jsx 编译策略也同样可以不跟 Solid 绑定啊对不对?这是一款可以和 Solid.js 搭配使用的 babel 插件,也同样是一款可以和 MobX、和 Knockout、和 S.js、甚至和 Rx.js 搭配使用的插件,只要你有一款响应式系统,那么 dom-expressions 就可以为你提供 jsx 服务。

所以这才是 Ryan 没把 dom-expressions 放在 solidjs/solid 里的重要原因之一,但 Solid.js 又是一个注重编译的框架,没了 dom-expressions 还不行,所以只能说 Solid.js 是由两部分组成的。

DOM Expressions

DOM Expressions 翻译过来就是 DOM 表达式的意思,有人可能会问那你标题为啥不写成《盘点 DOM Expressions 源码中的那些迷惑行为》?拜托!谁知道 DOM Expressions 到底是个什么鬼!如果不是我苦口婆心的说了这么多,有几个能知道这玩意就是 Solid.js 的编译器,甭说国内了,就连国外都没几个知道 DOM Expressions 的。你要说 Solid.js 那别人可能会竖起大拇指说声 Excellent,但你要说 DOM Expressions 那别人说的很可能就是 What the fuck is that? 了。不信你看它俩的🌟对比:

再来看看 Ryan油管上亲自直播 DOM Expressions时的惨淡数据:

这都没我在掘金随便写篇文章的点赞量高,信不信如果我把标题中的 Solid.js 换成了 DOM Expression 的话点赞量都不会有 Ryan 直播的数据好?好歹人家还是 Solid 的作者,都只能获得如此惨淡的数据,那更别提我了。

言归正传,为了防止大家不知道 Solid.js 编译后的产物与 React 编译后的产物有何不同,我们先来写一段简单的 jsx

import c from 'c'
im
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值