Solid 作者从 React 中学到最重要的是什么?


prtyaa
prtyaa 2024-01-06 22:36:29 65604 赞同 0 反对 0
分类: 资源 标签: 运维
前端界有句玩笑话 —— 「React 一点都不 react,Solid 才应该叫 React」。 作为一款「借鉴了很多 React 特性」的前端框架,截止目前,Solid已经有 29.6kstar。显然,他已经得到了社区的认可。

前段时间,Solid的作者「Ryan Carniato」在博文Thinking Locally with Signals[1]中提到 —— SolidReact中学到的最重要的东西,不是JSX虚拟DOM,而是一个被称为「局部思考」(Locality of Thinking)的概念。

本文就来聊聊这个对前端开发影响深远的理念。

局部思考是什么?

当我们新入职一家公司,在熟悉项目代码阶段,领导通常会分配给我们一些小需求,帮助我们快速熟悉项目代码。

这个过程是如此自然,以至于我们都忽视了一个重要问题 —— 为什么在一个庞大的项目代码库中,即使不熟悉代码,也能轻松修改一些小功能?

答案是 —— 「局部思考」理念在发挥作用。

「局部思考」是指你可以不看其他代码,只通过一个组件的代码就能理解它的行为。这种思考方式对代码的可维护性和可读性有着重大影响。

首先,在大型项目中,代码的「可维护性」至关重要。如果每次修改都需要理解整个代码库,那么这个项目可能会很快变得难以维护。

其次,从「可读性」的角度来看,如果代码的可读性好,那么新的开发人员可以更快地理解和开始他们的工作。

通过「局部思考」,可以使代码更易读、可维护性更高。试想,这不正是「使用框架开发」相比于「使用 jQuery 开发」的优势么?至于框架的其他特性(比如虚拟DOM细粒度更新Hooks…)都是在「局部思考」的基础上发展出来的。

可以说,「局部思考」是「框架开发」这种工作模式的基石。

如何实现局部思考

假设项目中有如下代码,你能保证结果是true么:

const obj = {}
someFunction(obj)

// 结果是 true 么?
console.log(obj.value === undefined)

要想知道结果,必须看someFunction函数的内部实现。如果项目中大量充斥了上面这样的代码,对可读性、可维护性简直是灾难。

「局部思考」理念的提出就是为了解决上述问题。要实现「局部思考」,有四个重要因素:

  • 单向数据流
  • 读写分离
  • 显式突变
  • 组件隔离

单向数据流

数据应该只在一个方向上流动。这样可以保证数据的来源和使用是一致的,使得代码行为更可预测,减小了出现bug的可能性。

考虑如下Solid代码,数据只从父组件流向子组件。子组件只读取数据,而不能改变它:

// 父组件内
const [count, setCount] = createSignal(0);


// 子组件内
const ChildComponent = ({ count }) => {
  // count是只读的
  return {count}
}

读写分离

读取数据和修改数据应该是两个独立的操作。这样可以降低代码的复杂度,使得阅读和理解代码更简单。

考虑如下Solid代码,SomeComponent通过title()读取值,通过setTitle修改值。这种分离使得我们可以更好地理解状态何时变化。

// [读, 写]
const [title, setTitle] = createSignal("title");

// `SomeComponent`不能改变`title`


// 现在`SomeComponent`可以更新title

在Svelte中,状态(或者叫signal)只能「按值传递」,所以下面SomeComponent即使接收title作为props,也无法直接修改他。

要修改他,需要执行updateTitle方法(方法内部闭包中的title是signal,可以响应更新)。这也是一种「读写分离」的实现。

let title = $state("title")

// `SomeComponent`不能改变`title`


// 现在`SomeComponent`可以更新title
 title = v} />

显式突变

所有的数据变化应该是显式的,而不是在背后默默发生。这样更容易跟踪数据的变化。考虑如下Solid代码:

// 定义状态
const [count, setCount] = createSignal(0);

// 显式改变状态
setCount(count() + 1);

是不是一下就想到了React中的useState呢?没错,其实不止是useState,在ClassComponent的this.setState也是遵循同样的原则。

组件隔离

每个组件应该只关心自己的状态和逻辑,而不是其他组件的。这样可以保证组件之间的独立性,降低耦合度,使得代码更易于维护。

总结

如果你觉得以上的介绍一点技术含量都没有,那是再自然不过的事。因为这些原则都是React最基本的使用规范。

本文存在的意义,是阐述一个观点 —— 这些规范之所以存在,是为了共同实现「局部思考」的理念。而这一理念,才是前端框架可维护性、可读性的来源。

按照这个思路去思考,就能明白很多React特性的用意,比如:

  • 为什么函数组件替代了类组件。
  • 为什么会出现useEffect这个Hook。
  • 为什么ref不能跨函数组件传递。

这些特性的背后,都体现了「局部思考」的理念。

如果您发现该资源为电子书等存在侵权的资源或对该资源描述不正确等,可点击“私信”按钮向作者进行反馈;如作者无回复可进行平台仲裁,我们会在第一时间进行处理!

评价 0 条
prtyaaL1
粉丝 1 资源 1949 + 关注 私信
最近热门资源
国产操作系统环境搭建(内含镜像资源链接和提取码)  96
银河麒麟桌面操作系统V10SP1-2403-update1版本中,通过“麒麟管家-设备管理-硬件信息-硬盘”查看硬盘类型时,显示的是HDD(机械硬盘),而实际上该笔记本的硬盘类型为SSD  91
分享几个在日常办公中可以用到的shell脚本  84
bat脚本生成查看电脑配置\硬件信息  81
以openkylin为例编译安装内核  80
常见系统问题及其解决方法  80
分享解决宏碁电脑关机时自动重启的方法  76
统信uosboot区分未挂载导致更新备份失败  71
分享如何解决报错:归档 xxx.deb 对成员 control.tar.zst 使用了未知的压缩,放弃操作  70
loadrunner常见问题整理  67
最近下载排行榜
国产操作系统环境搭建(内含镜像资源链接和提取码) 0
银河麒麟桌面操作系统V10SP1-2403-update1版本中,通过“麒麟管家-设备管理-硬件信息-硬盘”查看硬盘类型时,显示的是HDD(机械硬盘),而实际上该笔记本的硬盘类型为SSD 0
分享几个在日常办公中可以用到的shell脚本 0
bat脚本生成查看电脑配置\硬件信息 0
以openkylin为例编译安装内核 0
常见系统问题及其解决方法 0
分享解决宏碁电脑关机时自动重启的方法 0
统信uosboot区分未挂载导致更新备份失败 0
分享如何解决报错:归档 xxx.deb 对成员 control.tar.zst 使用了未知的压缩,放弃操作 0
loadrunner常见问题整理 0
作者收入月榜
1

prtyaa 收益401.13元

2

zlj141319 收益238.36元

3

哆啦漫漫喵 收益231.75元

4

IT-feng 收益219.97元

5

1843880570 收益214.2元

6

风晓 收益208.24元

7

777 收益173.2元

8

Fhawking 收益106.6元

9

信创来了 收益106.03元

10

克里斯蒂亚诺诺 收益91.08元

请使用微信扫码

添加我为好友,拉您入交流群!

请使用微信扫一扫!