1
0
Fork 0
Browse Source

vault backup: 2023-02-15 10:33:54

Canvas
YuJian920 2 years ago
parent
commit
c566152bc2
  1. 2
      .obsidian/app.json
  2. 6
      .obsidian/workspace.json
  3. 8
      探索与思考/Zustand 深入探索.canvas

2
.obsidian/app.json

@ -6,5 +6,5 @@ @@ -6,5 +6,5 @@
"attachmentFolderPath": "as",
"showLineNumber": false,
"tabSize": 2,
"useTab": false
"useTab": true
}

6
.obsidian/workspace.json

@ -15,9 +15,9 @@ @@ -15,9 +15,9 @@
"state": {
"file": "探索与思考/Zustand 深入探索.canvas",
"viewState": {
"x": -570.5,
"y": 171,
"zoom": 0,
"x": -445,
"y": 1102.5,
"zoom": -0.3961453739033218,
"snapToGrid": false
}
}

8
探索与思考/Zustand 深入探索.canvas

@ -2,9 +2,13 @@ @@ -2,9 +2,13 @@
"nodes":[
{"id":"70300943eedb4f0d","x":-903,"y":-556,"width":742,"height":219,"type":"text","text":"## create\n从 zustand/react.ts 文件开始,先看看 create 函数的代码实现。\n```tsx\nexport const create = (<T>(createState: StateCreator<T, [], []> | undefined) => {\n\t// creare 函数的核心是 createImpl 函数\n\tcreateState ? createImpl(createState) : createImpl) as Create\n}\n```"},
{"id":"8a1c4d4e899e9dad","x":-903,"y":-248,"width":974,"height":400,"type":"text","text":"## createImpl\n从 createImpl 函数的代码中可以看到,调用了 Object.assign() 函数合并 useBoundStore 和 api 对象,这也是为什么,通过 create 创建返回的 Hook 可以在没有 React 的环境通过访问内部属性的方式执行。\n```tsx\nconst createImpl = <T>(createState: StateCreator<T, [], []>) => {\n\t// 判断 createState 是否函数,是则执行 createStore 函数, 否则直接赋值为 createState\n\tconst api = typeof createState === \"function\" ? createStore(createState) : createState;\n\tconst useBoundStore: any = (selector?: any, equalityFn?: any) => useStore(api, selector, equalityFn);\n\t// 合并 api 到 useBoundStore,实际上就是合并到 useStore 执行之后的返回值,因为函数也是对象\n\tObject.assign(useBoundStore, api);\n\t// 最后将 useBoundStore 返回,完成 store 创建\n\treturn useBoundStore;\n};\n```\ncreateImpl 函数中用到了了两个函数,分别是 createStore 和 useStore"},
{"id":"1c7f002a32cbff2b","x":-903,"y":218,"width":665,"height":464,"type":"text","text":"## useStore\n```tsx\nexport function useStore<TState, StateSlice>(\n\tapi: WithReact<StoreApi<TState>>,\n\tselector: (state: TState) => StateSlice = api.getState as any,\n\tequalityFn?: (a: StateSlice, b: StateSlice) => boolean\n) {\n\t// 自定义一个基于 useSyncExternalStoreWithSelector 的 Hook 并返回\n\tconst slice = useSyncExternalStoreWithSelector(\n\t\tapi.subscribe,\n\t\tapi.getState,\n\t\tapi.getServerState || api.getState,\n\t\tselector,equalityFn\n\t);\n\tuseDebugValue(slice);\n\treturn slice;\n}\n```"}
{"id":"5a13c2f7db73d51f","x":-903,"y":251,"width":838,"height":191,"type":"text","text":"## createStore\n```tsx\nexport const createStore = ((createState) => {\n\t// 判断 createState 是否存在,是则执行 createStoreImpl,否则直接赋值为 createStoreImpl\n\tcreateState ? createStoreImpl(createState) : createStoreImpl) as CreateStore\n}\n```"},
{"id":"1c7f002a32cbff2b","x":135,"y":251,"width":682,"height":505,"type":"text","text":"## useStore\nuseStore 的核心就是 useSyncExternalStoreWithSelector,或者说 zustand 的核心就是这个 Hook\n```tsx\nexport function useStore<TState, StateSlice>(\n\tapi: WithReact<StoreApi<TState>>,\n\tselector: (state: TState) => StateSlice = api.getState as any,\n\tequalityFn?: (a: StateSlice, b: StateSlice) => boolean\n) {\n\t// 自定义一个基于 useSyncExternalStoreWithSelector 的 Hook 并返回\n\tconst slice = useSyncExternalStoreWithSelector(\n\t\tapi.subscribe,\n\t\tapi.getState,\n\t\tapi.getServerState || api.getState,\n\t\tselector,equalityFn\n\t);\n\tuseDebugValue(slice);\n\treturn slice;\n}\n```"},
{"id":"248404eda186b79c","x":-903,"y":545,"width":916,"height":1115,"type":"text","text":"## createStoreImpl\n```tsx\nconst createStoreImpl: CreateStoreImpl = (createState) => {\n type TState = ReturnType<typeof createState>;\n type Listener = (state: TState, prevState: TState) => void;\n let state: TState;\n const listeners: Set<Listener> = new Set();\n\n const setState: StoreApi<TState>[\"setState\"] = (partial, replace) => {\n\t\t// 判断传入的参数是否为函数,是则执行函数后将返回值赋值给为 state\n const nextState =\n typeof partial === \"function\"\n ? (partial as (state: TState) => TState)(state)\n : partial;\n\t\t// 比较 nextState 和 state 是否相同,相同则跳过后续逻辑\n if (!Object.is(nextState, state)) {\n const previousState = state;\n\t\t\t// 根据 replace 参数决定是否覆盖 state\n state =\n replace ?? typeof nextState !== \"object\"\n ? (nextState as TState)\n : Object.assign({}, state, nextState);\n\t\t\t// 触发 listener\n listeners.forEach((listener) => listener(state, previousState));\n }\n };\n\n\t// Get 函数非常简单\n const getState: StoreApi<TState>[\"getState\"] = () => state;\n\n\t// 订阅函数也很简单,listeners 是个 Set,内部存放的将会是 React 防止的回调\n const subscribe: StoreApi<TState>[\"subscribe\"] = (listener) => {\n listeners.add(listener);\n // 返回一个用于取消订阅的函数\n return () => listeners.delete(listener);\n };\n\n\t// 清空 listeners\n const destroy: StoreApi<TState>[\"destroy\"] = () => {\n listeners.clear();\n };\n\n\t// 返回\n const api = { setState, getState, subscribe, destroy };\n state = createState(setState, getState, api);\n return api as any;\n};\n```"}
],
"edges":[
{"id":"1b4e70ab90f0b813","fromNode":"70300943eedb4f0d","fromSide":"bottom","toNode":"8a1c4d4e899e9dad","toSide":"top"}
{"id":"1b4e70ab90f0b813","fromNode":"70300943eedb4f0d","fromSide":"bottom","toNode":"8a1c4d4e899e9dad","toSide":"top"},
{"id":"9bc83a725e3d3891","fromNode":"8a1c4d4e899e9dad","fromSide":"bottom","toNode":"1c7f002a32cbff2b","toSide":"top"},
{"id":"cc9bb810ea8176d6","fromNode":"8a1c4d4e899e9dad","fromSide":"bottom","toNode":"5a13c2f7db73d51f","toSide":"top"}
]
}
Loading…
Cancel
Save