logo

一种分离React组件内外部方法

Published on

一种分离React组件内外部方法

介绍一种比较新颖的架构方法,实现对React组件内外部方法的分离;

  • 外部方法:提供给组件外部对象调用的方法,在内部永远也不会用到
  • 作用:向外提供了操作此组件的接口;分离了外部方法之后使组件的结构更加清晰

创建项目

bash
复制代码npx create-react-app test-new-architecture --template=typescript
rm -rf src/*
mkdir App && touch index.tsx
cd App && touch index.tsx IApp.tsx IKit.tsx

各个文件作用

  • src/index.tsx : 展示App组件的功能
  • src/App/IApp.tsx : 原始组件
  • src/App/IKit.tsx : 操作原始组件的
  • src/App/index.tsx : 包装组件:包装了元素组件(IApp)及其操作工具(IKit)

文件内容

1. src/App/IApp.tsx

原始组件使用React.forwardRef包装,为其操作提供一个操作接口

tsx
复制代码import React from 'react';

type IRef = React.ForwardedRef<HTMLInputElement>;
const IApp = React.forwardRef((props, ref: IRef) => {
    return (
        <div>
            <label htmlFor="ipt">姓名: </label>
            <input ref={ref} type="text" name="ipt" />
        </div>
    )
})

export default IApp;

2. src/App/index.tsx

包装组件在结构上将原始组件和其操作工具包装在一起;在逻辑上使用ref进行数据通信

tsx
复制代码import React from 'react';
import IApp from './IApp';
import IKit from './IKit';


const App = () => {
  const appRef = React.useRef<any>();
  return (
    <>
      <IApp ref={appRef} />
      <IKit appRef={appRef} />
    </>
  );
}

export default App;

上面的代码中,将原始组件和工具组件进行逻辑联系的是appRef对象

3. src/App/IKit.tsx

工具组件本质上是一个函数式组件,之所以做成jsx,在于保持【原始组件和工具在结构上的统一】,即:

tsx
复制代码    <>
      <IApp ref={appRef} />
      <IKit appRef={appRef} />
    </>

此文件的内容为:

tsx
复制代码import React from 'react';

type IProps = {
    appRef: any;
}
const IKit = (props: IProps) => {
    const {appRef} = props;
    // 设置input的值
    const setText = React.useCallback((text: string) => {
        if (appRef && appRef.current) appRef.current.value = text;
    }, [appRef]);
    // 清空input的值
    const clearText = React.useCallback((text: string) => {
        if (appRef && appRef.current) appRef.current.value = '';
    }, [appRef]);
    // 向外暴露接口
    const appKit = React.useRef(
        {
            setText,
            clearText,
        }
    );

    React.useEffect(
        () => {
            // 挂载到全局中
            (window.top as any)['appKit'] = appKit.current;
        }, []
    )

    return null;
}

export default IKit;

4. src/index.tsx

使用包装组件App的代码如下:

tsx
复制代码import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';

const root = ReactDOM.createRoot(
  document.getElementById('root') as HTMLElement
);
root.render(
  <>
    <App />
  </>
);

测试效果

yarn start启动之后,在控制台分别执行appKit.setText(’hello architecture)appKit.clearText(),可以看到对应的结果。

🤪 您也可以编辑此页: