0%

跟着New Bing学习Solid.js

晚上闲来无事,和 New Bing 就 solid.js 主题进行了一些交流,在十来轮的对话中,我对 solid.js 有了更深的了解。

编写的一个示例组件

calculator

节选的对话内容

介绍一下 solid.js

Solid.js 是一个用于创建用户界面的声明式 JavaScript 库 ¹。它受到 React 的大影响,但与 React 不同的是,它不使用虚拟 DOM,而是将模板编译为真实的 DOM 节点,并用细粒度的反应来更新它们 ⁴。你可以在你的应用中声明你的状态,并在任何地方使用它,当状态发生变化时,只有依赖于它的代码才会重新运行 ⁴。
Solid.js 的优点是性能高,语法简洁,灵活度大,开发体验好 ¹。它在许多 UI 速度和内存利用率的基准测试中都名列前茅 ¹。它还支持所有预期的现代库特性,甚至改进了一些特性以提高开发体验 ¹。

Solid.js 目前还是一个相对新的库,可能还没有 React 那么成熟和稳定。如果你想了解更多关于 Solid.js 的信息,你可以访问官方网站 ¹,或者查看教程 ² 和 GitHub 仓库 ⁴。

源: 与必应的对话, 2023/4/15
(1) SolidJS · Reactive Javascript Library. https://www.solidjs.com/.
(2) GitHub - solidjs/solid: A declarative, efficient, and flexible …. https://github.com/solidjs/solid.
(3) SolidJS · Reactive Javascript Library. https://www.solidjs.com/tutorial.
(4) 次世代の React? Solid.js について - Zenn. https://zenn.dev/nicky/articles/754f0ca74c887a.
(5) 5 Places SolidJS is not the Best - DEV Community. https://dev.to/this-is-learning/5-places-solidjs-is-not-the-best-5019.

Solid.js如何实现细粒度的反应?

Solid.js实现细粒度的反应的原理是基于观察者模式²。它使用一个全局的栈来在运行时追踪哪些信号(Signal)被读取或写入,以及哪些效果(Effect)或记忆(Memo)依赖于它们¹。当一个信号的值发生变化时,它会通知所有订阅了它的效果或记忆,并重新执行它们的函数¹。这样,只有真正需要更新的部分才会重新运行,而不是整个虚拟DOM³。

这种反应性的方式非常强大和灵活,它可以处理动态变化的依赖关系,比如通过执行不同的条件分支¹。它也可以通过多层间接性来工作,任何在跟踪范围内执行的函数也会被跟踪¹。你可以把Solid.js的反应性看作是一个自动化的事件系统,你只需要声明你的数据和视图,剩下的更新逻辑都由框架来处理。

源: 与必应的对话, 2023/4/15
(1) What is Reactivity - docs.solidjs.com. https://docs.solidjs.com/references/concepts/reactivity.
(2) SolidJS · Reactive Javascript Library. https://www.solidjs.com/guides/reactivity.
(3) Reactivity with SolidJS - Frontend Masters. https://frontendmasters.com/courses/reactivity-solidjs/.
(4) First look at fine-grained reactivity in Solid - SolidJS Source Code …. https://jser.dev/react/2023/02/26/reactivity-in-solidjs.html.
(5) SolidJS · Reactive Javascript Library. https://www.solidjs.com/?ref=workingsoftware-dev.

举个例子说明信号、效果和记忆的用法。

好的,我来给你一个简单的例子。假设我们要做一个计算器,可以输入两个数字,并显示它们的和、差、积和商。我们可以用信号来表示输入的数字,用效果来监听输入的变化并更新显示的结果,用记忆来缓存计算的结果。代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import { createSignal, createEffect, createMemo } from "solid-js";

const Calculator = () => {
// 创建两个信号,表示输入的数字
const [num1, setNum1] = createSignal(0);
const [num2, setNum2] = createSignal(0);

// 创建四个记忆,表示计算的结果
const sum = createMemo(() => num1() + num2());
const diff = createMemo(() => num1() - num2());
const prod = createMemo(() => num1() * num2());
const quot = createMemo(() => num1() / num2());

// 创建一个效果,当输入或结果发生变化时,打印到控制台
createEffect(() => {
console.log(`num1: ${num1()}, num2: ${num2()}`);
console.log(`sum: ${sum()}, diff: ${diff()}, prod: ${prod()}, quot: ${quot()}`);
});

// 返回一个JSX元素,包含两个输入框和四个显示结果的标签
return (
<div>
<input type="number" value={num1()} onInput={(e) => setNum1(e.target.value)} />
<input type="number" value={num2()} onInput={(e) => setNum2(e.target.value)} />
<p>Sum: {sum()}</p>
<p>Diff: {diff()}</p>
<p>Prod: {prod()}</p>
<p>Quot: {quot()}</p>
</div>
);
};

