From 21adc57d48f543db3abe58aee086ed1221df59bf Mon Sep 17 00:00:00 2001 From: yetao Date: Thu, 31 Oct 2024 13:24:53 +0800 Subject: [PATCH] =?UTF-8?q?refactor=F0=9F=8E=A8:=20=20(=E9=98=85=E8=AF=BB?= =?UTF-8?q?=E4=BB=A3=E7=A0=81)=EF=BC=9Aredux.ts=E5=A2=9E=E5=8A=A0=E6=B3=A8?= =?UTF-8?q?=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- webview/src/redux.ts | 135 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 133 insertions(+), 2 deletions(-) diff --git a/webview/src/redux.ts b/webview/src/redux.ts index eaf4be8..5ff33ff 100644 --- a/webview/src/redux.ts +++ b/webview/src/redux.ts @@ -1,70 +1,201 @@ +// 导入 React 库,用于构建组件 import * as React from 'react'; +// 导入 react-redux 库中的 connect 函数,用于连接 React 组件和 Redux 存储 import { connect as realConnect } from 'react-redux'; +// 导入 redux 库中的 combineReducers、createStore 和 Dispatch 函数,用于管理 Redux 状态 import { combineReducers, createStore, Dispatch } from 'redux'; +// 从 './data' 模块中导入所有内容,可能包括 reducer、action 等 import * as data from './data'; +// 从 './view' 模块中导入所有内容,可能包括 reducer、action 等 import * as view from './view'; +// 从 './vscode' 模块中导入 API 对象,用于与 VSCode 环境交互 import { API } from './vscode'; +// 使用 redux 的 combineReducers 函数将多个 reducer 合并为一个 const reducers = combineReducers({ + // 引入 data 模块的 reducer,用于处理数据相关的状态 data: data.reducer, + // 引入 view 模块的 reducer,用于处理视图相关的状态 view: view.reducer, }); +/** + * 定义应用程序的状态 + * @interface State + * @property {data.IState} data - 数据相关的状态 + * @property {view.IState} view - 视图相关的状态 + */ export interface State { + // 数据相关的状态 data: data.IState; + // 视图相关的状态 view: view.IState; } +/** + * 定义一个联合类型,包含所有可能的 action + * @type Action + * @property {data.actions.Action} data - 数据相关的 action + * @property {view.actions.Action} view - 视图相关的 action + */ export type Action = data.actions.Action | view.actions.Action; +/** + * 定义应用程序的默认状态 + * @const DEFAULT_STATE + * @type {State} + * @property {data.DEFAULT_STATE} data - 数据相关的默认状态 + * @property {view.DEFAULT_STATE} view - 视图相关的默认状态 + */ export const DEFAULT_STATE: State = { + // 数据相关的默认状态 data: data.DEFAULT_STATE, + // 视图相关的默认状态 view: view.DEFAULT_STATE, }; +/** + * 创建一个 Redux store,用于存储应用程序的状态 + * @const STORE + * @type {Store} + * @param {Reducer} reducers - 应用程序的 reducer,用于处理状态的变化 + * @param {State} preloadedState - 初始状态,如果存在则从 API 中获取,否则使用默认状态 + * @param {Enhancer} enhancer - 可选的 store enhancer,用于增强 store 的功能 + */ export const STORE = createStore(reducers, API.getState() || DEFAULT_STATE, undefined); + +/** + * 初始化 data 模块的 store + * @function initStore + * @param {Store} store - 要初始化的 store + */ data.initStore(STORE); + +/** + * 初始化 view 模块的 store + * @function initStore + * @param {Store} store - 要初始化的 store + */ view.initStore(STORE); +// 保存原始的 dispatch 方法,以便在重写的 dispatch 方法中调用 const oldDispatch = STORE.dispatch.bind(STORE); + +// 重写 STORE 的 dispatch 方法 STORE.dispatch = (action) => { + // 打印日志,显示当前正在分发的 action console.log('STORE.dispatch', action); + // 调用原始的 dispatch 方法,分发 action oldDispatch(action); + // 返回 action,以便在调用 dispatch 方法后可以继续处理 action return action; }; +// 订阅 STORE 的变化,当 STORE 发生变化时,调用 API.setState 方法将当前状态同步到 VSCode 的 API 中 STORE.subscribe(() => API.setState(STORE.getState())); +// 当导航事件发生时,向 VSCode 发送一个消息,消息类型为 'navigated',内容包含当前的视图状态 API.postMessage({ type: 'navigated', view: STORE.getState().view.view }); // Makes debugging easier (and this is inside our WebView context anyway) +// 将 STORE 挂载到全局 window 对象上,以便在其他地方访问 (window as any).STORE = STORE; +/** + * 获取组件的属性类型 + * @typeparam C - 组件类型,可以是类组件或函数组件 + * @returns 组件的属性类型 + */ type GetComponentProps = C extends React.ComponentClass ? P : (C extends React.FunctionComponent ? P2 : {}); + +/** + * 获取组件的状态类型 + * @typeparam C - 组件类型,可以是类组件或函数组件 + * @returns 组件的状态类型,如果组件没有状态,则返回空对象 + */ type GetComponentState = C extends React.ComponentClass ? S : {}; +/** + * 从类型 T 中排除指定的键 K + * @typeparam T - 要排除键的类型 + * @typeparam K - 要排除的键 + * @returns 一个新的类型,包含 T 中除了 K 之外的所有键 + */ type Omit = Pick>; +/** + * 获取组件的自有属性 + * @typeparam C - 组件类型,可以是类组件或函数组件 + * @typeparam P - 要排除的属性 + * @returns 组件的自有属性类型,即排除了 P 中的属性 + */ type OwnProps | React.FunctionComponent), P> = Omit, keyof P>; +/** + * ConnectReturn 接口定义了 connect 函数的返回类型 + * @interface ConnectReturn + * @typeparam C - 组件类型,可以是类组件或函数组件 + */ interface ConnectReturn | React.FunctionComponent)> { + /** + * 第一个重载签名:接受一个函数 stateToProps,返回一个新的组件类 + * @template TStateProps, TState + * @param { (state: TState, ownProps: OwnProps) => TStateProps } stateToProps - 用于从 Redux 状态中提取 props 的函数 + * @returns { React.ComponentClass, keyof TStateProps>, GetComponentState> } - 返回一个新的组件类,该组件类的 props 是从 stateToProps 函数中提取的,并且排除了 TStateProps 中的键 + */ ( stateToProps: (state: TState, ownProps: OwnProps) => TStateProps ): React.ComponentClass, keyof TStateProps>, GetComponentState>; + + /** + * 第二个重载签名:接受两个函数 stateToProps 和 dispatchToProps,返回一个新的组件类 + * @template TStateProps, TDispatchProps, TState + * @param { (state: TState, ownProps: Omit, keyof (TStateProps & TDispatchProps)>) => TStateProps } stateToProps - 用于从 Redux 状态中提取 props 的函数 + * @param { (dispatch: Dispatch, ownProps: Omit, keyof TStateProps & TDispatchProps>) => TDispatchProps } dispatchToProps - 用于从 Redux dispatch 函数中提取 props 的函数 + * @returns { React.ComponentClass, keyof (TStateProps & TDispatchProps)>, GetComponentState> } - 返回一个新的组件类,该组件类的 props 是从 stateToProps 和 dispatchToProps 函数中提取的,并且排除了 TStateProps 和 TDispatchProps 中的键 + */ ( stateToProps: (state: TState, ownProps: Omit, keyof (TStateProps & TDispatchProps)>) => TStateProps, dispatchToProps: (dispatch: Dispatch, ownProps: Omit, keyof TStateProps & TDispatchProps>) => TDispatchProps, ): React.ComponentClass, keyof (TStateProps & TDispatchProps)>, GetComponentState>; } + +/** + * 连接 React 组件到 Redux 存储的高阶组件 + * @function connect + * @template TComponent - 要连接的组件类型,可以是类组件或函数组件 + * @param {TComponent} component - 要连接的组件 + * @returns {ConnectReturn} - 返回一个新的组件,该组件已经连接到 Redux 存储 + * @remarks + * 这个函数是一个高阶组件,它接受一个组件作为参数,并返回一个新的组件,这个新的组件已经连接到 Redux 存储。 + * 它可以接受两个参数:stateToProps 和 dispatchToProps。stateToProps 是一个函数,它接受 Redux 存储的状态作为参数,并返回一个对象,这个对象将被用作新组件的 props。 + * dispatchToProps 是一个函数,它接受 Redux 的 dispatch 函数作为参数,并返回一个对象,这个对象将被用作新组件的 props。 + * 如果只提供了 stateToProps 参数,那么 dispatchToProps 将默认使用 Redux 的 dispatch 函数。 + */ export function connect | React.FunctionComponent)>(component: TComponent): ConnectReturn { return (stateToProps: any, dispatchToProps?: any) => realConnect(stateToProps, dispatchToProps)(component) as any; } -export function pickProperties(obj: T, ...keys: K[]): Pick { +/** + * 从对象中提取指定的属性 + * @template T - 对象的类型 + * @template K - 要提取的属性的键的类型,必须是 T 的键的子集 + * @param {T} obj - 要从中提取属性的对象 + * @param {...K} keys - 要提取的属性的键 + * @returns {Pick} - 一个新的对象,包含了从原对象中提取的指定属性 + * @remarks + * 这个函数接受一个对象和一个或多个键作为参数,并返回一个新的对象,该对象只包含传入的键所对应的属性。 + * 如果传入的键不存在于原对象中,则该键对应的属性值在新对象中为 undefined。 + */ +export function pickProperties(obj: T,...keys: K[]): Pick { + // 创建一个新的对象,用于存储从原对象中提取的属性 const res: Pick = {} as any; + // 遍历传入的键列表 for (const key of keys) { + // 将原对象中对应键的值赋给新对象中的对应键 res[key] = obj[key]; } + // 返回新对象,其中包含了从原对象中提取的指定属性 return res; -} +} \ No newline at end of file