import { jsx, jsxs, Fragment } from 'solid-jsx/jsx-runtime';

/*@jsxRuntime automatic @jsxImportSource solid-jsx*/
const toc = [{
  "depth": 1,
  "value": "响应性",
  "children": [{
    "depth": 2,
    "value": "Primitives 简介",
    "children": []
  }, {
    "depth": 2,
    "value": "如何运作的？",
    "children": []
  }, {
    "depth": 2,
    "value": "注意事项",
    "children": []
  }]
}];
function _createMdxContent(props) {
  const _components = Object.assign({
    h1: "h1",
    a: "a",
    p: "p",
    code: "code",
    pre: "pre",
    span: "span",
    h2: "h2",
    ol: "ol",
    li: "li"
  }, props.components);
  return jsxs(Fragment, {
    children: [jsxs(_components.h1, {
      id: "响应性",
      children: [jsx(_components.a, {
        className: "header-anchor",
        href: "#响应性",
        children: "#"
      }), "响应性"]
    }), "\n", jsx(_components.p, {
      children: "Solid 的数据管理建立在一系列灵活的响应式 primitive 之上，这些 primitive 负责所有的更新。它采用与 MobX 或 Vue 非常相似的方法，只是它没有和虚拟 DOM 进行颗粒度绑定。当你访问你的 Effects 和 JSX 视图代码中的响应式值时，它会自动跟踪依赖项。"
    }), "\n", jsxs(_components.p, {
      children: ["Solid 的 primitives 通常以 ", jsx(_components.code, {
        children: "create"
      }), " 调用的形式出现，通常返回元组，其中通常第一个元素是可读 primitive，第二个元素是 setter。通常通过 primitive 名称来引用可读部分。"]
    }), "\n", jsxs(_components.p, {
      children: ["这是一个基础的自动递增计数器，它根据设置的 ", jsx(_components.code, {
        children: "count"
      }), " Signal 进行更新"]
    }), "\n", jsx(_components.pre, {
      children: jsxs(_components.code, {
        className: "hljs language-jsx",
        children: [jsx(_components.span, {
          className: "hljs-keyword",
          children: "import"
        }), " { createSignal, onCleanup } ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "from"
        }), " ", jsx(_components.span, {
          className: "hljs-string",
          children: "\"solid-js\""
        }), ";\n", jsx(_components.span, {
          className: "hljs-keyword",
          children: "import"
        }), " { render } ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "from"
        }), " ", jsx(_components.span, {
          className: "hljs-string",
          children: "\"solid-js/web\""
        }), ";\n\n", jsx(_components.span, {
          className: "hljs-keyword",
          children: "const"
        }), " ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "App"
        }), " = (", jsx(_components.span, {
          className: "hljs-params"
        }), ") => {\n  ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "const"
        }), " [count, setCount] = ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "createSignal"
        }), "(", jsx(_components.span, {
          className: "hljs-number",
          children: "0"
        }), "),\n    timer = ", jsx(_components.span, {
          className: "hljs-built_in",
          children: "setInterval"
        }), "(", jsx(_components.span, {
          className: "hljs-function",
          children: "() =>"
        }), " ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "setCount"
        }), "(", jsx(_components.span, {
          className: "hljs-title function_",
          children: "count"
        }), "() + ", jsx(_components.span, {
          className: "hljs-number",
          children: "1"
        }), "), ", jsx(_components.span, {
          className: "hljs-number",
          children: "1000"
        }), ");\n  ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "onCleanup"
        }), "(", jsx(_components.span, {
          className: "hljs-function",
          children: "() =>"
        }), " ", jsx(_components.span, {
          className: "hljs-built_in",
          children: "clearInterval"
        }), "(timer));\n\n  ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "return"
        }), " ", jsxs(_components.span, {
          className: "xml",
          children: [jsxs(_components.span, {
            className: "hljs-tag",
            children: ["<", jsx(_components.span, {
              className: "hljs-name",
              children: "div"
            }), ">"]
          }), "{count()}", jsxs(_components.span, {
            className: "hljs-tag",
            children: ["</", jsx(_components.span, {
              className: "hljs-name",
              children: "div"
            }), ">"]
          })]
        }), ";\n};\n\n", jsx(_components.span, {
          className: "hljs-title function_",
          children: "render"
        }), "(", jsx(_components.span, {
          className: "hljs-function",
          children: "() =>"
        }), " ", jsx(_components.span, {
          className: "xml",
          children: jsxs(_components.span, {
            className: "hljs-tag",
            children: ["<", jsx(_components.span, {
              className: "hljs-name",
              children: "App"
            }), " />"]
          })
        }), ", ", jsx(_components.span, {
          className: "hljs-variable language_",
          children: "document"
        }), ".", jsx(_components.span, {
          className: "hljs-title function_",
          children: "getElementById"
        }), "(", jsx(_components.span, {
          className: "hljs-string",
          children: "\"app\""
        }), "));\n"]
      })
    }), "\n", jsxs(_components.h2, {
      id: "primitives-简介",
      children: [jsx(_components.a, {
        className: "header-anchor",
        href: "#primitives-简介",
        children: "#"
      }), "Primitives 简介"]
    }), "\n", jsx(_components.p, {
      children: "Solid 由 3 个主要 Primitive 组成，即 Signal、Memo 和 Effect。它们的核心是观察者模式，其中通过封装 Memos 和 Effect 来跟踪 Signal（以及 Memo）。"
    }), "\n", jsx(_components.p, {
      children: "Signal 是最简单的 primitive。它们包含值，以及 get 和 set 函数，因此我们可以在读取和写入的时候进行拦截"
    }), "\n", jsx(_components.pre, {
      children: jsxs(_components.code, {
        className: "hljs language-js",
        children: [jsx(_components.span, {
          className: "hljs-keyword",
          children: "const"
        }), " [count, setCount] = ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "createSignal"
        }), "(", jsx(_components.span, {
          className: "hljs-number",
          children: "0"
        }), ");\n"]
      })
    }), "\n", jsx(_components.p, {
      children: "Effect 是读取 Signal 的封装函数，并且会在依赖的 Signal 值发生变化时重新执行。这对于创建诸如渲染之类副作用很有用。"
    }), "\n", jsx(_components.pre, {
      children: jsxs(_components.code, {
        className: "hljs language-js",
        children: [jsx(_components.span, {
          className: "hljs-title function_",
          children: "createEffect"
        }), "(", jsx(_components.span, {
          className: "hljs-function",
          children: "() =>"
        }), " ", jsx(_components.span, {
          className: "hljs-variable language_",
          children: "console"
        }), ".", jsx(_components.span, {
          className: "hljs-title function_",
          children: "log"
        }), "(", jsx(_components.span, {
          className: "hljs-string",
          children: "\"The latest count is\""
        }), ", ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "count"
        }), "()));\n"]
      })
    }), "\n", jsx(_components.p, {
      children: "最后，Memo 是缓存的派生值。它们有着 Signal 和 Effect 相同的属性。Memo 跟踪自己的 Signal，仅在这些 Signal 发生变化时重新执行，并且本身是可跟踪的 Signal。"
    }), "\n", jsx(_components.pre, {
      children: jsxs(_components.code, {
        className: "hljs language-js",
        children: [jsx(_components.span, {
          className: "hljs-keyword",
          children: "const"
        }), " fullName = ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "createMemo"
        }), "(", jsx(_components.span, {
          className: "hljs-function",
          children: "() =>"
        }), " ", jsxs(_components.span, {
          className: "hljs-string",
          children: ["`", jsx(_components.span, {
            className: "hljs-subst",
            children: "${firstName()}"
          }), " ", jsx(_components.span, {
            className: "hljs-subst",
            children: "${lastName()}"
          }), "`"]
        }), ");\n"]
      })
    }), "\n", jsxs(_components.h2, {
      id: "如何运作的",
      children: [jsx(_components.a, {
        className: "header-anchor",
        href: "#如何运作的",
        children: "#"
      }), "如何运作的？"]
    }), "\n", jsx(_components.p, {
      children: "Signal 作为事件发射器持有订阅列表。每当它们的值发生变化时，它们都会通知其订阅者。"
    }), "\n", jsx(_components.p, {
      children: "更有趣的是这些订阅是如何发生的。Solid 使用自动依赖跟踪。数据一旦变化，更新会自动发生。"
    }), "\n", jsx(_components.p, {
      children: "里面利用了运行时的全局堆栈的小技巧来实现。在 Effect 或 Memo 执行（或重新执行）开发人员编写函数之前，它会将自己压入该堆栈。然后读取的任何 Signal 检查堆栈上是否有当前侦听器，如果有，则将该侦听器添加到其订阅中。"
    }), "\n", jsx(_components.p, {
      children: "你可以通过下面代码进行思考："
    }), "\n", jsx(_components.pre, {
      children: jsxs(_components.code, {
        className: "hljs language-js",
        children: [jsx(_components.span, {
          className: "hljs-keyword",
          children: "function"
        }), " ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "createSignal"
        }), "(", jsx(_components.span, {
          className: "hljs-params",
          children: "value"
        }), ") {\n  ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "const"
        }), " subscribers = ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "new"
        }), " ", jsx(_components.span, {
          className: "hljs-title class_",
          children: "Set"
        }), "();\n\n  ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "const"
        }), " ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "read"
        }), " = (", jsx(_components.span, {
          className: "hljs-params"
        }), ") => {\n    ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "const"
        }), " listener = ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "getCurrentListener"
        }), "();\n    ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "if"
        }), " (listener) subscribers.", jsx(_components.span, {
          className: "hljs-title function_",
          children: "add"
        }), "(listener);\n    ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "return"
        }), " value;\n  };\n\n  ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "const"
        }), " ", jsx(_components.span, {
          className: "hljs-title function_",
          children: "write"
        }), " = nextValue => {\n    value = nextValue;\n    ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "for"
        }), " (", jsx(_components.span, {
          className: "hljs-keyword",
          children: "const"
        }), " sub ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "of"
        }), " subscribers) sub.", jsx(_components.span, {
          className: "hljs-title function_",
          children: "run"
        }), "();\n  };\n\n  ", jsx(_components.span, {
          className: "hljs-keyword",
          children: "return"
        }), " [read, write];\n}\n"]
      })
    }), "\n", jsx(_components.p, {
      children: "现在，每当我们更新信号时，我们就知道要重新运行哪些 Effect。简单而有效。实际的实现要复杂得多，但这就是内部实现的思路。"
    }), "\n", jsx(_components.p, {
      children: "想要更详细地了解响应性的工作原理，下面有些有用的文章："
    }), "\n", jsx(_components.p, {
      children: jsx(_components.a, {
        href: "https://dev.to/ryansolid/a-hands-on-introduction-to-fine-grained-reactivity-3ndf",
        children: "A Hands-on Introduction to Fine-Grained Reactivity"
      })
    }), "\n", jsx(_components.p, {
      children: jsx(_components.a, {
        href: "https://dev.to/ryansolid/building-a-reactive-library-from-scratch-1i0p",
        children: "Building a Reactive Library from Scratch"
      })
    }), "\n", jsx(_components.p, {
      children: jsx(_components.a, {
        href: "https://indepth.dev/posts/1289/solidjs-reactivity-to-rendering",
        children: "SolidJS: Reactivity to Rendering"
      })
    }), "\n", jsxs(_components.h2, {
      id: "注意事项",
      children: [jsx(_components.a, {
        className: "header-anchor",
        href: "#注意事项",
        children: "#"
      }), "注意事项"]
    }), "\n", jsx(_components.p, {
      children: "这种响应式的方法非常强大且灵活。它可以处理不同条件分支下动态执行代码的依赖变更。它还可以在不同的间接层级起作用。在跟踪作用域内执行的任意函数都会被跟踪。"
    }), "\n", jsx(_components.p, {
      children: "但是，我们必须注意一些关键特征和权衡。"
    }), "\n", jsxs(_components.ol, {
      children: ["\n", jsxs(_components.li, {
        children: ["\n", jsx(_components.p, {
          children: "所有响应性都从函数调用中跟踪的，无论是直接的还是隐藏在 getter/proxy 下通过访问属性触发的。这意味着你在何处访问响应式对象的属性很重要。"
        }), "\n"]
      }), "\n", jsxs(_components.li, {
        children: ["\n", jsx(_components.p, {
          children: "流程控制下的组件和回调函数不会跟踪作用域且只执行一次。这意味着在组件中解构或在顶层处理逻辑将不会触发重新执行。你必须从其他响应式 primitive 或 JSX 中访问这些 Signal、Store 和属性，以便重新运行对应部分代码。"
        }), "\n"]
      }), "\n", jsxs(_components.li, {
        children: ["\n", jsx(_components.p, {
          children: "这种方法只能进行同步跟踪。如果你使用 setTimeout 或在的 Effect 中使用异步函数，那么 Solid 并不会跟踪异步执行的代码。"
        }), "\n"]
      }), "\n"]
    })]
  });
}
function MDXContent(props = {}) {
  const {wrapper: MDXLayout} = props.components || ({});
  return MDXLayout ? jsx(MDXLayout, Object.assign({}, props, {
    children: jsx(_createMdxContent, props)
  })) : _createMdxContent(props);
}

export { MDXContent as default, toc };
//# sourceMappingURL=reactivity-ae9e8b3c.js.map