介绍一下solid.js的模板语言

Solid.js的模板语言是基于JSX的,它是一种在JavaScript中编写HTML标签的语法¹。它可以让你在组件中声明你的视图,并使用JavaScript表达式来动态地渲染数据¹。例如:

1
2
3
function Greeting(props) {
return <div>你好,{props.name}!</div>;
}

Solid.js的JSX需要通过Babel插件或Vite模板来编译,以便生成真实的DOM节点¹。编译后的代码会使用Solid.js提供的create*系列函数来创建信号、效果、记忆等反应性原语²。例如:

1
2
3
4
5
6
7
8
9
10
function Counter() {
const [count, setCount] = createSignal(0);
return (
<div>
<button onClick={() => setCount(count() + 1)}>+</button>
<span>{count()}</span>
<button onClick={() => setCount(count() - 1)}>-</button>
</div>
);
}

编译后的代码大致如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function Counter() {
const [count, setCount] = createSignal(0);
return createMemo(() =>
createFragment(
[
createComponent(Button, {
onClick: () => setCount(count() + 1),
children: "+",
}),
createText(count),
createComponent(Button, {
onClick: () => setCount(count() - 1),
children: "-",
}),
],
undefined,
undefined
)
);
}

Solid.js的JSX支持所有标准的HTML属性和事件,以及一些特殊的属性,比如ref、key、use、children等³。你可以在Solid.js的文档中查看更多关于JSX的信息和示例。

源: 与必应的对话, 2023/4/15
(1) GitHub - solidjs/templates: Vite + solid templates. https://github.com/solidjs/templates.
(2) SolidJS · Reactive Javascript Library. https://www.solidjs.com/guides/getting-started.
(3) GitHub - solidjs/solid: A declarative, efficient, and flexible …. https://github.com/solidjs/solid.

如何在solid.js的模板中进行条件判断和循环处理

在Solid.js的模板中进行条件判断和循环处理,有以下几种方法:

  • 使用JavaScript的三元运算符(a ? b : c)或逻辑与运算符(a && b)来实现简单的条件渲染¹。例如:
1
2
3
function Greeting(props) {
return <div>{props.name ? `你好,${props.name}!` : "你好,陌生人!"}</div>;
}
  • 使用Solid.js提供的组件来实现更复杂的条件渲染¹。它接受一个when属性和一个fallback属性,分别表示条件为真和为假时要渲染的内容¹。例如:
1
2
3
4
5
6
7
8
9
10
function Greeting(props) {
return (
<Show
when={props.name}
fallback={<div>你好,陌生人!</div>}
>
<div>你好,{props.name}!</div>
</Show>
);
}
  • 使用JavaScript的Array.prototype.map方法来实现数组的循环渲染¹。注意要给每个元素添加一个唯一的key属性,以便Solid.js正确地更新DOM¹。例如:
1
2
3
4
5
6
7
8
9
function List(props) {
return (
<ul>
{props.items.map((item) => (
<li key={item.id}>{item.name}</li>
))}
</ul>
);
}
  • 使用Solid.js提供的组件来实现更高级的循环渲染¹。它接受一个each属性和一个fallback属性,分别表示要遍历的数组和数组为空时要渲染的内容¹。它还提供了一些特殊的变量,比如index、first、last等,可以在循环中使用¹。例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function List(props) {
return (
<For
each={props.items}
fallback={<div>没有数据</div>}
>
{(item, index) => (
<div key={item.id}>
{index() + 1}. {item.name}
</div>
)}
</For>
);
}

源: 与必应的对话, 2023/4/15
(1) SolidJS · Reactive Javascript Library. https://www.solidjs.com/tutorial/flow_show.
(2) GitHub - solidjs/templates: Vite + solid templates. https://github.com/solidjs/templates.
(3) javascript - Conditional styling in SolidJS - Stack Overflow. https://stackoverflow.com/questions/72297265/conditional-styling-in-solidjs.

这些方法有什么优缺点?

这些方法的优点是:

  • 它们都是基于JavaScript的,所以你不需要学习新的语法或API。
  • 它们都是声明式的,所以你只需要关注你想要渲染什么,而不是如何渲染。
  • 它们都是反应式的,所以当数据发生变化时,它们会自动更新视图。
  • 它们都是编译时优化的,所以它们会生成高效的DOM操作。

