在前面的文章中,我们学习了 Solid 的响应式原理,深入了了解其实现方式。

Solid 之旅 —— Signal 响应式原理

这篇文章将主要深入解析组件内部props的原理,为什么结构后会导致响应式丢失?

案例

我们以一个例子作为参考,由浅入深的讲解其中的奥秘。

Parent.tsx

import { createSignal } from 'solid-js'
import Child from './child'

export default function Props() {
  const [name, setName] = createSignal('JinSo')
  const [age, setAge] = createSignal(23)

  const update = () => {
    setName('Jason')
    setAge(99)
  }

  return (
    <section class='text-gray-700 p-8'>
      <Child name={name()} age={age()} />
      <button type='button' onClick={update}>
        Update
      </button>
    </section>
  )
}

Child.tsx

interface ChildProps {
  name: string
  age: number
}

export default function Child(props: ChildProps) {
  return (
    <div>
      <div>name: {props.name}</div>
      <div>age: {props.age}</div>
    </div>
  )
}

组件编译

先来看看组件编译后是什么样子的,官网也提供了 Playground,可以进行尝试:

Solid Playground

Parent.tsx 组件编译效果

import { template as _$template } from "solid-js/web";
import { delegateEvents as _$delegateEvents } from "solid-js/web";
import { insert as _$insert } from "solid-js/web";
import { createComponent as _$createComponent } from "solid-js/web";
var _tmpl$ = /*#__PURE__*/_$template(`<section class="text-gray-700 p-8"><button type=button>Update`);
import { render } from "solid-js/web";
import { createSignal } from "solid-js";

export default function Props() {
  const [name, setName] = createSignal('JinSo');
  const [age, setAge] = createSignal(23);
  const update = () => {
    setName('Jason');
    setAge(99);
  };
  return (() => {
    var _el$ = _tmpl$(),
      _el$2 = _el$.firstChild;
    _$insert(_el$, _$createComponent(Child, {
      get name() {
        return name();
      },
      get age() {
        return age();
      }
    }), _el$2);
    _el$2.$$click = update;
    return _el$;
  })();
}

render(() => _$createComponent(Props, {}), document.getElementById("app"));
_$delegateEvents(["click"]);

Child.tsx 组件编译效果

import { template as _$template } from "solid-js/web";
import { createComponent as _$createComponent } from "solid-js/web";
import { insert as _$insert } from "solid-js/web";
var _tmpl$ = /*#__PURE__*/_$template(`<div><div>name: </div><div>age: `);
import { render } from "solid-js/web";

function Child(props) {
  return (() => {
    var _el$ = _tmpl$(),
      _el$2 = _el$.firstChild,
      _el$3 = _el$2.firstChild,
      _el$4 = _el$2.nextSibling,
      _el$5 = _el$4.firstChild;
    _$insert(_el$2, () => props.name, null);
    _$insert(_el$4, () => props.age, null);
    return _el$;
  })();
}