文档章节

【转】基于Nodejs+express4+Mongodb+Angularjs建立web项目

iNiL0119
 iNiL0119
发布于 2016/11/07 11:36
字数 1485
阅读 45
收藏 2

原文:http://blog.csdn.net/blacksiders/article/details/50081941

第一部分:服务端搭建

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.js
    app.js
    package.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);

运行 bin/www (node bin/www)即可运行服务器。

第二部分:前端搭建

前端使用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文件

<!DOCTYPE html>
<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>Title</th>
        <th>Year</th>
        <th>Director</th>
        <th>Genre</th>
        <th>Option</th>
    </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)">Update</a></td>
    </tr>
    </tbody>
</table>

menu.html

<div class="container">
    <div class="row margin-top-20">
        <p class="title-font">Movie Book System</p>
    </div>
</div>
<div class="container">
    <div class="row">
        <div class="ui-view"></div>
    </div>
</div>

update.html

<form role="form" class="form form-horizontal">
    <div class="form-group">
        <div class="col-md-1">
            <label for="title">Title</label>
        </div>
        <div class="col-md-6">
            <input id="title" type="text" class="form-control" ng-model="movie.title"/>
        </div>
    </div>
    <div class="form-group">
        <div class="col-md-1">
            <label for="year">Year</label>
        </div>
        <div class="col-md-6">
            <input id="year" type="text" class="form-control" ng-model="movie.releaseYear"/>
        </div>
    </div>
    <div class="form-group">
        <div class="col-md-1">
            <label for="director">Director</label>
        </div>
        <div class="col-md-6">
            <input id="director" type="text" class="form-control" ng-model="movie.director"/>
        </div>
    </div>
    <div class="form-group">
        <div class="col-md-1">
            <label for="genre">Genre</label>
        </div>
        <div class="col-md-6">
            <input id="genre" type="text" class="form-control" ng-model="movie.genre"/>
        </div>
    </div>
    <div class="form-group">
        <div class="col-md-12">
            <a href="javascript:void(0)" class="btn btn-default" ng-click="update()">Update</a>
        </div>
    </div>
</form>

在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即可访问项目。

© 著作权归作者所有

iNiL0119
粉丝 7
博文 90
码字总数 88887
作品 0
杭州
前端工程师
私信 提问
[转]Web App 框架选择之百度&腾讯

百度的GMU GMU(Global Mobile UI)是百度前端通用组开发的移动端组件库,GMU是基于zepto的mobile UI组件库,提供webapp、pad端简单易用的UI组件。具有代码体积小、简单、易用等特点,组件内...

冰点沐雪
2014/12/16
0
0
集成服务监控器-green.monitor发布

在大型企业应用开发中,一个项目经常需要依赖于多个项目集成,经常某个集成服务的升级或者不工作,会导致你所工作的服务也挂掉,甚至影响你的开发流程。你是否还在接到测试团队或者运维团队的...

zting科技
2017/01/10
0
0
Java框架之Struts2(基本配置)

什么是struts2 Struts2是一个基于MVC模式的框架,相当于servlet. 下图是一个请求在Struts框架中的工作原理图 Struts2核心.png 建立一个Struts框架的基本流程 (先导包 13个) 1.先在wed.xml中配...

Miss_差不多
2017/11/06
0
0
一步一步学Remoting之一:从简单开始

一步一步学Remoting之一:从简单开始 一、Remoting的优缺点? 优点: 1、能让我们进行分布式开发 2、Tcp通道的Remoting速度非常快 3、虽然是远程的,但是非常接近于本地调用对象 4、可以做到...

科技小毛
2018/01/13
0
0
SpringBoot项目中加入jsp页面

特别强调:启动类和所有的controller service mapper等包必须位于同一个主包下(同一个包中),而且启动类在最外面,否则这些层都扫不到,不报错,但是无法实现我们的功能,要非常注意 根据我们之前搭...

浅色夏墨
2018/07/13
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Spring Cloud Alibaba 实战(二) - 关于Spring Boot你不可不知道的实情

0 相关源码 1 什么是Spring Boot 一个快速开发的脚手架 作用 快速创建独立的、生产级的基于Spring的应用程序 特性 无需部署WAR文件 提供starter简化配置 尽可能自动配置Spring以及第三方库 ...

JavaEdge
今天
7
0
TensorFlow 机器学习秘籍中文第二版(初稿)

TensorFlow 入门 介绍 TensorFlow 如何工作 声明变量和张量 使用占位符和变量 使用矩阵 声明操作符 实现激活函数 使用数据源 其他资源 TensorFlow 的方式 介绍 计算图中的操作 对嵌套操作分层...

ApacheCN_飞龙
今天
7
0
五、Java设计模式之迪米特原则

定义:一个对象应该对其他对象保持最小的了解,又叫最小知道原则 尽量降低类与类之间的耦合 优点:降低类之间的耦合 强调只和朋友交流,不和陌生人说话 朋友:出现在成员变量、方法的输入、输...

东风破2019
昨天
23
0
jvm虚拟机结构

1:jvm可操作数据类型分为原始类型和引用类型,因此存在原始值和引用值被应用在赋值,参数,返回和运算操作中,jvm希望在运行时 明确变量的类型,即编译器编译成class文件需要对变量进行类型...

xpp_ba
昨天
5
0
聊聊nacos Service的processClientBeat

序 本文主要研究一下nacos Service的processClientBeat Service.processClientBeat nacos-1.1.3/naming/src/main/java/com/alibaba/nacos/naming/core/Service.java public class Service ex......

go4it
昨天
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部