这些方法的缺点是:

  • 它们有时候可能不够直观或易读,比如使用逻辑运算符来实现条件渲染。
  • 它们有时候可能不够灵活或强大,比如使用Array.prototype.map方法来实现循环渲染。
  • 它们有时候可能需要额外的注意或配置,比如给循环元素添加key属性或设置tsconfig.json来支持JSX 。

solid.js还有哪些有趣或者高效的用法

Solid.js是一个有趣和高效的用于创建用户界面的JavaScript库,它有以下一些有趣或高效的用法:

  • 使用Solid.js的反应性原语,你可以轻松地创建和管理你的应用状态,并在任何地方使用它¹。你可以使用createSignal、createEffect、createMemo等函数来声明你的数据和视图,并让它们自动同步更新¹。
  • 使用Solid.js的编译器,你可以把你的JSX模板编译成真实的DOM节点,并用细粒度的反应来更新它们²。这样,你可以避免使用虚拟DOM或复杂的diff算法,从而提高性能和内存利用率²。
  • 使用Solid.js的控制流组件,你可以在你的模板中实现条件渲染和循环渲染³。你可以使用等组件来控制你的视图逻辑,并让它们根据数据变化而动态更新³。
  • 使用Solid.js的资源组件,你可以从服务器获取数据并更新你的视图。你可以使用等组件来处理异步数据,并显示加载或错误状态。
  • 使用Solid.js的Web组件,你可以创建可复用和可扩展的自定义元素。你可以使用createComponent、defineElement等函数来封装你的组件逻辑,并在任何框架中使用它们。

源: 与必应的对话, 2023/4/15
(1) SolidJS · Reactive Javascript Library. https://www.solidjs.com/.
(2) SolidJS vs. React: Comparing declarative UI libraries. https://blog.logrocket.com/solidjs-vs-react/.
(3) SolidJS · Reactive Javascript Library. https://www.solidjs.com/resources.

你能给我一些关于如何使用这些用法的示例吗?

当然,我很乐意给你一些示例。以下是一些使用Solid.js的有趣或高效的用法的代码片段:

  • 使用Solid.js的反应性原语,你可以创建一个简单的计数器组件,如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import { createSignal, createEffect } from "solid-js";

function Counter() {
// 创建一个信号,表示计数器的值
const [count, setCount] = createSignal(0);

// 创建一个效果,当计数器的值发生变化时,打印到控制台
createEffect(() => console.log(`Count: ${count()}`));

// 返回一个JSX元素,包含两个按钮和一个显示计数器的值的标签
return (
<div>
<button onClick={() => setCount(count() + 1)}>+</button>
<span>{count()}</span>
<button onClick={() => setCount(count() - 1)}>-</button>
</div>
);
}
  • 使用Solid.js的编译器,你可以把你的JSX模板编译成真实的DOM节点,并用细粒度的反应来更新它们,如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import { createSignal } from "solid-js";

function Greeting() {
// 创建一个信号,表示问候语
const [greeting, setGreeting] = createSignal("Hello");

// 返回一个JSX元素,包含一个输入框和一个显示问候语的标签
return (
<div>
<input type="text" value={greeting()} onInput={(e) => setGreeting(e.target.value)} />
<p>{greeting()}, world!</p>
</div>
);
}

编译后的代码大致如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import { createSignal, createMemo, createComponent } from "solid-js";

function Greeting() {
// 创建一个信号,表示问候语
const [greeting, setGreeting] = createSignal("Hello");

// 返回一个记忆,表示要渲染的DOM节点
return createMemo(() =>
createFragment(
[
createComponent(Input, {
type: "text",
value: greeting(),
onInput: (e) => setGreeting(e.target.value),
}),
createText(greeting),
createText(", world!"),
],
undefined,
undefined
)
);
}
  • 使用Solid.js的控制流组件,你可以在你的模板中实现条件渲染和循环渲染,如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import { Show, For } from "solid-js";

function TodoList(props) {
// 返回一个JSX元素,包含一个条件渲染和一个循环渲染的组件
return (
<div>
<Show when={props.todos.length > 0} fallback={<p>没有待办事项</p>}>
<ul>
<For each={props.todos}>
{(todo) => <li key={todo.id}>{todo.title}</li>}
</For>
</ul>
</Show>
</div>
);
}

请展示一些使用solid.js资源组件的示例

好的,我来给你一些使用Solid.js资源组件的示例。以下是一些使用等组件来处理异步数据的代码片段:

  • 使用组件,你可以动态地加载一个组件,并在加载完成前显示一个占位符,如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
import { Dynamic } from "solid-js";

