本文介绍了利用MEAN技术栈(MongoDB,Express,Angular,Node.js)构建一个简单的商品管理功能
所需环境:Node.js、MongoDB 、(git)
先创建一个基于EJS的Express工程
express --view=ejs myvideo
cd myvideo
npm install
由于之后我们会用monk来实现服务器与数据库 的交互,我们先安装monk
npm install monk --save
然后我们先创建需要的文件夹及文件
- 进入public文件夹,创建partials文件夹,并在其中创建home.html和video-form.html.
- 然后进入public文件夹中的javascripts文件夹,并在其中创建vidzy.js作为应用服务器
- 最后,我们进入myvideo文件夹中的routes文件夹,并在其中创建videos.js作为控制器
准备工作完成,现在开始编写代码。
我们先来构建angular页面文件,进入views文件夹,打开index.js
<!DOCTYPE html>
<!-- 让 html 元素成为 AngularJS 应用的根元素。其中Vidzy是模块的名字,之后我们会在vidzy.js即控制器中创建 -->
<html ng-app='Vidzy' >
<head>
<!-- 添加bootstrap和angular框架 -->
<link rel='stylesheet' href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css' />
<script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script>
<script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular-resource.min.js"></script>
<script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular-route.min.js"></script>
<script src= "/javascripts/vidzy.js" > </script>
</head>
<body>
<!--使用 ngView 指令, 该 div 内的 HTML 内容会根据路由的变化而变化 -->
<div ng-view> </div>
</body>
</html>
接下来我们来编写用于替换 <div ng-view> </div>的两个页面
先编写home.html,该页面用于首页,至于如何使其出现在首页,将会在之后的路由中设置。
<h1>Home Page</h1>
<p>
<!-- 加#是为了兼容旧浏览器 -->
<a href="/#/add-video">Add a Video</a>
</p>
<ul>
<!-- ng-repeat与循环遍历有点相似,此处的意思为依次呈现出videos数组中的所有video的title属性 -->
<li ng-repeat='video in videos'>{{video.title}}</li>
</ul>
接下来,我们将video-form.html也编写好。
<h1>Add a Video</h1>
<form >
<div class ="form-group">
<label>Title</label>
<!-- ng-model将会绑定输入框的值到 scope 变量中,此处的代码会使输入框的值与控制器文件中的$scope.videos数组中的一个video的title属性绑定 -->
<input class="form-control" ng-model="video.title" >
</div>
<div class="form-group" >
<label>Description</label>
<textarea class="form-control" ng-model="video.description" > </textarea>
</div>
<!-- ng-click指令,当点击这个按钮时会触发控制器中的save()方法 -->
<input type="button" class="btn btn-primary" value="Save" ng-click="save()" >
</form>
编写好用于显示的angular页面之后,
我们先来编写vidzy.js即控制器
//控制器
// 此处直接调用全局变量angular来创建Vidzy模块,并添加了两个依赖模块
//ngResource模块提供了'$resource'模块,$resource模块是基于$http的一个封装
//ngRoute是路由模块,提供了$routeProvider模块用于设置路由
var app = angular.module('Vidzy', ['ngResource','ngRoute']);
//设置路由
app.config(['$routeProvider', function($routeProvider)
{
$routeProvider
//此处意为访问首页即http://localhost:3000/ 时会用home.html中的内容来替换index.ejs中设置了ng-view的div元素,
//并且调用名为'HomeCtrl'的控制器,将在下面的代码编写控制器
.when('/',
{
templateUrl: 'partials/home.html',
controller: 'HomeCtrl'
})
.when('/add-video', {
templateUrl: 'partials/video-form.html',
controller: 'AddVideoCtrl'
})
//此处意为没有匹配的路由时,将会默认跳转到'/'路径
.otherwise({
redirectTo: '/'
});
}]);
//创建HomeCtrl控制器
app.controller('HomeCtrl', ['$scope','$resource',function ($scope, $resource) {
var Videos = $resource('/api/videos');//此处可以将Videos对象理解为vidzy.js控制器与videos.js服务器交互的接口
//query方法属于GET类型请求
Videos.query(function(videos)
{
//将videos.js服务器返回的videos对象数组赋值给$scope.videos,这样home.html中的列表便能依次显示这个对象数组中的每一个对象了
$scope.videos = videos;
});
}]
);
//创建AddVideoCtrl控制器
app.controller('AddVideoCtrl', ['$scope', '$resource', '$location',
function($scope, $resource, $location)
{
//创建$scope.save方法,与video-form.html中按钮ng-click="save()"的save方法对应
$scope.save = function()
{
var Videos = $resource('/api/videos');
//$resource的save方法属于POST类型,此处将video-form.html中表单里填写的内容POST给服务器
Videos.save($scope.video, function()
{
//post成功后,调用回调函数,跳转到首页
$location.path('/');
});
};
}]);
最后我们 来编写videos.js
//服务器
var express = require('express');
var router = express.Router();
var monk = require('monk');
//var db = monk('localhost:27017/vidzy');
var db = monk('localhost:27017/myVideoDB');
//处理get请求,本案例中与vidzy.js控制器中的query方法对应
router.get('/', function(req, res)
{
//从数据库中读取数据并返回给控制器
var collection = db.get('videos');
collection.find({}, function(err, videos)
{
if (err) throw err;
res.json(videos);
});
});
// 增加一件商品
//处理post请求,本案例中与vidzy.js控制器中的save方法对应
router.post('/', function(req, res)
{
console.log ( req.body );
//将控制器post请求中的数据插入数据库中,并返回插入后的数据
var collection = db.get('videos');
collection.insert(
{
title: req.body.title,
description: req.body.description
}, function(err, video)
{
if (err) throw err;
res.json(video);
});
});
module.exports = router;
别忘记在app.js中插入以下代码,因为之前我们在$resource()中写入的路径为/api/videos
app.use('/api/videos', require('./routes/videos'));
启动工程
npm start
最后我们来理一下思路
启动工程之后,我们输入http://localhost:3000/就会显示home.html中的内容,这是因为我们设置了路由。
如果数据库中有数据,我们便会看到一条条商品记录,这是因为控制器向服务器发送了GET请求,服务器从数据库中取出数据并返回响应给控制器
点击Add a Video我们进入到video-form.html页面,输入数据之后点击按钮,控制器便会发送POST请求(输入的数据包含在请求中)给服务器,服务器接收请求,并将请求中的数据插入数据库,然后调用回调函数,返回响应(包含输入数据后的商品数据即更新后的商品数据)给控制器,控制器接收响应,并调用回调函数跳转到home.html页面
第一次写博客,MEAN技术栈也是最近开始学习,之后会总结一些RESTful API等与angular无关的服务器端代码,因为之后我会去学习react而不是angular。
若有谬误或纰漏,请大佬指正,也欢迎大家与我交流web开发的相关知识
最后贴上github代码,https://github.com/jc1144096387/MEAN-myvideo/tree/master/myvideo