我爱编程

Getting MEAN

2018-03-07  本文已影响0人  hayleyx

getting MEAN

MEAN是一个Javascript平台的现代Web开发框架总称,它是MongoDB + Express +AngularJS + NodeJS 四个框架的第一个字母组合。它与传统LAMP一样是一种全套开发工具的简称。

http://mmbiz.qpic.cn/mmbiz_png/WJgPSvOicEiaDPT2xM0BVYbYL7Kpr1ZfWibfw1uz7KONFKuic7VSYOjVlmRXkiaxRHtQ4T9t6Xibu3icwbClXiaK4rZbFA/640?wx_fmt=png&wxfrom=5&wx_lazy=1

Angular

AngluarJS 1.x的迭代之路

2012年6月,发布了1.0.0版本,集成了angular应用习以为常的诸多概念:

2013年11月,整合了1.1版本功能的1.2版本带来的功能和调整如下:

2014年10月,在1.3版本中,angular宣布不再支持IE8,同时提供了如下新功能:

2015年5月底,Angular团队终于发布了1.4版本,该版本中有超过400条提交,同时优化了文档,修改了100多处bug,以及新增了30多个新特性,其中包括:

2016年2月份,Angular团队又发布了AngularJS1.5版本,该版本的主题就是要和Angular做进一步整合,提供更接近于Angular应用的书写体验,如组件式开发、定义组件指令、生命周期钩子等等。

初生的Angular2

2014年3月份,官方博客就有提及在为新的Angular做设计和开发,所有设计文档都公布在Google云盘中,博客宣称该框架有以下特点:优先为移动应用设计、更快速的变化检测、ES6原生模块化引入、采用状态、支持整合认证授权和缓存视图的新路由、有持久化支持离线使用的存储层,等等。

2014年9月,Angular首次亮相,它的接口和变化在很多AngluarJS1.x开发者中引起了不小的争议,这些变化包括:

这些改变抛弃了AngluarJS1.x这几年来的一些历史包袱,让经验老到的开发团队能够重新设计,结合Angluar1.x的经验教训和外界引入的思潮(React的Virtual DOM方案分离出的渲染来获得性能提升和平台扩展性,向Web Component的标准看齐等等)。它成就了现在具有高性能、高开发效率、丰富扩展能力特点的Angluar。

快速发展的Angular2+

2016年5月,Angluar发布rc1版本,正式进入发行候选阶段。6月中旬发布rc2版本,它的动画模板从底层支持多平台,合入了超过100项社区贡献的代码。一周后rc3发布,把新路由项目合入主代码库中。7月初发布rc4版本,官方对暴露出来的公共接口进行了清理,并且大幅度提升了测试的灵活性和易用性。8月中的rc5版本中,又引入了不少新特性,如路由支持懒加载、组件和服务支持Ahead-of-Time(AoT)编译、新的NgModules封装方式等。在随后的9月,官方先后发布了rc6和rc7版本,其中r6为表单引入更多功能(如validator指令绑定等),同时增强了国际化支持;而rc7主要集中在问题的修复上。

通过7次rc版本的迭代,Angular已经基本趋于稳定:

在AngularJS2发布后大约6个月,下一个大的更新也发布了:Angluar4,或者Angular v4。其主要feature有:

经过14个月的2次重要迭代,Angluar5终于在2017年1月发布了。其承诺更好的代码共享能力,更新的HttpClient,更快的重构,重点是更容易创建渐进式web应用。主要feature有:

Angluar6。。。

Angular核心概念

模块 Modules

组件 Components

模板 Templates

依赖注入 Dependency Injection

服务 Service

数据绑定 Data Binding

指令 Directives

Typescript 介绍

Typescript相当于Javascript的超集,实现了ECMAScript的标准,并在此基础上做了进一步增强,主要有类型校验、接口、装饰器等特性,这使得代码编写更加规范化,也更有利于项目维护。

