vivipure / blog

Funkun's blog.
https://funkun.hashnode.dev/
2 stars 0 forks source link

Solid 使用体验 #24

Open vivipure opened 2 years ago

vivipure commented 2 years ago

写在前面

国庆假期基本没出去玩,学习了下Astro 和 Solid。这篇文章就来具体讲下 Solid 的开发体验,还有和Vue ,React的框架区别

React Like

const [count, setCount] = createSignal(0)

看到语法的第一眼,就会感到十分眼熟。这不是 React吗?

从语法上来说,Solid 和 React 十分相似,但确有根本上的不同。

在 Solid 中声明响应式变量需要用到 createSignal. 与 React 的 useState 不同的是,返回的第一个值为函数,而不是一个值。

React 为了实现组件中数据的更新,利用多次闭包加链表实现了 Hooks ,但是 Hooks 存在的闭包陷阱和必须顶层使用是无法进行避免的。

Solid 中直接返回一个函数,使用函数获取真实的值,完全没有 React hook 存在的问题。这里有点像 Vue3 ,但是比 Vue3 更简洁。

Reactive

在组件更新上,Solid的处理方式和 React 有很大的区别

React 函数组件中, 通过 setState 触发函数再次执行函数,实现组件更新。

而 Solid 函数组件中的代码只会执行一次,组件的更新依赖于响应式数据。Solid 实现了和Vue 类似的方式,进行了依赖收集。当数据变化时,组件就会进行更新。

...
const [count, setCount] = createSignal(0)

return <div onClick={() => setCount(prev => prev+1)}>{count()}</div>
...

由于是直接使用函数,useMemo 在Solid 中变得很简单

const [count, setCount] = createSignal(0)
const doubleCount = () => count() * 2

return <div onClick={() => setCount(prev => prev+1)}>{doubleCount()}</div>

不得不说,这样的实现十分优美

❌ Virtual DOM

Solid 还比较不同的地方,就在于DOM的更新策略上。

Solid 并没有使用 虚拟DOM, 而是基于真实DOM进行操作。Solid 将DOM的变化颗粒化,响应式数据的变化只对依赖的Node起作用。而不是像虚拟DOM 一样组件重新更新再比较差异进行 patch

这是一段Solid 代码

function Counter() {
    const [count, setCount] = createSignal(0);
    const increment = () => setCount(count() + 1);

    return (
    <button type="button" onClick={increment}>
        {count()}
        <span>{count() * 2}</span>
    </button>
    );

}

编译后的代码

const _tmpl$ = /*#__PURE__*/template(`<button type="button"><span></span></button>`, 4);
function Counter() {
    const [count, setCount] = createSignal(0);
    const increment = () => setCount(count() + 1);
    return (() => {
        const _el$ = _tmpl$.cloneNode(true),

        _el$2 = _el$.firstChild;

        _el$.$$click = increment;

        insert(_el$, count, _el$2);
        insert(_el$2, () => count() * 2);
    return _el$;
    })();

}

这里我们可以看出,其实函数组件就返回了一个DOM。后续数据的变化只会影响到收集到DOM,这一点十分巧妙。

缺点

  1. 由于响应式的实现问题,导致props不能解构,解构会丢失响应式。所以只能使用props获取属性
  2. 待补充

写在最后

使用过Vue, React后,来学习 Solid 有一种奇妙的感觉。Solid 使用了两个前辈的各自优点,又有自己的独特之处。

第一眼看到 Solid 时,感觉是React. 具体进行使用时,又感觉是 Vue. 到了最后,才发现Solid 就是 Solid.

这篇文章大概讲了下 Solid, 其实也没有讲具体用法。后续会更新具体的使用和相关生态。

vivipure commented 2 years ago

TS支持

tsconfig 配置 JSX

 "jsx": "preserve",
 "jsxImportSource": "solid-js"

vite支持

插件: vite-plugin-solid

babel: babel-preset-solid