基于Nodejs+express4+Mongodb+Angularjs建立web项目
转自 http://blog.csdn.net/blacksiders/article/details/50081941
基于Nodejs+express4+Mongodb+Angularjs建立web项目
– 基于Nodejs搭建web服务器
– 利用Express4搭建restful服务
– 使用Mongodb作为数据库,用mongoose组件连接Mongodb
– 使用AngularJS+bootstrap设计UI界面
– 使用Webstorm 10.0.4开发
第一部分:服务端搭建
1.通过Webstorm建立Node.js Express APP
File -> New Project -> Node.js Express App,Location栏填写项目名称,选择Nodejs和npm位置,Options -> Template 选择EJS
在项目下新建文件夹models保存mongodb相关对应model。
在models目录下创建model文件movie.js。
在routes目录下创建restful API 支持文件 movies.js
完成后的目录结构如下
- project
-- bin
--- www
-- models
--- movie.js
-- node_modules
--- ...
-- public
--- ...
-- routes
movies.jsapp.jspackage.json
2.在package.json中添加mongoose支持及其他相关组件
{"name": "project","version": "0.0.0","private": true,"scripts": {"start": "node ./bin/www"},"dependencies": {"body-parser": "~1.13.2","cookie-parser": "~1.3.5","debug": "~2.2.0","ejs": "~2.3.3","express": "~4.13.1","morgan": "~1.6.1","errorhandler": "~1.4.2","serve-favicon": "~2.3.0","mongoose": "~4.2.5","connect-mongo": "latest","express-session": "latest"},"engines": {"node": ">=0.10.0"}
}
3.在movie.js中建立movie模型:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;// define an db object
var movieSchema = new Schema({title: String,releaseYear: String,director: String,genre: String
});// bind module for accessing outside
module.exports = mongoose.model('Movie', movieSchema);
4.在movies.js中建立基于movie的restful API
引入movie模型,并开启router
var Movie = require('../models/movie.js');
var express = require('express');
var router = express.Router();
实现一些基本的功能API
var Movie = require('../models/movie.js');// get all movies
exports.list = function(req, res){Movie.find(function (err, movies) {if (err) {return res.send(err);}res.json(movies);})
};// create new movie
exports.create = function(req, res){var movie = new Movie(req.body);movie.save(function (err) {if (err) {return res.send(err);}res.send({message: 'add a movie'});});
};// update a movie
exports.update = function (req, res) {//Movie.findById(req.params.id, callback)Movie.findOne({_id: req.params.id}, function (err, movie) {if (err) {return res.send(err);}for (prop in req.body) {movie[prop] = req.body[prop];}movie.save(function (err) {if (err) {return res.send(err);}res.json({message: "update a movie"});});});
};//delete a movie
exports.delete = function (req, res) {Movie.remove({_id: req.params.id}, function (err, movie) {if (err) {return res.send(err);}res.json({message: 'delete a movie'});});
};
导出功能模块让其他部分可以使用该模块
module.exports = router;
5.启用Restful服务
在app.js中引入mongoose建立数据库连接
var mongoose = require('mongoose');
// connect to mongodb
var dbName = 'movie';
var url = 'mongodb://localhost:27017/' + dbName;
var mongoOptions = {server: {socketOptions: {keepAlive: 1}}
};
mongoose.connect(url, mongoOptions);
mongoose.connection.on('error', function (err) {console.log('Mongo Error:' + err);
}).on('open', function () {console.log('Connection opened');
});
引入router启用Restful服务
var express = require('express');
var app = express();
var movies = require('./routes/movies');
app.use('/api', movies);
由于http通信是基于json格式的,需要指定请求数据格式和编码
var bodyParser = require('body-parser');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
导出模块
module.exports = app;
6.在bin/www中开启server
var app = require('../app');
var http = require('http');
var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);//Create HTTP server
var server = http.createServer(app);
server.listen(port);
第二部分:前端搭建
前端使用AngularJS+Bootstrap搭建
1.引入bower
先安装NodeJS,使用npm工具引入bower。
在项目文件夹pubic下依次建立以下目录结构
- project
-- ...
-- public
--- css
--- images
--- js
---- controller
---- service
--- views
index.html
添加bower依赖,在项目根目录下新建.bowerrc文件,指定bower安装路径
{"directory": "/public/bower_components"
}
添加bower.json文件指定依赖:
{"name": "project","version": "0.0.0","dependencies": {"jquery": "~2.1.3","bootstrap": "~3.3.2","angular": "~1.3.8","font-awesome": "~4.2.0","angular-ui-router": "~0.2.13","angular-bootstrap": "~0.12.1"}
}
运行bower install,安装相关js插件
2.引入AngularJS组件
在public > js下新建module.js,创建AngularJS项目组件app
'use strict';var app = angular.module('app', ['ui.router','ui.bootstrap'
]);
创建一个service来保存windows session
session.storage.js
(function (app) {'use strict';app.factory('SessionStorage', function ($window) {var store = $window.sessionStorage;return { save: function (key, value) { value = angular.toJson(value); store.setItem(key, value); }, get: function (key) { var value = store.getItem(key); if (value) { value = angular.fromJson(value); } return value; }, delete: function (key) { store.removeItem(key); } }});
})
(angular.module('app'));
新建一个movie service进行http请求
movie.service.js
(function (app) {'use strict';app.factory('MovieService', function ($http, $q) {return {getAllMovies: function () {var url = "http://localhost:3000/api/movie/all";var deferred = $q.defer();$http.get(url).then(function success(respData) {var movies = respData.data;deferred.resolve(movies);},function error(reason) {deferred.reject(reason);});return deferred.promise;},updateMovie: function (movie, id) {var url = "http://localhost:3000/api/movie/" + id;var deferred = $q.defer();$http.put(url, movie).then(function success(respData) {var movies = respData.data;deferred.resolve(movies);},function error(reason) {deferred.reject(reason);});return deferred.promise;}}});
})(angular.module('app'));
在controller目录下建立两个controller处理相关数据操作
main.controller.js
(function (app) {
'use strict';app.controller('MainController', function ($scope, $rootScope, $state, SessionStorage, movies) {$rootScope.title = 'express_demo2';$scope.movies = movies;$scope.updateMovie = function (movie) {SessionStorage.delete('movie');$state.go('movie.update', {data: movie});};});
})(angular.module('app'));
movie.controller.js
(function (app) {'use strict';app.controller('MovieController', function ($scope, $rootScope, $state, $stateParams, MovieService, SessionStorage) {$scope.movie = $stateParams.data;if (!$scope.movie) { $scope.movie = SessionStorage.get('movie'); } else { SessionStorage.save('movie', $scope.movie); }$scope.update = function () { var promise = MovieService.updateMovie($scope.movie, $scope.movie._id); promise.then(function (data) { alert('update success!'); SessionStorage.delete('movie'); $state.go('movie.main'); }); };});
})(angular.module('app'));
建立uirouter指定路由
(function (app) {
'use strict';app.config(function ($stateProvider, $urlRouterProvider, $locationProvider) {$locationProvider.html5Mode(true);$urlRouterProvider.otherwise('/movie');$stateProvider.state('movie', {abstract: 'true',templateUrl: '/views/menu.html'}).state('movie.main', {url: '/movie',controller: 'MainController',templateUrl: '/views/main.html',resolve: {'movies': function (MovieService) {return MovieService.getAllMovies();}}}).state('movie.update', {url: '/movie/update',controller: 'MovieController',templateUrl: '/views/update.html',params: {data: null}});});
})(angular.module('app'));
在css文件下建立css
.margin-top-20 {margin-top: 20px;
}.title-font {font-size: large;font-style: italic;font-family: Consolas;font-weight: bold;
}
在index.html中声明app位置,并导入相关的js和css文件
<html ng-app="app">
<head><meta charset="UTF-8"/><base href='/'/><title ng-bind="title">title><link rel='stylesheet' href='bower_components/bootstrap/dist/css/bootstrap.css'/><link rel='stylesheet' href='bower_components/font-awesome/css/font-awesome.css'/><link rel='stylesheet' href='css/style.css'/>head>
<body><div ui-view>div><script src="bower_components/jquery/dist/jquery.min.js">script>
<script src="bower_components/angular/angular.min.js">script>
<script src="bower_components/bootstrap/dist/js/bootstrap.min.js">script>
<script src="bower_components/angular-ui-router/release/angular-ui-router.min.js">script>
<script src="bower_components/angular-bootstrap/ui-bootstrap-tpls.min.js">script><script src="js/module.js">script>
<script src="js/routes.js">script><script src="js/controller/main.controller.js">script>
<script src="js/controller/movie.controller.js">script><script src="js/service/movie.service.js">script>
<script src="js/service/session.storage.js">script>body>
html>
在views目录下建立三个html页面进行操作
main.html
<table class="table table-bordered"><thead><tr><th>Titleth><th>Yearth><th>Directorth><th>Genreth><th>Optionth>tr>thead><tbody><tr ng-repeat="movie in movies"><td>{{movie.title}}td><td>{{movie.releaseYear}}td><td>{{movie.director}}td><td>{{movie.genre}}td><td><a class="btn btn-default" href="javascript:void(0)" ng-click="updateMovie(movie)">Updatea>td>tr>tbody>
table>
menu.html
<div class="container"><div class="row margin-top-20">class="title-font">Movie Book System
div>
div>
<div class="container"><div class="row"><div class="ui-view">div>div>
div>
update.html
在app.js中声明html位置
app.set('views', path.join(__dirname, 'public'));
app.engine('html', require('ejs').__express);
app.set('view engine', 'html');
// rewrite to load static resources
app.use(express.static(path.join(__dirname, 'public')));// static views
app.all('/*', function (req, res) {res.sendfile('index.html', {root: path.join(__dirname, 'public')});
});
至此,运行www文件即可启动nodejs项目,在界面上访问localhost:3000即可访问项目。
=========================================
以下是实现过程中自己的一些总结感想:
实现过程中遇到的异常处理:
(1) 在用bower安装依赖的时候,出现了Bower : ENOGIT git is not installed or not in the PATH ,这个错误提示很明显。就是git没有设置在环境变量中!
解决方法一:
添加git到window的环境变量中。设置path路径为C:\Program Files\Git\bin
关于环境变量的设置,在这里就不多说了。
解决方法二:
在不用添加环境变量的情况下,运行下面一个命令,就可以设置当前文件加的环境变量。
$ set PATH=%PATH%;C:\Program Files\Git\bin
运行完了上面的命令,然后你再用bower安装依赖就成功了,不会有Bower : ENOGIT git is not installed or not in the PATH 这个报错了!
(2) 执行bower install命令遇到异常:
ECONFLICT Unable to find suitable version for angular
解决方法:
It worked for me by making following changes in "bower.json":
"angular": "latest",
"angular-mocks": "latest",
"jquery": "latest",
"bootstrap": "latest"
(3)查询movie列表时查询结果总为空
解决方法:将movie.js中
module.exports = mongoose.model('Movie',movieSchema);
改为
module.exports = mongoose.model('Movie',movieSchema,'Movie');
原因:
使用Mongoose#model(name, [schema], [collection], [skipInit]);定义模型, mongoose 会把表名变成复数 所以这里collection参数要写上
整个工程流程架构:
views文件夹下定义视图,routes.js中定义路由,路由将视图和控制器Controller进行关联,controller调用service完成业务数据操作,之后将操作结果反映在视图中(例如通过$scope.movies=movies实现变量双向绑定,通过$scope.updateMovie和视图中的ng-click关联)。而service通过调用模型中的API实现数据库操作。
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
