Node.js

node+mongodb 建站攻略(一期)

2018-10-16  本文已影响24人  六个周

本文档根据慕课网视频学习所总结

主题:
1.1.png
开发框架介绍
1.2.png
开发框架介绍对应上图
1.3.png
项目开发流程
1.4.png
原型图-首页、详情页
1.5.png
后台录入页
1.6.png

第二章:项目前后端流程打通

2.1、Node入口文件分析和目录初始化
2.1.png
2.2.png
2.3.png
2.4.png
2.2、创建四个jade视图及入口文件中处理
  1. 创建一个项目目录imooc
  2. 根目录下创建app.js与views目录
    终端打开项目并输入命令:
    npm init
    npm install express jade moment mongoose
  • 新建app.js,编写入口文件:
#app.js
var express =require('express')//加载express这个模块
var port = process.env.PORT || 3000//设置端口:process是全局变量
var app = express()//启动一个web服务器

app.set('views','./views')//设置视图的根目录
app.set('view engine','jade')//设置默认的模板引擎
app.listen(port)//监听端口
console.log('imooc started on port ' + port)//打印一条日志,控制台查看服务是否能成功启动

//添加路由
//index page
app.get('/index',function(req,res){//浏览器中访问页面是以get方法提交提交的,参数一位匹配规则,参数二为回调方法
    res.render('index',{
        title:'imooc 首页'
    })
})
//detail page
app.get('/movie/:id',function(req,res){
    res.render('detail',{
       title:'detail 详情页'
    })
})
//list page
app.get('/list',function(req,res){
    res.render('list',{
        title:'imooc 列表页'
    })
})
//admin page
app.get('/admin/movie',function(req,res){
    res.render('admin',{
        title:'imooc 后台录入页'
    })
})

项目结构为:


2.2.1.png

doctype
html
head
meta(chaset="utf-8")
title #{title}
body
h1 #{title}

#将以上代码直接copy在四个jade文件中且注意变换格式
#@将该项目在终端下打开并输入  node app.js,检测是否正确启动(也可以PORT=40000 node app.js 启动)
 #在浏览器的输入地址:localhost:3000/index,localhost:3000/list,localhost:3000/admin/movie,localhost:3000/admin/01查看是否正确启动。
2.3、伪造模板数据跑通前后端交互流程
2.3.1.png

修改目录结构-运用jade语法可以继承的优点以及公共区块的调用
在views中新建includes文件夹以及pages文件夹以及layout.jade布局文件,将原先views中的四个文件移动至pages文件中,在includes文件中新建head.jade文件与header.jade文件

layout.jade(copy代码时请将注释去掉,有可能报错)
  doctype
  html
   head
    meta(chaset="utf-8")
    title #{title}
    include ./includes/head  //- 将公用样式抽象成一个区块
  body
    include ./includes/header  //-网站标题或者logo
    block content  //-每个页面中的内容

在编写head.jade以及header.jade文件前,我们首先安装bower,然后通过bower安装bootstrap
npm install bower -g
bower install bootstrap@3.3.7 //如果不加@3.3.7会安装最新的,导致页面会出现一些显示问题。

head.jade (写入引入的公共样式)
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.jade
.container
.row
    .page-header
        h1 #{title}
        h3 六个周
改变pages中四个文件内容为:
extends ../layout

安装成功后的项目结构是这样的:

2.3.2.png

此时,我们再次终端输入命令node app查看是否可以正确访问

注意app.js中访问文件的路径修改

如果依然访问成功,我们继续下一步操作。
我们开始进行index.jade(首页)的文件编码:。

extends ../layout

block content
    .container
        .row
            each item in movies
                .col-md-2
                    .thumbnai
                        a(href="/movie/#{item._id}")
                            img(src="#{item/poster}",alt="#{item.title}")
                       .caption
                            h3 #{title}
                            p: a.btn.btn-primary(href="/movie/#{item._id}",role="button")
                              观看预告片

