您的位置:首页 > 数据库 > Mongodb

单页WEB应用(九),终篇-总结和发布

2017-03-15 18:10 246 查看

前言

本篇是该书系列最后一篇,本书所有涉及的功能和其中所涉及的知识点,基本已经学习完成。

大体上有以下几个部分

简单的页面布局

第一个部分首先是进行简单的页面,和其布局的设计,并且采用的是模块化思想,组件组装器概念,因此每个模块都有自己的页面代码,在加载模块的时候将其渲染出来。

功能添加和功能容器,或者说模块容器及其子模块

这部分主要涉及,模块容器
shell
和页面子模块的完成,这部分主要值得学习的是该单页应用的实现思想,即组件组装器概念:也就是将
shell
定义成全局的容器作用,在该容器中负责着子组件的加载和初始化行为,而子组件的功能实现被限定在自身模块当中,从而不会与其他模块产生混淆,降低了模块与模块之间的依赖性;

数据模型模块

这部分主要负责数据模型的创建和管理,比如(用户管理对象
people
chat
聊天消息对象等等),而数据模块负责对该应用涉及到的数据的增删改查等功能的实现。

服务器

如果说前面几个部分都属于客户端一块的东西,那这以及这以后的部分则是涉及到服务器端的业务和功能的内容了,该应用的服务器部分自然由
Node.js
来承担,而其中涉及的路由、通信、数据库则是由
express
socket.io
,和
mongodb
等来完成,并且在后台服务器的处理过程中,还涉及了一些认证,数据验证,
CRUD
等概念。

经过该书的系统性学习加实践,对于单页应用的大体开发流程,和其中涉及的部分关键技术有了更深的认识,其中也对部分关键技术做了更深入的研究,比如(
Node.js
express
socket.io
mongodb
),并且在该书系列完成之后便会依次完整系统性的去学习这些知识点。

知识点回顾

模块化思想

模块化实现,不仅让功能进行分离,减少模块间的依赖,还可使代码更容易维护,甚至能使模块得到复用,好处自然是值得称赞。

比如当前主流的模块化编程有(
CommonJS
AMD
CMD
ES6 标准
),这里简单看下它们的简单使用方式,稍详细点的介绍,之前有篇文章是关于这几个的,地址:WEB前端模块化基础知识 go ✈

CommonJS


相对而言,
CommonJS
模块化更偏向于服务器端,也正由于它的发展就是由服务器端模块化的需要,随着技术不断更新和发展,前端模块化的概念推出,
CommonJS
Node.js
的推动下大力支持了前端模块化。

// welcome.js

var hello = 'hello world!';

function sayHello () {
alert( hello );
}

function bye() {
alert( 'bye bye !' );
}

module.exports = {
hello   : sayHello,
bye     : bye
}


使用:

// test.js
var welcome = require( './welcome' );

welcome.hello();    // 'hello world!'
welcome.bye();      // 'bye bye !'


AMD


AMD
:Asynchronous Module Definition,异步模块定义,属于异步加载,这个其实是一套基于浏览器模块化开发的规范,要使用该规范进行模块化开发,需要用到其中的函数库:
requireJS


相比较
CMD
而言,这个有个不好的地方就是,模块需要提前一次性进行加载。

来看下器定义和使用:

定义:

// module.js

define(
['dependModule1', 'dependModule2', ...],  // 这个数组里面包含了该模块所依赖的所有模块
function () {

// 这里面就是新模块的内容

return {
// 返回模块对象
};
}
);


会发现上面模块的定义时,
define
中并没有声明模块的名称,这是因为对于
AMD
而言,一个文件既是一个模块,因此该模块的文件名也就是该模块的名称:
module


使用:

// test.js

// 加载模块
require(['module'], function ( myModule ) {

// myModule 就是模块加载完成之后,该模块的对象名,在这个回调里面
// 可以通过 myModule 来引用该模块
});


CMD


CMD
:Common Module Definition,表示通用模块定义,这个相对
AMD
有个好处就是,能按需加载模块,也就是说在哪里需要才去加载模块,而不是一次性把模块全部加载好,这点会一定程度上减少程序启动时间,但在运行过程中则需要实时去加载模块。

定义:

// module.js

define(function (require, exports, module) {

var dependModule = require( 'dependModuleName.js' );

// balabala  module content
});


使用模块,需要用到
seajs


seajs.use(['module.js'], function (myModule) {

// 模块加载完成
});


ES6


ES6
标准下的模块化编程,主要分两种方式

命名式导出

这种方式,支持一个文件同时可以导出多个函数或变量

比如:

// module.js

export function fn1() {}
export var1 = 10;


然后通过
import
使用:

// test.js

import { fn1, var1 } from 'module'

// 或者别名
import { fn1, var1 } as myModule from 'module'

// 或者
import { fn1 as show, var1 as name } from 'module'


定义式导出

定义式导出,一个文件只能出现一个定义式的导出变量或函数

比如:

// module.js

// 这个时候就可以省略调函数名
export function () {}


使用的时候,可以通过文件名,或者
default
关键字来使用
module.js
模块中定义式声明的函数,因为一个文件只需要一个,因此不用担心会引用不对的情况发生

// test.js

import myModule from 'module';

// 或者使用 default
import default from 'module';

// 也可别名

import { default as myModule } from 'module';


混合使用

也就是说两种定义方式可以混合使用。

// module.js

export function () {
// 定义式导出方式的内容 在这里完成
}

// 下面是命名式方式
export function fn1() {}
export function fn2() {}
export var name = 'lizc';


使用:

// test.js

// 这里的 module 可以用 default 代替,得到的结果就是
// module.js 中采取定义式方式定义的那个函数
import { module, fn1, fn2, name } from 'module'


服务器端编程

该书中的单页应用中的服务器端是基于
Node.js
来实现的,其中使用到的内容主要包含三大块(
Express
Socket.IO
MongoDB
)下面依次来简单的回顾下

http
服务器

先来看下使用
http
模块创建简单的服务器

// server.js

require( 'http' ).createServer(function ( req, res ) {
// do something
}).listen( 3000 );


Express


使用
express
创建服务器程序

// server.js

var express = require( 'express' )
app = express();

app.listen( 3000, function () {
console.log( 'express server listening on port 3000.' );
} );


http
express
混合使用的情况

// server.js

var http    = require( 'http' ),
express = require( 'express' ),
app     = express(),
server;

server = http.createServer( app );
server.listen( 3000, function () {
console.log( 'http server with express listening on port 3000.' );
} );


express
环境变量(’development’, ‘testing’, ‘staging’, ‘production’)

获取:
app.get( 'env' );


设置:
app.set( 'env', 'testing' );


中间件使用:比如日志中间件(logger)

在 3.0+ 版本中 logger 可直接通过
express.logger
使用,4.0+ 版本中大部分中间件都被独立出来了,都需要单独安装使用

安装 logger:
npm install morgan --save
, 4.0+ 中间件 logger 的包名是:
morgan


