MEAN Tutorial
为了熟悉MEAN基本架构,参考了 https://blog.udemy.com/node-js-tutorial/ 提供的实例。本文对该实例涉及的文件进行梳理。
实例使用的 Express Generator 由 npm 进行安装
npm install express-generator -g
-g 参数说明该nodejs模块采用全局安装的方式 install this package at the global level , 以便于在终端中可直接使用express调用该生成器。
使用
express PorjectName
建立基本的工程目录:
- bin/
- www
- public/
- images/
- javascipts/
- stylesheets/
- routes/
- index.js
- users.js
- views/
- error.jade
- index.jade
- layout.jade
- app.js
- package.json
进入工程目录,使用 nodemon 启动网页服务,默认端口为3000。
同样的,nodemon 可通过npm install -g nodemon
安装。
分析 /bin/www的文件内容,其包含如下语句:
var app = require('../app');
var http = require('http');
var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);
var server = http.createServer(app);
...
不难发现 port 决定了服务器的端口,通过修改此处可更改 nodemon 启动的服务端口
/app.js 是服务器的基本配置,实例中通过 app.js 添加基本路由,形如:
var apiName= require('apiPath');
...
app.use('/routePath', apiName);
通过 apiPath 索引至相应的 js 文件以获取返回值,以 index 为例:
./app.js
...
var routes = require('./routes/index');
app.use('/', routes);
...
./routes/index.js
...
router.get('/', function(req, res, next) {
res.render('index', { title: 'Express' });
});
...
通过该设置,访问网页根目录会返回 render 渲染的 index 界面。由于 app.js 中默认设置了 ./views 作为渲染文件的目录,故会调用 ./views/index.jade 进行渲染。
该实例中使用了 layout.jade 作为网页框架,形如:
doctype html
html(ng-app = 'myApp')
head
title= title
link(rel='stylesheet', href='/stylesheets/style.css')
link(rel='stylesheet', href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css')
script(src='https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.5/angular.js')
script(src='https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.5/angular-resource.js')
script(src='https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.5/angular-route.js')
script(src='/javascripts/myApp.js')
body
block content
为了使用 Angular 进行渲染,添加了(ng-ap ='myApp')
标签,并引用相应的 js 文件。在此基础上, index.jade 只需要套用 layout.jade , 形如:
extends layout
block content
div(ng-view)
即使用自己的 block content 替换 layout 中相应的策略。此处增加的 ng-view 标签,为后续添加 Angular 页面路由做准备。
前文中 layout.jade 中 包含了script(src='/javascripts/myApp.js')
,且增加了(ng-app='myApp')
标签,故可使用 myApp.js 定义路由和控制器,形如:
var app = angular.module('myApp', ['ngRoute', 'ngResource']);
app.config(['$routeProvider', function($routeProvider){
$routeProvider
.when('/', {
templateUrl : 'partials/homePage.html',
controller : 'contorllerName'
})
.otherwise({
redirectTo : '/'
})
}]);
...
partials/homePage.html 为新增的引导界面,该界面会替换 index中的<div ng-view>
,实现页面路由。
为何不仅仅使用Express的路由,而选择Angular来实现多页面路由?
实例作者给出的解释是,MEAN 基于 RESTful API,完全可以使用JSON对象进行数据传递。与传统的Jade渲染多页面不同的是,MEAN 框架下的后端可选择仅传递 JSON 给前端,使用 Angular 完成渲染。该方案减少了服务器的数据转换开销,同时具有较好的拓展性和延伸性。
继续分析上文中的 myApp.js,该文件中使用controller : 'contorllerName'
语句实现 controller 和页面的绑定,而 controller 的实现形如:
./public/partials/homPage.html
<ul>
<li ng-repeat="data in datas ">{{data.title}}</li>
</ul>
...
./public/javascripts/myApp.js
app.controller('myApp', ['$scope', '$resource',
function($scope, $resource){
//data-API
var dataList = $resource('/datas');
pollsList.query(function(datas){
$scope.datas = datas;
console.log(polls);
});
}]);
该部分的代码使用 $resource 模块获取服务器的数据,并绑定 homePage.html 的 datas 。关注 var dataList = $resource('/datas')
,该语句会向路由 /datas 发起get请求以获取 json 数据,针对该操作,回顾前文描述的 ./app.js,为实现该接口,我们需要在 ./app.js 中增加形如 :
var dataAPI = require('./routes/api/getData.js');
...
app.use('/datas', dataAPI);
进而在 ./routes/api/getData.js 中实现 get 方法。
var express = require('express');
var router = express.Router();
var monk = require('monk');
var db = monk('localhost:27017/dbName');
/* GET */
router.get('/', function(req, res) {
var collection = db.get("collectionName");
collection.find({}, function(err, dataList){
if(err) throw err;
res.json(pollsName);
});
});
该实例使用了 node 的 monk 模块连接 MongoDB 数据库,实现了查询 collection 中所有项并返回相应的 json 对象。该API可通过 http://localhost:port/datas 观察功能是否正确。
至此,实例的基本架构已经分析完成。原实例中完善API实现的post/delete 此处不再详述。
笔者梳理该实例的简单的框架图为: