美文网首页Node.js
node+mongodb 建站攻略(一期)

node+mongodb 建站攻略(一期)

作者: 六个周 | 来源:发表于2018-10-16 06:33 被阅读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

    相关文章

      网友评论

        本文标题:node+mongodb 建站攻略(一期)

        本文链接:https://www.haomeiwen.com/subject/bqrczftx.html