如何设计和实现一个web app

web app简介html

web app其实不算是什么新鲜的东西,相比于传统的web和传统的app,web app这种web和app相结合的产物有的优势以下:前端

1. 开发上web app更有便捷性,ios开发一上来须要安装一堆东西,android开发也差很少,另外web app的学习成本要比平台客户端开发要低些,至少你不用去招聘ios和android程序员。只要具有基础web开发能力的人均可以比较快上手。react

2. 部署方便,在不少状况下,部署一个单页web app只须要一个index.html页面文件做为容器和一个前端资源打包文件(通常叫bundle.js)便可,而后把index.html放在本身服务器项目路径下,在其中引入bundle.js,至于bundle.js则能够放在CDN上,更新web app就等因而上传并刷新CDN缓存。这样一来前端部署极其简单,基本上不须要SSH到服务器去更换文件,也能够避免本身的服务器传输比较耗费带宽的前端资源文件。android

3. 单页web app若是技术选型得当,开发和维护成本都相对比较低。ios

4. 能够适应更多环境。程序员

凡事都有利弊,web app也有不尽如人意的地方,web app的主要缺点以下:web

1. 性能上不如原生app,这个不用多说,基本是不可改变的事实。ajax

2. 暂时还没想到其余的。编程

前期准备redux

首先要进行技术选型,根据做者的经历,我选择的是react+flux,flux是一种数据流的架构方式,严格来讲它并非某一种特定的实现。比较经常使用的实现有facebook官方的flux实现,还有一些第三方实现(好比redux)。要注意的是,flux的具体实现基本不会影响到咱们的项目开发,具体选择哪一个实现就看你的喜爱了(固然最好不要中途再作改变:D)。

那么就要来简单介绍一下react是什么,react能够说是一个改变前端生态系统的发明,传统web开发中,咱们以页面为单位来设计模块,若是有多个页面都用到了某个功能,好比一个列表,那么就要重复地写HTML和JS实现它,代码抽象程度很低,冗余度很高,也不利于后期维护。react推出了UI组件的概念,让web前端开发人员能够封装UI组件用于复用。

flux这种数据流架构思想其实也不是什么新东西,可是真正在web前端大规模使用也是在开发人员使用react+flux以后的事情。flux制定了一些web前端数据获取和分发的规则,虽然刚开始看上去比较复杂,可是一旦你理解了它的思想,其实很简单,并且对于维护一个web app来讲,react+flux能够说是至关不错的组合。

设计一个web app具体是在设计什么?

刚才谈到了react+flux,其实UI组件的封装和数据流的架构,它们都帮开发人员规定好了,咱们须要作的就是去好好运用它,那么还有什么可设计的呢?

仍是有的,并且很多。从技术角度来讲,web app和ios app、android app这些原生app在技术设计上有不少共通之处:

1. 页面生命周期管理
2. 公共函数的设计
3. 局部/全局事件和通知
4. UI组件API设计
5. 常量定义
6. 网络请求
...

web app也具有一些原生app所没有或不同的特性,例如app路由、JS(ES5/ES6差别)、使用/刷新CDN缓存、前端资源打包、快速部署等。

react+flux是怎么工做的

因为本篇文章并非react和flux的教程,因此只会大体介绍一下它们的工做方式。

下面是官方给出的一个flux工做流程图:

详细版:

简单解释一下flux的工做流程:

在第一张图中,有两种流程:

1. Action->Dispatcher->Store->View

2. View->Action->Dispatcher->Store->View

在Action->Dispatcher->Store->View中,能够经过调用Action中的方法来执行一项操做,这个操做能够是向服务器请求数据,或仅仅在本地改变数据,操做完成后,Action会通知Dispatcher,而后由后者来分派动做和数据。在Store中,事先注册好对各个类型事件的回调函数,当Store接收到Dispatcher分发来的事件和数据时,就执行一些更新操做。另外View能够对Store注册监听器,一但Store中的数据有变化,会当即执行View预先设置好的监听器回调函数,这通常会是一个更新View的操做,这至关于一个发布-订阅模式。

在View->Action->Dispatcher->Store->View中,其实是说指用户和View之间的交互致使数据变动(无论是请求服务器仍是本地数据改变),其余操做和Action->Dispatcher->Store->View基本同样。

光看这些是十分抽象的,若是没有深刻去看一个demo或者本身实现一个项目,确实有点很差理解。我将在后续介绍flux和react。

本篇中react+flux基本介绍到这。下面要谈谈具体设计。

具体设计

一个web app无非就是颠来倒去地作如下几件事:

1. 调用网络API
2. 展现页面
3. 数据本地存储(这里通常指非持久化的那种,这和原生app有所不一样)
4. 接受用户输入并反馈

做为技术人员,咱们首先要明确几点:

