项目初始化
建立Imooc文件夹,在文件夹根目录下安装模块
npm install express jade mongoose bootstrap@3
npm install bower -g
项目结构目录如下
- Imooc/
-node_modules/
-bower_components/
-views/
-index.jade
-detail.jade
-admin.jade
-list.jade
-app.js
测试地址
localhost:3000/
localhost:3000/movie/1
localhost:3000/admin/movie
localhost:3000/admin/list
入口文件app.js
var express = require('express')
var app = express()
app.set('view engine','jade')
app.set('port',3000)
app.get('/',function(req,res){
res.render('index',{title:'imooc'})
})
创建入口文件及视图
修改app.js文件,配置路由
var express = require('express')
var port = process.env.port || 3000
var app = express()
app.set('views', './views')
app.set('view engine','jade')
app.listen(port)
console.log('Imooc started on port' + port)
//index page
app.get('/',function(req,res){
res.render('index',{title:'imooc 首页'})
})
//detail page
app.get('/movie/:id',function(req,res){
res.render('detail',{title:'imooc 详情页'})
})
//admin page
app.get('/admin/movie',function(req,res){
res.render('admin',{title:'imooc 后台录入页'})
})
//list page
app.get('/admin/list',function(req,res){
res.render('list',{title:'imooc 列表页'})
})
创建4个jade视图,代码如下
doctype
html
head
meta(chareset="utf-8")
title #{title}
body
h1 #{title}
在cmd命令中以node app
启动项目,查看浏览器
页面开发
创建如下view结构
head文件中引入js css
link(href="/bootstrap/dist/css/bootstrap.min.css", rel="stylesheet")
script(src="/jquery/dist/jquery.min.js")
script(src="/bootstrap/dist/js/bootstrap.min.js")
header文件中为公用代码
.container
.row
.page-header
h1= title
small 重度科幻迷
layout文件如下
doctype
html
head
meta(chareset="utf-8")
title #{title}
include ./includes/head
body
include ./includes/header
block content
h1 #{title}
修改index,继承layout,根据movies创建thumbnail缩略图
extends ../layout
block content
.container
.row
each item in movies
.col-md-2
.thumbnail
a(href="/movie/#{item._id}")
img(src="#{item.poster}", alt="#{item.title}")
.caption
h4 #{item.title}
p: a.btn.btn-primary(href="/movie/#{item._id}", role="button") 观看预告片
修改detail,左边flash插件,右边movie内容
extends ../layout
block content
.container
.row
.col-md-7
embed(src="#{movie.flash}", allowFullScreen="true", quality="high", width="720", height="600", align="middle", type="application/x-shockwave-flash")
.col-md-5
.dl-horizontal
dt 电影名字
dd= movie.title
dt 导演
dd= movie.doctor
dt 国家
dd= movie.country
dt 语言
dd= movie.language
dt 上映年份
dd= movie.year
dt 简介
dd= movie.summary
修改admin,加入form表单组件
extends ../layout
block content
.container
.row
form.form-horizontal(method="post", action="/admin/movie")
.form-group
label.col-sm-2.control-label(for="inputTitle") 电影名字
.col-sm-10
input#inputTitle.form-control(type="text", name="movie[title]", value=movie.title)
.form-group
label.col-sm-2.control-label(for="inputDoctor") 电影导演
.col-sm-10
input#inputDoctor.form-control(type="text", name="movie[doctor]", value=movie.doctor)
.form-group
label.col-sm-2.control-label(for="inputCountry") 国家
.col-sm-10
input#inputCountry.form-control(type="text", name="movie[country]", value=movie.country)
.form-group
label.col-sm-2.control-label(for="inputLanguage") 语种
.col-sm-10
input#inputLanguage.form-control(type="text", name="movie[language]", value=movie.language)
.form-group
label.col-sm-2.control-label(for="inputPoster") 海报地址
.col-sm-10
input#inputPoster.form-control(type="text", name="movie[poster]", value=movie.poster)
.form-group
label.col-sm-2.control-label(for="uploadPoster") 海报上传
.col-sm-10
input#uploadPoster(type="file", name="uploadPoster")
.form-group
label.col-sm-2.control-label(for="inputFlash") 片源地址
.col-sm-10
input#inputFlash.form-control(type="text", name="movie[flash]", value=movie.flash)
.form-group
label.col-sm-2.control-label(for="inputYear") 上映年代
.col-sm-10
input#inputYear.form-control(type="text", name="movie[year]", value=movie.year)
.form-group
label.col-sm-2.control-label(for="inputSummary") 电影简介
.col-sm-10
textarea#inputSummary.form-control(type="text", name="movie[summary]")= movie.summary
.form-group
.col-sm-offset-2.col-sm-10
button.btn.btn-default(type="submit") 录入
修改list 加入table组件
extends ../layout
block content
.container
.row
table.table.table-hover.table-bordered
thead
tr
th 电影名字
th 导演
th 国家
th 上映年份
//- th 录入时间
th 查看
th 修改
th 删除
tbody
each item in movies
tr(class="item-id-#{item._id}")
td #{item.title}
td #{item.doctor}
td #{item.country}
td #{item.year}
//- td #{moment(item.meta.updateAt).format('MM/DD/YYYY')}
td: a(target="_blank", href="/movie/#{item._id}") 查看
td: a(target="_blank", href="/admin/movie/update/#{item._id}") 修改
td
button.btn.btn-danger.del(type="button", data-id="#{item._id}") 删除
修改app.js ,添加path模块来制定文件夹,在page中传入mock数据
var express = require('express')
var path = require('path')
var port = process.env.PORT || 3000
var app = express()
var bodyParser = require('body-parser')
app.set('views', './views/pages')
app.set('view engine', 'jade')
app.use(bodyParser.urlencoded({extended:true}))
app.use(express.static(path.join(__dirname, 'node_modules')))
app.listen(port)
console.log('imooc stated on port ' + port)
//index page
app.get('/', function(req, res) {
res.render('index', {
title: 'imooc 首页',
movies: [{
title: '机械战警',
_id: 1,
poster: 'http://r3.ykimg.com/05160000530EEB63675839160D0B79D5'
},
{
title: '机械战警',
_id: 2,
poster: 'http://r3.ykimg.com/05160000530EEB63675839160D0B79D5'
},
{
title: '机械战警',
_id: 3,
poster: 'http://r3.ykimg.com/05160000530EEB63675839160D0B79D5'
},
{
title: '机械战警',
_id: 4,
poster: 'http://r3.ykimg.com/05160000530EEB63675839160D0B79D5'
},
{
title: '机械战警',
_id: 5,
poster: 'http://r3.ykimg.com/05160000530EEB63675839160D0B79D5'
},
{
title: '机械战警',
_id: 6,
poster: 'http://r3.ykimg.com/05160000530EEB63675839160D0B79D5'
}]
})
})
//detail page
app.get('/movie/:id', function(req, res) {
res.render('detail', {
title: 'imooc 详情页',
movie: {
doctor: '何塞·帕迪里亚',
country: '美国',
title: '机械战警',
year: '2014',
poster: 'http://r3.ykimg.com/05160000530EEB63675839160D0B79D5',
language: '英语',
flash: 'http://player.youku.com/player.php/sid/XNjA1Njc0NTUy/v.swf',
summary: '《机械战警》是由何塞·帕迪里亚执导,乔尔·金纳曼、塞缪尔·杰克逊、加里·奥德曼等主演的一部科幻电影,改编自1987年保罗·范霍文执导的同名电影。影片于2014年2月12日在美国上映,2014年2月28日在中国大陆上映。影片的故事背景与原版基本相同,故事设定在2028年的底特律,男主角亚历克斯·墨菲是一名正直的警察,被坏人安装在车上的炸弹炸成重伤,为了救他,OmniCorp公司将他改造成了生化机器人“机器战警”,代表着美国司法的未来。'
}
})
})
//admin page
app.get('/admin/movie', function(req, res) {
res.render('admin', {
title: 'imooc 后台录入页',
movie: {
title: '',
doctor: '',
country: '',
year: '',
poster: '',
flash: '',
summary: '',
language: ''
}
})
})
//list page
app.get('/admin/list', function(req, res) {
res.render('list', {
title: 'imooc 列表页',
movies: [{
title: '机械战警',
_id: 1,
doctor: '何塞·帕迪里亚',
country: '美国',
year: 2014,
language: '英语',
flash: 'http://player.youku.com/player.php/sid/XNjA1Njc0NTUy/v.swf',
summary: '《机械战警》是由何塞·帕迪里亚执导,乔尔·金纳曼、塞缪尔·杰克逊、加里·奥德曼等主演的一部科幻电影,改编自1987年保罗·范霍文执导的同名电影。影片于2014年2月12日在美国上映,2014年2月28日在中国大陆上映。影片的故事背景与原版基本相同,故事设定在2028年的底特律,男主角亚历克斯·墨菲是一名正直的警察,被坏人安装在车上的炸弹炸成重伤,为了救他,OmniCorp公司将他改造成了生化机器人“机器战警”,代表着美国司法的未来。'
}]
})
})
启动应用查看浏览器
项目数据库实现
Mongo DB 通过 Schema Model Document来进行数据库的定义操作
建立模式 schemas/movie.js,定义MovieSchema结构,添加pre方法及静态方法,最后将其导出
var mongoose = require('mongoose')
var Schema = mongoose.Schema
var MovieSchema = new Schema({
doctor: String,
title: String,
language: String,
country: String,
summary: String,
flash: String,
poster: String,
year: Number,
meta: {
createAt: {
type: Date,
default: Date.now()
},
updateAt: {
type: Date,
default: Date.now()
}
}
})
MovieSchema.pre('save', function(next) {
if (this.isNew) {
this.meta.createAt = this.meta.updateAt = Date.now()
}
else {
this.meta.updateAt = Date.now()
}
next()
})
MovieSchema.statics = {
fetch: function(cb) {
return this
.find({})
.sort('meta.updateAt')
.exec(cb)
},
findById: function(id, cb) {
return this
.findOne({_id: id})
.exec(cb)
}
}
module.exports = MovieSchema
建立模型 models/movie.js,通过MovieSchema对模式进行编译建立模型,最后将其导出
var mongoose = require('mongoose')
var MovieSchema = require('../schemas/movie')
var Movie = mongoose.model('Movie', MovieSchema)
module.exports = Movie
修改app.js如下,安装npm install underscore moment
,本地MongoDB创建DB imooc。
index page中,Movie模型调用fetch方法得到movies数据集
detail page中,Movie模型调用findById方法,通过req中参数取得id
admin page中,提交表单调用post方法,id为空创建新对象,id不为空扩展对象
list page中,与index类似读取movies数据集
添加update路由
var express = require('express')
var path = require('path')
var mongoose = require('mongoose')
var _ = require('underscore')
var Movie = require('./models/movie')
var port = process.env.PORT || 3000
var app = express()
var bodyParser = require('body-parser')
mongoose.connect('mongodb://localhost/imooc')
app.set('views', './views/pages')
app.set('view engine', 'jade')
app.use(bodyParser.urlencoded({extended:true}))
app.use(express.static(path.join(__dirname, 'node_modules')))
app.locals.moment = require('moment')
app.listen(port)
console.log('imooc stated on port ' + port)
//index page
app.get('/', function(req, res) {
Movie.fetch(function(err,movies){
if (err) {
console.log(err)
}
res.render('index', {
title: 'imooc 首页',
movies: movies
})
})
})
//detail page
app.get('/movie/:id', function(req, res) {
var id = req.params.id
Movie.findById(id,function(err,movie){
res.render('detail', {
title: 'imooc 详情页',
movie: movie
})
})
})
//admin page
app.get('/admin/movie', function(req, res) {
res.render('admin', {
title: 'imooc 后台录入页',
movie: {
title: '',
doctor: '',
country: '',
year: '',
poster: '',
flash: '',
summary: '',
language: ''
}
})
})
//admin update movie
app.get('/admin/update/:id',function(req,res){
var id = req.params.id
if (id) {
Movie.findById(id,function(err,movie){
res.render('admin',{
title: 'Imooc 后台更新页',
movie: movie
})
})
}
})
//admin post movie
app.post('/admin/movie/new', function(req,res){
var id = req.body.movie._id
var movieObj = req.body.movie
var _movie
if (id !=='undefined') {
Movie.findById(id, function(err,movie){
if (err){
console.log(err)
}
_movie = _.extend(movie, movieObj)
_movie.save(function(err,movie) {
if (err){
console.log(err)
}
res.redirect('/movie/'+movie._id)
})
})
} else {
_movie = new Movie({
dector: movieObj.dector,
title: movieObj.title,
country: movieObj.country,
language: movieObj.language,
year: movieObj.year,
poster: movieObj.poster,
summary: movieObj.summary,
flash: movieObj.flash,
})
_movie.save(function(err,movie) {
if (err){
console.log(err)
}
res.redirect('/movie/'+movie._id)
})
}
})
//list page
app.get('/admin/list', function(req, res) {
Movie.fetch(function(err,movies){
if (err) {
console.log(err)
}
res.render('list', {
title: 'imooc 列表页',
movies: movies
})
})
})
在admin.jade添加隐藏的input,记录id
block content
.container
.row
form.form-horizontal(method="post", action="/admin/movie/new")
input(type="hidden",name="movie[_id]", value="#{movie._id}" )
.form-group
label.col-sm-2.control-label(for="inputTitle") 电影名字
.col-sm-10
删除功能及配置文件
创建public目录,创建文件public/js/admin.js,添加异步删除方法
$(function() {
$('.del').click(function(e) {
var target = $(e.target)
var id = target.data('id')
var tr = $('.item-id-' + id)
$.ajax({
type: 'DELETE',
url: '/admin/list?id=' + id
})
.done(function(results) {
if (results.success === 1) {
if (tr.length > 0) {
tr.remove()
}
}
})
})
})
在list.jade文件末尾引入admin.js
script(src="/js/admin.js")
创建.bowerrc文件,制定bower安装目录
{
"directory": "public/libs"
}
用bower安装bootstrap bower install bootstrap@3
修改app.js中path路径 app.use(express.static(path.join(__dirname, 'public')))
修改head.jade
link(href="/libs/bootstrap/dist/css/bootstrap.min.css", rel="stylesheet")
script(src="/libs/jquery/dist/jquery.min.js")
script(src="/libs/bootstrap/dist/js/bootstrap.min.js")
在app.js添加delete路由
//list delete movie
app.delete('/admin/list',function(req,res){
var id = req.query.id
if (id) {
Movie.remove({_id: id},function(err,movie){
if (err) {
console.log(err)
} else {
res.json({success: 1})
}
})
}
})
前端配置文件生成 bower init
后端配置文件生成 npm init
上传项目到GIT
在码云上创建项目
复制SSH地址
项目目录下创建.gitignore文件,忽略下列文件夹
/node_modules/
/public/libs
在项目根目录下启用Git Bash,git init
初始化
git remote add origin (ssh copy)
将本地目录与github关联
git pull origin master
拉取master分支
git status
查看状态
git add .
把文件追踪上
git commit -am 'test'
/ git ca 'test'
提交并加上test注释
git push --set-upstream origin master
推送到远程master分支
git checkout -b v1.0.0
创建v1.0.0分支并checkout
git branch
查看分支
查看github