React 在 Coding WebIDE 中的应用实践

大家下午好,非常荣幸能够在这里和大家分享一些关于 React 的应用实践。

我叫刘辉,来自 Coding.net。

Coding 的一个口号就是云端开发嘛,所以我们有一个 WebIDE 的项目,大概就是这样子的,他包括 IDE 最基础的一些功能,比如文件树,编辑器,Terminal 等等,另外还有一个比较有特色的功能,就是云端开发环境的切换和共享,这可能是他相对于本地 IDE 最大的一个优势,大家有兴趣可以去尝试一下。

在这里输入图片描述

我今天要分享的主题大概会有三个方面的内容:React、Flux,以及最后还有一些测试相关的实践。

在这里输入图片描述

React

关于 React,相信大家都有所了解,就不多做介绍了,我们知道 React 的一个基础就是组件。

在这里输入图片描述

如果我们用组件的视角来看 WebIDE,主体大概就是这么一些组件,所以我们要做的就是实现这些组件,并且把这些组件组装起来。

在这里输入图片描述

其实 WebIDE 本身就是一个组件,他是由各种小的组件像堆积木一样堆其来的,我们可以看一下在 React 里面如何组装这些组件。首先我们定义这些组件,比如 Menu,文件树等等,然后有个 App 组件,他就是 WebIDE 最外层的一个组件,组件都会有一个 render 方法来生成组件的 DOM 结构,我们看到中间这段奇怪的 HTML,就是 JSX。JSX 可能是前端最开始接触 React 最不能接受的东西,但是我觉得他是一种非常聪明的做法,他打破了我们之前一直坚持的逻辑和表现层分离的原则,直接将 HTML 嵌入到 JS 里面,一个独立的组件就应该包含自己的 HTML,我们可以看到这种组件化用起来是很自然的。

在这里输入图片描述

Flux

这些组件组装完了之后,彼此之间需要通信,这时候就要用到 Flux。Flux 他不是另一个框架或者类库,他只是一种架构方式,类似 MVC 的一个东西。

在这里输入图片描述

Flux 他把一个应用分成 3 个部分,Store 数据层,View UI 层,在 React 里面 View 就是组件,然后是 Action 动作,View 可以调用 Action,然后通过一个 dispatcher 分发给 Store,Store 会注册感兴趣的 Action 去修改数据,然后通知 View 刷新 UI。

在这里输入图片描述

在一个复杂的应用里面,最终就会形成这么一个所谓的单向数据流,整个数据流是透明的,可预测的,所以 Flux 可以让一个复杂的应用变得很清晰,不会让人觉得是一团乱麻。

在这里输入图片描述

举个栗子,可能会说明得更清楚一点。IDE 有一个常见的功能就是要能够对编辑器进行配置,所以我们有一个 SettingModal 弹窗来配置这些选项。

在这里输入图片描述

然后我们可能会打开多个 Editor,当配置更改的时候,所有的 Editor 都要更新自己的配置。

在这里输入图片描述

我们可以看一下 Flux 里面怎么做,我们会有一个 SettingStore 来保存这些配置选项,SettingModal 和 Editor 会从 SettingStore 获取配置选项,然后当我们点击弹窗里面的保存按钮的时候会调用一个 SettingActions 里面的比如一个 save 方法,这个 Action 会触发 Store 的更改,然后通知到组件更新,这样 SettingModal 和所有的 Editor 都会更新到。所以 Store 作为数据唯一可信的来源,这点很重要,可以大大简化数据的维护。

在这里输入图片描述

这是另一个 Flux 简化我们开发的栗子,我们希望支持插件,那实现插件的一个前提条件就是插件能够调用到核心暴露的接口,因为 Flux 所有的交互都是基于 Action 的,所以我们在全局自定义了一个 require 方法,就可以把 Action 暴露给外部调用了,所以就这么几行代码就打通了插件和核心之间的调用。

在这里输入图片描述

Flux 中的异步请求处理

接下来讲一下 Flux 里面如何处理异步请求,这也是我们最常遇到并且比较纠结的一个问题。我们的处理方式是把异步请求分成两种类型:读和写。

在这里输入图片描述