TS,ES7,ES6,ES5关系
为什么要用TS

从开发效率上看,虽然需要多写一些类型定义代码,但TS在VSCode、WebStorm等IDE下可以做到智能提示,智能感知bug,同时我们项目常用的一些第三方类库框架都有TS类型声明,我们也可以给那些没有TS类型声明的稳定模块写声明文件,这在团队协作项目中可以提升整体的开发效率。

从可维护性上看,长期迭代维护的项目开发和维护的成员会有很多,团队成员水平会有差异,而软件具有熵的特质,长期迭代维护的项目总会遇到可维护性逐渐降低的问题,有了强类型约束和静态检查,以及智能IDE的帮助下,可以降低软件腐化的速度,提升可维护性,且在重构时,强类型和静态类型检查会帮上大忙,甚至有了类型定义,会不经意间增加重构的频率(更安全、放心)。

从线上运行时质量上看,很多bug都是由于一些调用方和被调用方(如组件模块间的协作、接口或函数的调用)的数据格式不匹配引起的,由于TS有编译期的静态检查,让我们的bug尽可能消灭在编译器,加上IDE有智能纠错,编码时就能提前感知bug的存在,我们的线上运行时质量会更为稳定可控。

面向对象编程增强

访问权限控制

接口,组合继承和实现接口的方式使面向对象编程更为灵活、可扩展性更好。

泛型,泛型(模板)在传统面向对象编程语言中是很常见的概念了,在代码逻辑是通用模式化的,参数可以是动态类型的场景下比较有用

类型系统

模块系统增强,支持命名空间,在管理复杂模块的内部时比较有用

TS作者在最近微软Build大会给出的一个图:


image.png

如图,Web和Node平台的JS始终与JS最新规范有一段距离,Web平台的距离更远,TS可以填充这个间隙,让使用者在Web和Node平台都能用上最新的Feature,用上优雅的JS,提高生产力。【Anders Hejlsberg: What's new in TypeScript? 2017】

响应式编程RxJS

在计算领域,响应式编程一种面向数据流和变化传播的编程范式。这意味着可以在编程语言中很方便地表达静态或动态的数据流,而相关的计算模型会自动将变化的值通过数据流进行传播。

在大家熟悉的MVVM中,存在一种M(Model)到V(View)的绑定关系,当model变化时view也随之变化,体现了响应式编程中面向变化传播的思想。

监听一系列事件流并对这一系列事件流进行映射、过滤和合并等处理后,再响应整个事件流的回调,这过程便属于面向数据流的编程。比如ReactiveX的编程范式中,数据流被封装在一个叫作Observable的对象实例中,通过观察者模式,对数据流进行统一的订阅(Subscribe),并在中间插入像filter()这样的操作函数,从而对Obervable所封装的数据进行过滤处理。

实例代码如下:myObservable.filter(fn).subscribe(callback);

通过这个例子可以看到响应式编程清楚地表达了动态的异步数据流,而相关的计算模型也自动地将变化的值通过数据流的方式进行了传播。响应式编程需要描述数据流,而不是单个点的数据变量,我们需要把数据的每个变化汇聚成一个数据流。如果说传统编程方式是基于离散的点,那么响应式编程就是线。

核心概念

在Rx中,最核心的概念就是Observable,应用中产生的异步数据都需要先包装成Observable对象,其作用就是把异步的数据变换成数据流的形式。

Rx在结合了观察者模式的同时,还结合了函数式编程和迭代器模式的思想,其中Operator就是对这两种编程思想的重要体现。在Rx中,每一个Observable对象,都可以通过某个operator对象进行变换、过滤、合并和监听等操作。可以进行链式调用。

Observable作为观察者模式的被观察者,需要一个方法来订阅它,subscribe就是这样一个方法。除此还有

Observer

Subscription

Subject

等等

一个简单的示例:

用户在文本框进行输入时,需要对用户的输入进行实时监听,每当用户输入一个新的字符时,发送请求到服务器。有以下限制条件:

用户输入停顿500ms后才发送到服务器;

保证返回顺序;

let inputSelector = document.querySelector('input');

Rx.Observable.formEvent(inputSelector, 'keyup')

.debounceTime(500)

.switchMap(event => getRecommend(evnet.target.value))

.subscribe(callback);
RxJS和Promis的对比

RxJS的Observable可以通过toPromise()方法把原有的Observable对象转为Promise对象,所以能用Promise的场景RxJS都适用,RxJS是作为Promise的超集存在。

Observable能以流的形式响应多个异步事件,有forkJoin合并请求,Promise的其他一系列操作,RxJS都有对应的解决方案。

Angluar中的RxJS

HTTP服务中的get/post/request等方法会返回一个Observable对象,以及路由中的events,params等也是Observable对象。

addSuit(suit: Suit): Observable<Suit> {
  return this.http.post<Suit>('/api/suit', suit);
}
this.suitService.addSuit(this.addSuitForm.value).subscribe(
  res => {
    this.suits.push(res);
    this.addSuitForm.reset();
    this.toast.setMessage('item added successfully.', 'success');
  },
  error => console.log(error)
);

MongoDB

MongoDB

强大、灵活、易于扩展的通用型数据库。能扩展出非常多的功能,比如二级索引、范围查询、排序、聚合以及地理空间索引。

Mongoose

mongoose是nodeJS提供连接 mongodb的一个库,遵循模板式方法, 能够对你输入的数据进行自动处理。

Mongoose是NodeJS的驱动,不能作为其他语言的驱动。Mongoose有两个特点

  1. 通过关系型数据库的思想来设计非关系型数据库
  2. 基于mongodb驱动,简化操作


    image.png

Mongooose中,有三个比较重要的概念,分别是Schema、Model、Entity。它们的关系是:Schema生成Model,Model创造Document,Model和Document都可对数据库操作造成影响,但Model比Document更具操作性

数据库设计

实体关系如下所示:

实体关系

关系型数据库设计如下:

关系型数据库设计

文档型数据库设计如下:

agentSchema

const agentSchema = new mongoose.Schema({
  name: { type: String, unique: true, trim: true },
  price: Number,
  discountPrice: Number,
}, { timestamps: true });

memberSchema

const memberSchema = new mongoose.Schema({
  bid: { type: String, unique: true, trim: true },
  username: { type: String, unique: true, trim: true },
  name: String,
  _agent: { type: mongoose.Schema.Types.ObjectId, ref: 'Agent' }
}, { timestamps: true });

topicSchema

const memSchema = new mongoose.Schema({
  userId: String,
  username: String,
  name: String,
  donePageCount: Number,
  areaCount: Number,
});

const topicSchema = new mongoose.Schema({
  no: { type: Number, unique: true },
  name: { type: String, unique: true, trim: true },
  shortName: String,
  total: Number,
  assessment: Number,
  passTime: { type: Date },
  note: String,
  mems: [memSchema],
}, { timestamps: true });

orderSchema

const memOSchema = new mongoose.Schema({
  _mem: { type: mongoose.Schema.Types.ObjectId, ref: 'Member' },
  userId: String,
  username: String,
  name: String,
  income: Number,
  areaCount: Number,
  isBelong: Boolean,
});

const agentOSchema = new mongoose.Schema({
  _agent: { type: mongoose.Schema.Types.ObjectId, ref: 'Agent' },
  name: String,
  income: Number,
  areaCount: Number,
});

const orderSchema = new mongoose.Schema({
  name: { type: String, unique: true, trim: true },
  income: Number,
  areaCount: Number,
  memList: [memOSchema],
  agentList: [agentOSchema],
}, { timestamps: true });
上一篇下一篇

猜你喜欢

热点阅读