React之Arco组件:Message

发布于:2023-01-01 ⋅ 阅读:(354) ⋅ 点赞:(0)

前言

本次阅读源码分析十分艰难,但也学习到不少知识,可能有不少错误希望指正。

请注意,本文代码经过大量删减,源码请看相关连接

控制消息最大条数


试想一下,在页面的上端不停的出现提示,但是最多只能显示5条,我们当然可以简单的不停的生成,然后控制他们的生命周期,但是我们无法确定到底有几条数据。

类似游戏中的对象池的概念,但也可以通过一个变量来存储所有消息对象就行了。

// Message.tsx

interface BaseNoticeState {
  notices: { [key: string]: any }[];
  position?: 'top' | 'bottom';
}

let messageInstance: Record<'top' | 'bottom',BaseNoticeState> | {} = {};
  • 也就是说,我们顶部或者底部各有两个BaseNoticeState,管理各自的state
  • messageInstance这个变量在全局是唯一的,即使Message被各个其他组件引用

消息组件


正向继承 & HOC & HOOK

  • 正向继承就是父组件给子组件提供了一些公共方法,然后子组件也就用了这些功能,这里父组件似乎一般不具备渲染功能
class SignUpDialog extends SignUpDialogFather{}
  • HOC也就是高阶组件,你可以将组件塞到高阶组件里面去,然后给这个组件加上额外的功能,再渲染出这个子组件
const EnhancedComponent = higherOrderComponent(WrappedComponent);
  • Hook是完全将逻辑和视图完全剥离开来,页面继承也直接嵌套就行,逻辑复用直接用hook代替
const [count, setCount] = useState(0);

react-transition-group

这似乎是个提供动画的依赖,是react官方开发的

// Message.tsx 
class Message extends BaseNotification {
	// 这个先不管,最后会用到
	static success: (config: MessageProps | string) => MessageType;
  static info: (config: MessageProps | string) => MessageType;
	...
    render() {
			// 这里拿到了state值,也就是因为BaseNotification 提供了
        const { notices, position } = this.state;
        return (
          <div>
            <TransitionGroup component={null}>
              {notices.map((notice) => (
                <CSSTransition
                  key={notice.id}
                  timeout={{
                    enter: 100,
                    exit: 300,
                  }}
                >
									// Notice提供具体的功能
                  <Notice
                    {...notice}
                    onClose={this.remove}
                    noticeType="message"
                  />
                </CSSTransition>
              ))}
            </TransitionGroup>
          </div>
        );
      }
}

// BaseNotification.tsx
// 继承的父组件
class BaseNotice extends Component<any, BaseNoticeState> {
  constructor(props) {
    super(props);

    this.state = {
      notices: [],
      position: 'topRight',
    };
    this.remove = this.remove.bind(this);
  }

  add = (noticeProps) => {
   
  };
}

添加实例方法


动态创建div以及渲染组件到div内部

  1. 通过原生方法createElement创建div
  2. 通过ReactDOM.createRoot(div as HTMLElement).render()渲染进去

Ref

下面这句话很重要,可能是字节大佬说的,说不定就是他写的arco

Props 是单向数据流,以 “声明式” 渲染组件;Ref 则是以 “命令式” 操作组件

那么我们这利用ref的回调方法,也就是说整个流程是这样

  1. 我们有个接受实例的方法
  2. 我们将改方法传入Message的ref属性
  3. Message组件在其实例化时会自动调用这个方法,并且把自身实例传入进去
  4. 方法内部拿到了实例
// Message.tsx

function addInstance(noticeProps:MessageProps) {
  const div = document.createElement('div');
    (container || document.body).appendChild(div);

    ReactDOM.createRoot(div as HTMLElement).render(
      <Message
      transitionClassNames={transitionClassNames}
      // 这里利用的是ref可以传入回调方法,instance即是Message组件的实例在,Message实例化后,会执行改方法
      ref={(instance) => {
        // 当方法执行,我们拿到实例,注入到messageInstance中
        messageInstance[position] = instance;
        
        // 调用Message实例add方法,也就是把noticeProps这个东西传入到state的Notices中
        // 注意这个方法继承BaseNotification
        id = messageInstance[position].add(_noticeProps);
      }}
    />
    )
}

调用Message


为类的静态属性注入方法

在Message内部有各个类型的静态属性,当我们把addInstance这个方法注入到其中,在其他页面引入后,便可直接调用了

// Message.tsx
const messageTypes = ['info', 'success', 'error', 'warning', 'loading', 'normal'];

messageTypes.forEach((type) => {
  Message[type] = (noticeProps: MessageProps | string) => {
    const props = typeof noticeProps === 'string' ? { content: noticeProps } : noticeProps;
    return addInstance({
      ...props,
      type,
    });
  };
});

// App.tsx
// 直接调用
Message.success({ duration: 2000 ,content: '你好'})

其他小知识


数组转联合类型

// 通过这种方式将数组转换成联合类型
const messageTypes = ['info', 'success', 'error', 'warning', 'loading', 'normal']  as const;
type MessageTypes = typeof messageTypes[number];

相关链接


组合 vs 继承 – React​zh-hans.reactjs.org/docs/composition-vs-inheritance.html正在上传…重新上传取消

高阶组件 – React​zh-hans.reactjs.org/docs/higher-order-components.html正在上传…重新上传取消

财神:React 高阶组件 -- 继承的用法3 赞同 · 4 评论文章

React Transition Group (reactcommunity.org)​reactcommunity.org/react-transition-group/

秦书羽:前端进阶系列——理解 React Ref11 赞同 · 2 评论文章正在上传…重新上传取消

官方源码


Arco Design - 企业级产品的完整设计和开发解决方案​arco.design/react/components/message

arco-design/index.tsx at main · arco-design/arco-design​github.com/arco-design/arco-design/blob/main/compo

 

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到