首先关于读取数据的请求直接放在 Store 里面,组件可以调用 Store 里面的方法获取这个数据,这个方法总是返回一个 Promise,然后我们会有一个 API 层,去处理所有的异步请求,Store 里面的这个方法就是通过 API 层去服务器端获取数据,最后可能会有一些错误处理的 Action。将读取数据请求放在 Store 里面的一个好处就是将数据管理集中到 Store 一个地方了,可以方便的做数据缓存,Component 并不需要知道数据是从哪里来的。然后额外的 API 层就可以去做请求队列,剔除重复请求等等这些事情。

在这里输入图片描述

然后写入请求,还是按照 Flux 的惯例,用 Action 来调用,同样我们通过 API 层去发送这个写入请求。最后可能会有一些错误处理的 Action。

在这里输入图片描述

测试实例

最后关于测试,以前我们总是说要写可测试的 JS 代码,但很少有前端去做,因为他很难,特别是我们以前以 DOM 交互为中心的开发方式就很难写测试。

在这里输入图片描述

要写出可测试的 JS 代码一个前提条件就是代码之间是解藕的,Flux 天生就是解藕的。

在这里输入图片描述

所以测试一个 Flux 应用会相对比较简单,我们只需要针对 Store 和 Component 写测试就可以了,理论上来讲 Store 包含了所有的数据逻辑,Component 包含了所有的交互。

在这里输入图片描述

首先是工具的选择,这是我们选择测试方案,karma 加 mocha,karma 作为跑测试的容器,mocha 作为测试框架,sinon 作为 mock 工具,chai 作为断言库,另外还有一个 rewire 用来做依赖注入……前端的工具真的是太丧心病狂了。虽然我个人比较喜欢这种一个工具只做一件事情并且把他做好,但是要整合这些工具还是一件很繁琐的事件,具体怎么配置,这里就不细讲了,不同的项目可能都有些不一样,这里有一个样板,大家有需要可以去参考一下。

在这里输入图片描述

接下来看一下怎么写测试,首先是 Store 的测试,主要解决两个问题,一个是在每个测试之前保持 Store 数据的一致性,另外一个就是伪造 Action 触发 Store 的更改。

在这里输入图片描述

首先我们引入 rewire 用来做注入数据,然后通过 spy 拿到 dispacher 注册的回调函数,用来调用 Action,在每个测试之前重置 Store 的数据,然后用 callback 调用伪造的 Action 触发 Store 的更改,测试 Store 的数据逻辑。

在这里输入图片描述

然后是关于异步请求的测试,这是一篇关于 JS 异步测试的文章,里面提到一条原则,就是尽可能减少写真正的异步测试,所谓真正的异步测试就是通过回调函数来写的测试。除非我们写一些底层的类库,比如一个 ajax 的类库,才需要去做这种真正的异步测试,但是大部分时候我们都是应用层面调用异步请求,完全可以使用同步的方式去测试。

在这里输入图片描述

要做到这点,所以我们会有一个 API 层去隔离异步请求,然后第二点就是总是用 Promise。

在这里输入图片描述

我们可以看一下具体如何去隔离异步请求,首先我们引入 API 层,然后 stub API 某个异步请求的方法,然后 Store 里面获取数据的函数通过这个方法去获取数据,通过 Promise 我们就可以很容易去伪造这个异步请求返回的数据,这样就可以测试这个异步请求了。如果我们要测试错误处理也很容易,直接用 Promise reject 一个错误就可以模拟。

在这里输入图片描述

最后关于组件的测试,就是测试两个方面,一个是验证 DOM 结构,另一个就是模拟 DOM 事件。

在这里输入图片描述

我们可以通过具体代码来看一下,React 提供了一个插件 TestUtils 可以方便的将组件渲染到 document,然后我们就可以针对这个组件的 DOM 元素测试 DOM 结构,模拟 DOM 事件也很简单 TestUtils 下面的 Simulate 包含了所有标准的 DOM 事件,直接调用就可以了,然后我们就可以测试对应的交互逻辑了。

在这里输入图片描述

今天讲的内容只是使用 React 构建一个应用最基本的一些内容,React 还有很多其他可以尝试的东西,比如 immutable.js,服务器端渲染,React styling 是想解决组件里面嵌入 CSS 问题,另外还有 Relay 和 GraphQL 这类不明觉厉的东西等等。所以 React 开启了很多新的思路,说他引领了前端一个新的时代也不为过,推荐大家没有尝试过的都去尝试一下。

在这里输入图片描述

谢谢大家。


转载请注明来源:https://blog.coding.net/blog/React-practice-Coding-WebIDE

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值