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

一种分离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(),可以看到对应的结果。

相关推荐
FanetheDivine10 小时前
ts中如何描述一个复杂函数的类型
前端·typescript
刺客_Andy11 小时前
React 第四十六节 Router中useInRouterContext的使用详细介绍及注意事项
前端·javascript·react.js
刺客_Andy11 小时前
React 第四十四节Router中 usefetcher的使用详解及注意事项
前端·javascript·react.js
刺客_Andy11 小时前
React 第四十五节 Router 中 useHref() Hook的使用详解及注意事项
前端·javascript·react.js
需要兼职养活自己12 小时前
react 之redux
前端·react.js·redux
ら陈佚晨12 小时前
React 18 的核心设计理念:并发渲染
前端·javascript·react.js·前端框架·fiber
南城巷陌16 小时前
错误边界:用componentDidCatch筑起React崩溃防火墙
前端·react.js·前端框架
Dcc18 小时前
构建可维护的 React 应用:系统化思考 State 的分类与管理
前端·react.js
进阶的鱼18 小时前
React+ts+vite脚手架搭建(五)【规范篇】
前端·react.js·vite
Gazer_S20 小时前
【理解React Hooks与JavaScript类型系统】
前端·javascript·react.js