1. 明确地知道业务放须要什么。
2. 划分功能模块。
3. 弄清楚各个问题之间的依赖关系,制定模块之间的通讯规范。
4. 适当考虑项目将来走向,对架构设计留有余地。
5. 分析风险。
6. 考虑如何解决依赖关系中最基础的部分,先实现基础模块(或者至少你要先对此有个大体的设计),不断在此基础上完善整个架构。这部分开发人员会花费比较大的精力去作,由于这影响到整个项目将来的几乎全部事情。同时在这个过程当中不断审视架构是否合理,及时调整。
7. 单元测试,性能测试(若是项目须要且有时间的话)。

项目文件结构

好的开发习惯其中一个就是要制定清晰的项目文件结构,而且从始至终保持下去。

适当的文档描述

若是可能的话,适当写一些帮助性的架构文档,用简洁明确的词语传达你想要表达的,让后来的程序员能够快速上手。

思路和方法同一,不搞多元化

在一个项目中,对同一类事情应该有一个统一的处理方法,包括代码风格、变量和方法的命名规范、调用规范、流程规范等,事先制定出来,而且要求全部人都要遵照。

尽可能少的横向依赖,尽可能减小跨层访问,下降模块间耦合度

这部份内容react+flux已经帮咱们作了很大一部分。

对业务方该限制的地方有明确的限制,该灵活的地方要给业务方创造灵活实现的条件

能够经过良好的设计来保证这一点。

接下来会对划分功能模块、模块间通讯规范、解决依赖关系这几个方面进行说明。

功能模块的划分

在react+flux的项目中,不谈具体业务的状况下,有几个大的基础模块是必定要考虑的:

1. 展现模块
2. 网络请求模块
3. 本地存储模块
4. 路由模块
5. 公用模块

1. 展现模块

这是用户能直接看到的东西,咱们用react封装各个UI组件提供出来,也能够引入第三方UI组件,这自己已是一种进步,让咱们能够在web前端“面向组件编程”,所以对UI组件的处理就尤其关键。ES6语法下,咱们能够用extends react.Component来创建一个UI组件,而后在组件“类”中写初始化方法、渲染方法、生命周期函数、事件回调等方法,而后把它做为一个总体提供出去,这里就涉及到UI组件API的设计,UI组件能够接受属性值,这些属性应该尽量的少和命名清晰、简单,保持简洁性颇有必要。另外组件的展现离不开CSS和一些资源文件,做为一种封装,把CSS、图片等资源文件一并放在这个UI组件的文件夹下也是颇有必要的。

2. 网络请求模块

web app网络请求全靠ajax,在和服务器交互时,应该和服务端约定好返回数据的格式,如错误代码的含义、出错信息、详细的数据格式等,而且颇有必要在web app端作一层封装,好比封装出一个request模块,在服务器返回数据后首先解析返回数据,若是出错就报错,成功就执行用户回调函数等。这部分做为整个项目对外的接口应该考虑到全部可能的网络状况:服务器致命错误、普通错误、成功、超时、无网络等。

3. 本地存储模块

这部分主要交给flux处理,咱们须要作的就是设计本地数据的结构,使其尽可能合理并适应多种应用场景。

4.路由模块

react+flux的单页web app通常采用react-router做为路由,这能够省下你很多时间和精力,react-router是一个很是成熟和优秀的路由模块。

5. 公共模块

公共模块通常包括但不只限于:公用函数、helper、常量定义、应用级别的功能(如展现loading框、警告框、确认框这些)。这部分功能也很重要,好比loading框,咱们在发起网络请求时会展现它,数据返回时它会消失,那么这个框的出现就与上面说到的网络模块有关系,警告框和确认框也是经常使用的东西,这些组件均可应该在app层面上进行设计和整合,而不该该放在各个UI组件内部,由于这个是一个app中的通用功能。

模块间通讯规范

在react+flux中,使用一种单向数据流的方式来分发数据,这就让整个数据走向很是清楚,咱们的web app模块间通讯规范就是根据这个单向数据流的思想来的。

解决依赖关系

react+flux中处理依赖关系时,用的比较多的方式无非3种:显式引入、基于事件(发布-订阅模式)、回调函数。

在要向模块中引入其余模块时(import),使用显式引入,这种依赖关系最强也最明显。若是是依赖关系没有那么强,能够考虑用后面两种,这有助于代码的简介和模块解耦。

基于事件(发布-订阅模式),举个简单的例子,flux中当Store中的数据变化时,要通知相对应的View更新页面,典型的处理方式是让Store成为一个EventEmitter,同时View对该Store addChangeListener,即成为它的订阅者,当Store改变时会自动调用该View的监听回调,让View更新界面。

基于回调函数,有一个很是典型的用例,在设计通用的警告框和确认框组件时,有时咱们须要在用户点击“肯定”和“取消”按钮时作一些事情,固然也可能什么也不作。这时候咱们不要忘了JS中函数是一等公民这件事,咱们能够把事件处理函数传递给警告框和确认框组件,这样就很巧妙的解决了跨组件、跨模块通讯而不会使模块过于耦合了。

相关文章
相关标签/搜索