detail.jade(详情页)文件:

extends ../layout

block content
.container
    .row
        .col-md-7
            img(src="#{movie.poster}",alt="#{movie.title}",height="720")
        .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.jade(后台录入页)文件:

  extends ../layout

  block content
  .container
    .row
        form.form-horizontal(method="post",action="/admin/movie/new")
            .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#inputTitle.form-control(type="text",name="movie[doctor]",value="#{movie.doctor}")
            .form-group
                label.col-sm-2.control-label(for="inputCountry") 国家
                .col-sm-10
                    input#inputTitle.form-control(type="text",name="movie[country]",value="#{movie.country}")
            .form-group
                label.col-sm-2.control-label(for="inputLanguage") 语种
                .col-sm-10
                    input#inputTitle.form-control(type="text",name="movie[language]",value="#{movie.language}")
            .form-group
                label.col-sm-2.control-label(for="inputPoster") 海报地址
                .col-sm-10
                    input#inputTitle.form-control(type="text",name="movie[poster]",value="#{movie.poster}")
            .form-group
                label.col-sm-2.control-label(for="inputFlash") 片源地址
                .col-sm-10
                    input#inputTitle.form-control(type="text",name="movie[flash]",value="#{movie.flash}")
            .form-group
                label.col-sm-2.control-label(for="inputSummary") 电影简介
                .col-sm-10
                 textarea#inputSummary.form-control(type="text", name="movie[summary]", value="#{movie.summary}")
            .form-group
                .col-sm-offset-2.col-sm-10
             button.btn.btn-default(type="submit") 录入

list.jade(列表页)文件:

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.createAt).format('MM/DD/YYYY')}
                    td :a(target="_blank",href="../movie/#{item._id}") 查看
                    td :a(target="_blank",href="../admin/update/#{item._id}") 修改
                    td
                        button.btn.btn-danger.del(type="button",data_id="#{item._id}") 删除

伪造的静态数据:app.js

 var express = require('express')//加载express这个模块
var app = express()
var path =require('path')
var port = process.env.PORT || 3000//设置端口:process是全局变量

app.set('views','./views/pages') //设置视图的根目录
app.set('view engine','jade')//设置默认的模板引擎

var bodyParser = require('body-parser')
app.use(bodyParser.json())

app.use(express.static(path.join(__dirname,'bower_components')))
app.listen(port)//监听端口
console.log('六个周 started on port ' + port)//打印一条日志,控制台查看服务是否能成功启动