使用: `app.use( logger( ‘dev’ ) );

可以根据开发环境不同设置不同的中间件

比如:

var env = app.get( 'env' );

if ( env === 'development' ) {
app.use( ... );
} else if ( env === 'testing' ) {
app.use( ... );
}

......


自定义中间件

app.use( function ( req, res, next ) {

// 中间件处理程序

next();
} );


路由设置

get 请求路由处理:

app.get( '/', function ( req, res ) { ...... } );


post 请求路由处理:

app.post( '/', function ( req, res ) { ...... } );


通用路由处理(必须要有
next
且执行
next();
将路由控制流往下传递)

app.all( '/', function ( req, res, next ) { ...... } );


Socket.IO


socket.io
主要用来客户端和服务器进行通信用,通过消息加事件触发机制来完成。

要使用
socket.io
,首先要建立个服务器,如上面
http
express
方式,然后获取
socket
实例监听该服务器,得到通信管道。

// server.js

var http    = require( 'http' ),
express = require( 'express' ),
app     = express(),
socket  = require( 'socket.io' ),
server, io;

// 新建服务
server = http.createServer( app );

// socket 监听服务
io = socket.listen( server );

// 服务监听端口 3000
server.listen( 3000, function () {
console.log( 'http server with express listening on port 3000.' );
} );


服务程序创建完成,并且使用
socket
进行了监听,那么接下来就可以通过
socket
管道向客户端发送消息:

io.sockets.emit( 'update', data );


客户端通过连接,然后监听消息

前提:客户端需要通过
<script>
引入
socket.io
库文件

<script src="/socket.io/socket.io.js"></script>


接下来就可以 :

var connect = io.connect( 'http://192.168.179.103:3000' );

// 开始监听消息
connect.on( 'update', function ( data ) {

// 这里就是客户端对服务器发送来的 update 消息的处理程序
// 参数 data 就是服务器携带的数据

} );


也可以链式写法:

io.connect( 'http://192.168.179.103:3000' ).on( 'update', function ( data ) {

// 这里就是客户端对服务器发送来的 update 消息的处理程序
// 参数 data 就是服务器携带的数据

} );


上面就是个简单的
socket.io
客户端和服务器连接,以及消息的发送和监听处理。

MongoDB


数据库,基于文件存储,文件内容,采用的是
JSON
格式,也就是说该数据库的数据存储包括各种操作都是在
JSON
之上进行的。对于更多的介绍和优缺点,百度/google/官网介绍的很详细,没事可以去观摩观摩。

这里就直接回顾下它的简单使用

首先:安装

sudo apt-get install -y mongodb-org


安装之后,需要启动下服务,不然直接使用
mongo
进入数据库时候会报错。

sudo service start mongod


启动之后就可以进入
mongo
数据库的命令行进行数据库操作了,这里就不回顾了,重点是
Node.js
环境下
mongodb
的使用。

在新版 2.0+ 中,连接方式已经发生了改变,使用如下:

// 引入数据库模块,并获取数据库实例

var MongoClient = require( 'mongodb' ).MongoClient,
collection;

// 连接到默认的 test 数据库
MongoClient.connect( 'mongodb://localhost:27017/test', function ( error, db ) {

// 这个函数有两个参数,第一个表示连接过程中发生的错误对象,如果
// 该对象存在,表示连接不成功,可以通过该对象获取到具体错误信息

// 只有在 error 为空的情况下,表示连接成功,那么第二个参数 db 就是连接后的数据库实例

// 通过这个实例我们就可以连接到 test 数据库中具体集合对象,比如:user
collection = db.collection( 'user' );

// 随后就可以对集合进行一系列的 CRUD 操作
} );


CRUD
相关函数(需要注意的是这些函数都是基于数据中集合上进行操作的)

插入:

collection.insertOne({}, function ( error, result ) {} );


collection.insertMany([{},{}], function ( error, result ) {} );


error
: 插入失败的错误信息;

result
:插入之后的结果,一般包含插入的条目,简要内容等信息;

删除:

collection.deleteOne( {}, function ( error, result ) {} );


collection.deleteMany( [{},{}], function ( error, result ) {} );


更新:

collection.updateOne( find_map, set_map, function ( error, result ) {} );


collection.updateMany( find_map, { $set: set_map }, function ( error, result ) {} );


find_map
:查找的对象,需要被更新的;

set_map
: 更新的对象,用来替换旧数据的;

查找:查找功能很强大,并且包含很多功能,具体可参考
find
链式函数


collection.find( {}, function ( error, result ) {} );


通过路由和数据库结合,返回查询结果

// 路由处理
app.get( '/user/list', function ( req, res ) {

// 查询所有用户
collection.find( {} ).toArray( function ( error, result ) {

// 错误退出
if ( error ) { return false; }

// 成功返回查询到的的结果
// 回调放在 toArray 中,表示将结果数组化
res.send( result );
} );
} );


发布准备

最后来看下该书对于发布的准备工作都讲了些啥

前面部分讲述了爬虫,错误处理机制,CDN,重点看下缓存的内容。

缓存

缓存方式有下面四种:

Web 存储:把字符串保存至客户端,应用可以访问这些数据,并用它来保存处理好的 HTML,这些HTML是根据服务器上的数据生成的;

包含两种方式:本地存储(localStorage)和会话存储(sessionStorage)

两种方式除了存储时期不同之外,使用方式几乎相同

window.storage = localStorage || sessionStorage;


对象的使用方式也有两种,通过
*item
系的函数,或者直接使用
obj[ key ] = value
形式,推荐使用函数方式;

添加:

storage.setItem(key, value);
storage[ key ] = value;


读取:

storage.getItem( key );
storage[ key ];


修改:

storage.setItem(key, newValue);


删除:

storage.removeItem( key );


HTTP 缓存:客户端缓存,在客户端保存着服务器的响应;

这种方式是通过浏览器进行缓存,当服务器给浏览器发送数据时,这个时候浏览器就会把数据缓存起来,下次如果发生同样的数据请求时直接从浏览器缓存中读取。

对于 HTTP 缓存有两种模式存储:是否检查数据新鲜度(或者说是否过期)

如果不检查,相当于直接取浏览器缓存;

如果检查,则需要从服务器重新获取数据;

因此 HTTP 缓存方式比较适合那种在一定时间内不会有啥改动的数据,比如图片,脚本文件,样式文件等等。

max-age

服务器在响应数据的时候,可以通过设置
max-age
来告诉客户端该数据需要被缓存多久,设置方式:

单位(秒),如果设为 0 ,表示每次请求都需要检查数据是否是最新的。

res.header( 'Cache-Control', 'max-age=28800' );


阻止中间服务器使用它的缓存,可以通过下面三个属性来达到目的:

no-cache
: 不进行缓存,使用起来会引起不必要的慢,建议使用
no-store


no-store
:通知客户端和中间服务器,不缓存本次请求结果;

last-modified
:在不设置
Cache-Control
情况下,客户端会根据这个属性来决定缓存期限,通常是这个值的 1/3;

服务器缓存:Memcached 和 Redis 服务器缓存,将客户端请求的响应数据保存至服务器,以至于其他请求同样的数据的时候可以使用,而不用重新搜索数据库;

数据库缓存:数据库缓存查询结果,供下次使用。

把书中的对比图绘制了一份,看下图更直观



结篇语

《单页应用开发》这本书完整的阅读下来,包括一步步跟着把书中代码敲下来,至今刚好一个月了,这本书中从前到后的介绍了单页应用的开发过程,从中学习到了很多内容,不管是编程思想上,还是技术知识上都是不小的积累。

还是随便侃几句吧,文笔太菜了,只怪书读的太少,囧!

学习的步伐越来越紧促,越是感觉知识的缺乏,技术的薄弱,不论以往经历了什么,如今能继续从事自己热爱的技术工作,是件值得开心的事情,前路漫漫,奋斗在路上 !!!

最后感谢作者,也感谢翻译此书的牛牛们!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息