述职

述职分享 - 刘睿敏

主要工作成果

DDP:react/redux-thunk/koa(ssr)

  • 是什么:需求管理平台(需求的创建 -> 评审 -> 开发
  • 用户:产品/运营/技术/大佬 everbody
  • 价值:

    • 解决需求来源不统一(lean/wiki/运营直接d-chat等等方式提需求等
    • 出现问题,快速准确定责(无法快速且准确的确定需求来源方和需求owner
  • http://ddp-test.intra.xiaojuk...

把脉:react/typescript/mobx

  • 是什么:滴滴云端诊断分析服务平台,帮助快速发现与定位问题
  • 用户:客服/RD
  • 价值:其他业务方把原始的trace数据接入到把脉,把脉在原始数据的基础上提供界面,帮助快速发现与定位问题
  • http://bamai.xiaojukeji.com/n...

主要工作分享:ddp前端配置化方案

配置化背景:

一开始ddp是一个老老实实的应用,只有网约车一条业务线在用,很多逻辑都硬编码在前端,随后ERP想要接入,接入erp时,就发现很多问题!!!

1.业务线有不同的业务需求
解决方案:前端硬编码/大量的if...else...逻辑,造成代码冗余,难以维护,可读性查
不同业务方向下,又有不用角色, 对应的文案/字段/字段类型都不同
const isERP = [3,4].includes(Number(sponsor))
const options = detail.type == 1?STATUS[5]:STATUS[detail.sponsor];
tatusOptions={options || STATUS[2] || []}
2.前端硬编码,牵一发动全身,接入业务线时间长

预期收益
  • 减少硬编码逻辑,通过增强后台配置化能力,实现对业务线级别需求包含字段以及需求流转过程的动态配置能力
  • 减少新业务线接入望岳系统的时间,新业务线接入时间由2周缩短至2天(一期功能目标)

设计原则:

1.数据驱动页面

写通用的配置化逻辑,在加载页面的时候拉取配置数据,动态生成页面,前端不再关注业务逻辑的流转,只拿到后端JSON数据做渲染,简化逻辑
原工作流实现,前端有配置json,硬编码在前端,转移到后端存入MongoDB配置库中

2.组件化

组件父子化:便于定制和扩展
  • 父组件本质是一个容器组件(container)。在内部定义了渲染出子组件排列的规则。同时也承担了通用(子组件的表现)的规则(比如子组件布局 & 数据处理 & 报错 & 提示信息处理等)
  • 在父组件中需要定义component Map映射,实现一套组件映射关系。
  • 子组件是纯component, 没有额外的适配逻辑。便于普通react组件接入
组件和页面剥离,功能解耦
  • 可复用的基础组件库:快速编辑组件库/表单组件库(相似的props)
  • 业务强耦合的业务组件渲染函数(内聚功能,只暴露数据源和更新接口)
布局:
整个页面被认为是一个树形结构,由不同的组件构成
组件由组件构成,直到最小的组件,这一类的组件逻辑上将无法再被拆分

如图:
FieldSection - 动态通用组件 - 相似的props/更新获取接口一致

subModules - 业务组件渲染块 - 不同的props/fetch不同的接口得到数据

组件样式:

  • 绝不配置任何有关样式的信息(同一种类型的组件,都具有同样的样式)

    • 配置样式会带来配置的急剧复杂化(一个组件的样式,由很多控制选项,而且不同组件之间还会相互影响)
    • 配置样式导致样式修改调整都十分困难(相互影响)
  • 问题:有两个组件,它们除了样式不同以外,都一样,那么怎么办?(实例:标题和内容的快速编辑)

    • 定义一种新的组件?组件类型膨胀的问题/无法复用,除了bug修两个地方
    • 借鉴antd,配置每个组件的主题(normal, bold, red)/ (big/small/middle)

发布订阅模式 - 组件解耦

A 模块使用了 data1, B 模块使用了 data2;A B 模块可以修改对应的 data;这两份 data 结构上不同,但是存在业务上的联系: 当 data1 更新后需要 data2 更新;data2 更新同样需要 data1 同步;对应后端的两个不同的 API。

我们整理一下

  • A B 使用两份存在联系的 data
  • 其中一个更新需要另一个更新
  • 两份 data 对应不同的 API 接口
  • A B 对应两个不同的 tab 且可能同时存在

方案一

  • 当其中B数据因操作发生更新时,在页面/action中刷新A模块的数据
class B extends React.Component {
    handleUpdateData = () => {
        const { dispatch, queryA, queryB } = props
        dispatch(queryB())
        dispatch(queryA())
    }
}
  • 缺点:

    在模块 B 内调用模块 A 的更新逻辑;但这样逻辑就耦合了,我在模块 A 调用模块 B 方法 在模块 B 调用模块 A 的方法;但很有可能这两个模块是没有其他交互的。这违反了低耦合高内聚的原则
    而且书写 redux 的一个原则就是 不要调用(dispatch)其他模块的 action

方案二:发布-订阅事件系统pubsub.js

模块B - 使用PubSub.publish发送事件

模块A - 订阅事件type

通过事件系统做到了两个模块之间的解耦,作为事件发布方只管发布自己的事件。两个模块在事件系统唯一的联系就是事先定义好事件的type

class B extends React.Component {
    handleUpdateData = () => {
        PubSub.publish('queryA',null);
    }
}

class A extends React.Component {
    componentDidMount(){
      this.pubsub_token = PubSub.subscribe('queryA', function (topic,message) {
        dispatch(queryA())
      }.bind(this));
    }
    componentWillUnmount(){
      PubSub.unsubscribe(this.pubsub_token);
    }
}

限制

  • 不支持复杂布局
  • 不支持复杂交互

优点

  • 释放前端资源,终于不用切砖了!
  • 节省测试资源,接入新的业务的时候,基本上就是看看配置对不对

你可能感兴趣的:(javascript)