//添加路由
//index page
app.get('/index',function(req,res){//浏览器中访问页面是以get方法提交提交的,参数一位匹配  规则,参数二为回调方法
res.render('index',{
    title:'六个周 首页',
    movies:[{
        title:'Node.js指南',
        _id:1,
        poster:'http://img4.imgtn.bdimg.com/it/u=1178625225,3686148785&fm=26&gp=0.jpg'
    },{
        title:'Node.js指南',
        _id:2,
        poster:'http://img4.imgtn.bdimg.com/it/u=1178625225,3686148785&fm=26&gp=0.jpg'
    },{
        title:'Node.js指南',
        _id:3,
        poster:'http://img4.imgtn.bdimg.com/it/u=1178625225,3686148785&fm=26&gp=0.jpg'
    },{
        title:'Node.js指南',
        _id:4,
        poster:'http://img4.imgtn.bdimg.com/it/u=1178625225,3686148785&fm=26&gp=0.jpg'
    },{
        title:'Node.js指南',
        _id:5,
        poster:'http://img4.imgtn.bdimg.com/it/u=1178625225,3686148785&fm=26&gp=0.jpg'
    },{
        title:'Node.js指南',
        _id:6,
        poster:'http://img4.imgtn.bdimg.com/it/u=1178625225,3686148785&fm=26&gp=0.jpg'
    },{
        title:'Node.js指南',
        _id:7,
        poster:'http://img4.imgtn.bdimg.com/it/u=1178625225,3686148785&fm=26&gp=0.jpg'
    },{
        title:'Node.js指南',
        _id:8,
        poster:'http://img4.imgtn.bdimg.com/it/u=1178625225,3686148785&fm=26&gp=0.jpg'
    },{
        title:'Node.js指南',
        _id:9,
        poster:'http://img4.imgtn.bdimg.com/it/u=1178625225,3686148785&fm=26&gp=0.jpg'
    },{
        title:'Node.js指南',
        _id:10,
        poster:'http://img4.imgtn.bdimg.com/it/u=1178625225,3686148785&fm=26&gp=0.jpg'
    },]
})
})
//detail page
app.get('/movie/:id',function(req,res){
res.render('detail',{
   title:'detail 详情页',
   movie:{
       doctor:'六个周',
       counter:'China',
       title:'人生缘编程',
       year:2019,
       poster:'http://img4.imgtn.bdimg.com/it/u=1178625225,3686148785&fm=26&gp=0.jpg',
       language:'汉语',
       flash:'https://www.六个周.com/video/1226',
       summary:'1.,生命太短暂,不要去做一些根本没有人想要的东西。——Ash Maurya。2,如果你交给某人一个程序,你将折磨他一整天;如果你教某人如何编写程序,你将折磨他一辈子。——David Leinweber。3,软件设计有两种方式:一种方式是,使软件过于简单,明显没有缺陷;另一种方式是,使软件过于复杂,没有明显的缺陷。——C.A.R. Hoare。4,软件开发往往是这样:最开始的 90% 代码占用了开始的 90% 的开发时间;剩下 10% 代码同样需要 90% 的开发时间。——Tom Cargill'
   }
})
})
//admin page
app.get('/admin/movie',function(req,res){
res.render('admin',{
    title:'六个周 后台录入页',
    movie:{
        title:'',
        doctor:'',
        country:'',
        year:'',
        poster:'',
        flash:'',
        summary:'',
        language:''
    }
})
})
//list page
app.get('/admin/list',function(req,res){
res.render('list',{
    title:'六个周 列表页',
    movies:[
        {
            title:'Node.js指南',
            _id:1,
            doctor:'六个周',
            country:'China',
            year:2019,
            language:'汉语',
            flash:'https://www.jianshu.com/u/5842abb77bd1',
            summary:'1.,生命太短暂,不要去做一些根本没有人想要的东西。——Ash Maurya。2,如果你交给某人一个程序,你将折磨他一整天;如果你教某人如何编写程序,你将折磨他一辈子。——David Leinweber。3,软件设计有两种方式:一种方式是,使软件过于简单,明显没有缺陷;另一种方式是,使软件过于复杂,没有明显的缺陷。——C.A.R. Hoare。4,软件开发往往是这样:最开始的 90% 代码占用了开始的 90% 的开发时间;剩下 10% 代码同样需要 90% 的开发时间。——Tom Cargill'
        }
    ]
})

})

然后,容易出错的地方是bootstrap版本的安装导致的页面样式以及jade的代码缩进,经过一番调整后,启动'node app,效果图如下:

2.3.1.png 2.3.2.png 2.3.3.png 2.3.4.png
然后,至此先将代码提交至git于码云。

码云地址:https://gitee.com/ShaoBingYouTiao/movies


第三章:项目数据库实现

3.1、mongodb模式类型设计及编码以及数据库交互代码
3.1.1.png
3.1.2.png 3.1.3.png 3.1.4.png 3.1.5.png
3.1.6.png 3.1.7.png 3.1.8.png

在项目根目录下新建文件夹schemas(模式声明)、models(模型)、controllers。
分别在schemas中和models中添加movie.js文件,代码如下:

schemas-movie.js

var mongoose =require('mongoose')

var MovieSchema =new mongoose.Schema({
doctor:String,
title:String,
language:String,
country:String,
summary:String,
flash:String,
poster:String,
year:Number,
meta:{
    createaAt:{
        type:Date,
        default:Date.now()
    },
    updataAt:{
        type:Date,
        default:Date.now()
    }
}
})