function App() {
// 返回一个JSX元素,包含一个动态加载的组件和一个占位符
return (
<div>
<Dynamic
component={import("./Counter")} // 异步导入Counter组件
fallback={<p>Loading...</p>} // 加载前显示的占位符
/>
</div>
);
}
  • 使用组件,你可以从服务器获取数据并更新你的视图,如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
import { Resource } from "solid-js";

function App() {
// 创建一个资源,表示从服务器获取的用户数据
const [user] = Resource(() => fetch("/api/user").then((r) => r.json()));

// 返回一个JSX元素,包含一个显示用户数据的标签
return (
<div>
<p>{user.name}</p>
</div>
);
}
  • 使用组件,你可以在多个资源加载完成前显示一个加载状态,如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import { Suspense, Resource } from "solid-js";

function App() {
// 创建两个资源,分别表示从服务器获取的用户数据和文章数据
const [user] = Resource(() => fetch("/api/user").then((r) => r.json()));
const [posts] = Resource(() => fetch("/api/posts").then((r) => r.json()));

// 返回一个JSX元素,包含一个悬停状态和一个显示用户和文章数据的标签
return (
<Suspense fallback={<p>Loading...</p>}>
<div>
<p>{user.name}</p>
<ul>
{posts.map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
</div>
</Suspense>
);
}

solid.js的生态中有没有比较成熟的组件库

Solid.js的生态中有一些比较成熟的组件库,比如:

  • solid-styled-components:这个库提供了Styled Components和css helper,让你可以在Solid.js中使用流行的JS in CSS库¹。
  • solid-heroicons:这个库提供了一个方便地使用Tailwind Heroicons的组件¹。
  • solid-transition-group:这个库提供了一个受React Transition Group和Vue Transitions影响的动画库,让你可以在Solid.js中创建过渡效果¹。
  • solid-particles:这个库提供了一个官方的particles.js实现,让你可以在Solid.js中创建粒子效果¹。
  • SUID - Material UI:这个库提供了一个Material UI的移植,让你可以在Solid.js中使用Material风格的组件²。

除此之外,还有一些第三方库提供了一些其他的组件或工具,比如:

  • solid-playground:这个库提供了一个用于在浏览器中编写和运行Solid代码的在线工具¹。
  • solid-custom-scrollbars:这个库提供了一些自定义的滚动条组件,让你可以在Solid.js中美化你的滚动条³。
  • solid-custom-navigation:这个库提供了一些自定义的导航组件,让你可以在Solid.js中实现自定义的页面过渡逻辑和动画³。
  • solid-copy-to-clipboard:这个库提供了一个复制到剪贴板的组件,让你可以在Solid.js中使用自定义的事件触发器来复制文本³。
  • solid-apexcharts:这个库提供了一个ApexCharts的移植,让你可以在Solid.js中创建交互式的可视化图表。

源: 与必应的对话, 2023/4/15
(1) SolidJS · Reactive Javascript Library. https://www.solidjs.com/ecosystem.
(2) SolidJS vs. React: Comparing declarative UI libraries. https://blog.logrocket.com/solidjs-vs-react/.
(3) SolidJS · Reactive Javascript Library. https://www.solidjs.com/guides/faq.

solid.js与React.js的性能对比如何

Solid.js与React.js的性能对比,有以下几个方面:

  • 启动时间:Solid.js的启动时间比React.js快得多,因为它不需要加载虚拟DOM或其他额外的库¹。根据一个基准测试,Solid.js的启动时间是React.js的1/3左右²。
  • 运行性能:Solid.js的运行性能比React.js高得多,因为它使用细粒度的反应来直接更新DOM,而不需要使用虚拟DOM或复杂的diff算法¹。根据一个基准测试,Solid.js的运行性能是React.js的2倍以上²。
  • 内存占用:Solid.js的内存占用比React.js低得多,因为它不需要创建和维护虚拟DOM或其他中间层的对象¹。根据一个基准测试,Solid.js的内存占用是React.js的1/4左右²。

综上所述,Solid.js在性能方面明显优于React.js,这主要归功于它使用了不同的DOM操作和反应性原理。当然,这并不意味着React.js就没有优势,比如它有更丰富的生态系统和社区支持³。你可以根据你的具体需求和场景来选择合适的框架。

源: 与必应的对话, 2023/4/15
(1) SolidJS vs. ReactJS |User Interface |Dexlock. https://dexlock.com/blog/comparison-between-solidjs-and-react-in-basic-level/.
(2) SolidJS vs. React: Comparing declarative UI libraries. https://blog.logrocket.com/solidjs-vs-react/.
(3) SolidJS vs. React: The Go-to Guide | Toptal®. https://www.toptal.com/react/solidjs-vs-react.

这些性能指标有什么实际意义吗?

这些性能指标有以下一些实际意义:

  • 启动时间:启动时间影响了用户对应用的第一印象,以及应用的可用性和可靠性。如果启动时间太长,用户可能会感到不耐烦或失去兴趣,甚至放弃使用应用。因此,启动时间越短越好。
  • 运行性能:运行性能影响了用户对应用的交互体验,以及应用的稳定性和效率。如果运行性能太低,用户可能会感到卡顿或延迟,甚至出现错误或崩溃。因此,运行性能越高越好。
  • 内存占用:内存占用影响了用户对应用的资源消耗,以及应用的兼容性和扩展性。如果内存占用太高,用户可能会感到电池耗尽或设备发热,甚至无法运行应用。因此,内存占用越低越好。

总之,这些性能指标都是衡量一个应用质量和用户满意度的重要因素。当然,并不是说性能就是唯一的衡量标准,还有其他方面也需要考虑,比如功能、设计、安全等。

我想使用solid.js开发一个业余项目,暂时没有好的想法,你有什么建议吗?

我很高兴你想使用Solid.js开发一个业余项目,这是一个很好的学习和实践的机会。关于项目的想法,我有以下一些建议:

  • 你可以根据你的兴趣或爱好来选择一个主题,比如音乐、电影、游戏、运动等。这样,你可以更有动力和乐趣地开发项目,并且可以利用你的专业知识或经验来增加项目的价值和创意。
  • 你可以根据你的技能或水平来选择一个难度,比如简单、中等、困难等。这样,你可以更合理地规划和管理项目,并且可以挑战自己或提升自己的能力和信心。
  • 你可以根据你的时间或资源来选择一个规模,比如小型、中型、大型等。这样,你可以更有效地分配和利用项目,并且可以避免过度或不足的投入或产出。
  • 你可以根据你的目标或需求来选择一个类型,比如个人、团队、社区等。这样,你可以更明确地定位和传达项目,并且可以获得更多的反馈或支持。

以上是一些通用的建议,具体的项目想法还需要你自己去发现和创造。如果你需要一些灵感或参考,你可以查看一些已经使用Solid.js开发的项目,比如:

  • Solid RealWorld:这是一个使用Solid.js实现的RealWorld示例应用,它是一个类似于Medium的博客平台。
  • Solid Chess:这是一个使用Solid.js实现的国际象棋游戏,它支持人机对战和人人对战。
  • Solid TodoMVC:这是一个使用Solid.js实现的TodoMVC示例应用,它是一个简单的待办事项列表。

希望这些建议和示例对你有所帮助,祝你开发顺利!

我已经有了一个想法,你能给我一些关于如何开始开发的建议吗?

很好,你已经有了一个想法,那么你可以按照以下步骤来开始开发:

  • 第一步,你需要准备你的开发环境,比如安装Node.js、npm、git等工具,并且选择一个合适的代码编辑器或IDE,比如VS Code、WebStorm等。
  • 第二步,你需要创建你的项目文件夹,并且初始化你的项目配置,比如package.json、tsconfig.json等。你可以使用Solid.js提供的脚手架工具,比如solid-start、solid-scripts等,来快速生成一个基本的项目模板。
  • 第三步,你需要安装你的项目依赖,比如solid-js、solid-app-router等。你可以使用npm或yarn等包管理器,来安装和管理你的依赖。
  • 第四步,你需要编写你的项目代码,比如创建和导出你的组件、定义和使用你的状态和逻辑、设置和导航你的路由等。你可以参考Solid.js的文档和示例,来学习和掌握它的语法和API。
  • 第五步,你需要测试和调试你的项目代码,比如运行和查看你的应用、检查和修复你的错误、优化和改进你的性能等。你可以使用Solid.js提供的开发工具,比如solid-dev-server、solid-devtools等,来辅助你的测试和调试。
  • 第六步,你需要构建和部署你的项目代码,比如打包和压缩你的资源、选择和配置你的服务器、发布和更新你的应用等。你可以使用Solid.js提供的构建工具,比如vite-plugin-solid、esbuild-plugin-solid等,来简化你的构建和部署。

以上是一些通用的步骤,具体的细节可能会根据你的项目需求和场景而有所不同。如果你遇到任何问题或困难,你可以查看Solid.js的文档和教程,或者加入Solid.js的社区和论坛,寻求帮助和支持。

总结

使用New Bing进行新知识的学习的体验相当不错,它会查询并总结互联网上的时效性强并且相对权威的资料(这一点比ChatGPT强),并且会提示你下一轮的问题,引导你进行深入的学习。

扫码加入技术交流群🖱️
QR code