MovieSchema.pre('save',function(next){
if(this.isNew){
    this.meta.createaAt = this.meta.updataAt =Date.now()
}else{
    this.meta.updataAt =Date.now()
}

next()
})

MovieSchema.statics = {
fetch:function(cb){
    return this
        .find({})
        .sort('meta.updateAt')
        .exec(cb)
},
fingdById:function(id,cb){
    return this
        .findOne({_id:id})
        .exec(cb)
}
}

module.exports =MovieSchema

models-movie.js

var mongoose =require('mongoose')
var MovieSchema = require('../schemas/movie')
var Movie = mongoose.model('Movie',MovieSchema)
module.exports = Movie

模式和模型代码编写结束,进入下一章节。


3.2、编写数据库交互代码

进入app.js文件,添加代码
需要在终端中安装underscore模块:npm install underscore

var mongoose = require('mongoose')
mongoose.connect('mongodb://localhost/imooc')
var Movie =require('./models/movie')
var _ =require('underscore')
#将app.js中的所有静态数据注释掉  

index路由与list路由中添加 Movie.fetch()方法
detail路由中添加 Movie.findById()方法
admin路由中在路由外添加一个方法:app.post()

// 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,mmovie){
        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({
        doctor:movieObj.doctor,
        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)
    })
}
})

还差一个在列表页点击更新的时候重新回到后台录入页,将表单中数据重新初始化到表单中,于是添加一个路由

//admin update
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:'六个周 后台更新页',
            movie: movie
        })
    })
}
})

最后还需要在admin录入页(admin.jade)添加一个隐藏的表单域,存储电影ID,用于更新

input(type="hidden",name="movie[_id]",value="#{movie._id}")

然后我们开始进行测试:

  • 打开终端输入 mongod
  • node app

后台电影录入页:http://localhost:3000/admin/movie

addMovie.png
点击录入后跳转至添加项的详情页:
detail.png
电影首页:localhost:3000/index
index
后台列表页:localhost:3000/admin/list
list.png
4.1删除功能及项目生成配置文件

删除功能这里我们需要使用jQuery,通过异步请求进行删除。
在此之前,我们需要改变项目结构,将bower_components中内容放在新建的一个public文件中。--这里我们需要用的bower的一个特性(可以指定将bower下载的东西放在哪个目录下)。

  • 项目根目录下新建public文件夹
  • 项目根目录下新建 .bowerrc文件,在本文件下写入如下代码:
    {
    "directory": "public/libs"
    }
  • 删除bower_components文件夹
  • 终端中重新安装bootstrap:bower install bootstrap@3.3.7
  • 同时修改head.jade的bootstrap引入路径,添加/libs
  • 最好修改app.js中的bower_components改为public。至此,可以再次输入各个路径进行测试 。

测试成功没有问题,我们继续添加删除的功能,在public文件下新建文件js,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中添加代码

 script(src="/js/admin.js")

在app.js中添加删除路由:

//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.send({success:1})
        }
    })
}
})
然后将修改的代码文件上传至码云:https://gitee.com/ShaoBingYouTiao/movies

总结:至此建站攻略一期完毕,本项目对于很多不熟悉jade的同学来说,可能会对写jade代码处有所抵触,但是如果你按着我上面的思路一点一点写出来的话还是很有收获的。本项目中的代码给出很可能~很可能的存在一两个单词的拼写错误导致你在运行项目的时候出现问题,这个时候你要细细查看原因,我已经尽可能的将正确代码贴上,如有问题,欢迎留言,我会在看到时及时回复。

关于本项目的升级、二期学习与文档整理我会尽快更新,先将地址贴上:
二期学习视频慕课网地址:https://www.imooc.com/learn/197
二期学习简书文档整理地址:https://www.jianshu.com/p/a9192427597a

上一篇下一篇

猜你喜欢

热点阅读