基於 Express 與 Mongodb 的簡易 實現一個多人 blog

項目參考:

N-blog: github.com/nswbmw/N-bl…javascript

感謝做者大大詳盡的指導,後端基本用的做者原始的架構css

關於 fetchAPI, express 的原理沒有深刻了解,整體作了點搬磚的活前端

項目地址:

SimpleBlog: github.com/ShiroCheng/…java

該項目已布在公網服務器上,demo地址:http://120.78.134.26node

頁面演示:

  • 主頁:

Snipaste_2018-06-27_02-12-15

  • 特定文章頁:

Snipaste_2018-06-27_02-12-47

  • 發佈文章頁:

Snipaste_2018-06-27_02-13-17

  • 電影頁:

Snipaste_2018-06-27_02-13-34

使用方法:

環境配置:預裝 MongoDB, Node.jsjquery

mkdir mongodb/data
mongod --dbpath=mongodb/data
git clone https://github.com/Ubilabs-NicholasCheng/SimpleBlog.git
cd SimpleBlog
npm i
vim config/default.js #修改端口 80->3000
node index.js
複製代碼

以後,訪問 localhost:3000git

項目目錄結構:

  1. lib: 定義實體的數據結構github

  2. models: 操做數據庫的文件web

  3. public: 靜態文件,如樣式、圖片,包括用戶上傳的頭像等mongodb

  4. routes: 存放路由文件

  5. views: 用於渲染的視圖文件

  6. index.js: 程序主文件

  7. package.json: 項目名、描述、做者、依賴等等信息

  8. config: 項目的配置信息,服務器端口,鏈接的數據庫端口等

    遵循 MVC 的開發模式

前端組件庫

  1. Materilazie + GoogleIcons: Material Design 風格的組件庫與 Google 圖標
  2. github-markdown-css: 添加 github markdown 風格樣式
  3. highlight.js: 代碼語法高亮
  4. simpleMDE: markdown 的樣式支持
  5. jquery: 實現動畫等功能
  6. materialize.min.js : materialize 組件的js庫

後端依賴模塊

  1. express: web 框架
  2. express-session: session 中間件
  3. connect-mongo: 將 session 存儲於 mongodb,結合 express-session 使用
  4. connect-flash: 頁面通知的中間件,基於 session 實現
  5. ejs: 模板
  6. express-formidable: 接收表單及文件上傳的中間件
  7. config-lite: 讀取配置文件
  8. marked: markdown 解析
  9. moment: 時間格式化
  10. mongolass: mongodb 驅動
  11. objectid-to-timestamp: 根據 ObjectId 生成時間戳
  12. sha1: sha1 加密,用於密碼加密
  13. winston: 日誌
  14. express-winston: express 的 winston 日誌中間件

主要功能

  1. 多用戶註冊登陸
  2. 發表、修改、刪除文章
  3. 發表、刪除評論
  4. 添加視頻

實現方法

  1. 服務器後端框架:express,使用express 控制路由,動態渲染特定界面
  2. 數據庫驅動:Mongolass,服務器與數據庫交互的中間件
  3. 模板引擎:ejs,動態渲染前端頁面

以登錄後的用戶建立 movies 爲實例:

定義 Movie 的 schema:

// lib/mongo.js
const Mongolass = require('mongolass')
const mongolass = new Mongolass()

/********* Movie Schema **********/
exports.Movie = mongolass.model('Movie', {
    title:{
        type: 'string',
        required: true
    },
    src:{
        type: 'string',
        required: true
    }
})

// 創建索引
exports.Movie.index({
        postId:1,
        _id: 1
    }).exec()
複製代碼

Movie 這個 model 中定義的方法,加載全部電影,刪除與獲取特定的電影:

(Mongolass 這個驅動的方法與mongodb的數據庫api一致,使用起來很直觀)

// model/movies.js
const Movies = require('../lib/mongo').Movie

module.exports = {
    create: function create (movie) {
        return Movies.create(movie).exec()
    },

    // 經過電影 id 獲取一部電影
    getMovieById: function getMovieById(movieId) {
        return Movies.findOne({
            _id: movieId
        }).exec()
    },

    // 經過電影 id 刪除一部電影
    delMovieById: function (movieId) {
        return Movies.deleteOne({
            _id: movieId
        }).exec()
    },

    //找到全部的電影
    getMovies: function () {
        return Movies.find({
        }).exec()
    }
}
複製代碼

定義表單的方法爲 post,input 的 name 爲屬性名。

// views/createMovies.ejs
<form class="col s12 m12 " method="POST">
      // more code here 
      <input name="title" id="title" type="text" class="validate">
      <input name="src" id="src" type="text" class="validate" >
      // more code here 
</form>
複製代碼

express 的路由中提供了處理請求的方法,input 的 value 將掛載在 req.fileds.name 這一屬性下:

使用 MovieModel 的 create方法,在數據庫對應的表中插入這一條用戶新建立的數據,若該表不存在則會建立該表。

// routes/movies.js
// 建立電影頁
router.post('/create', function(req, res, next) {

    const movieId = req.fields.movieId
    const title = req.fields.title
    const src = req.fields.src

    // 校驗參數
    try {
        if (!src.length) {
            throw new Error('Please write movie src!')
        }
    } catch (e) {
        req.flash('error', e.message)
        return res.redirect('back')
    }

    const movie = {
        movieId: movieId,
        title: title,
        src: src
    }

    MovieModel.create(movie)
        .then(function() {
            req.flash('success', 'create movie successfully!')
            // 建立成功後跳轉到上一頁
            res.redirect('/movies')
        })
        .catch(next)

})
複製代碼

同時引入了 checkLogin 方法,判斷用戶是否登錄,登錄後的用戶纔有權限建立電影:

// middlewares/checkLogin.js
module.exports = {
    checkLogin: function checkLogin(req, res, next) {
        if (!req.session.user) {
            //設置當前的錯誤爲未登陸
            req.flash('error', '未登陸')
            return res.redirect('/signIn')
        }
        next()
    },
    checkNotLogin: function checkNotLogin(req, res, next) {
        if (req.session.user) {
            req.flash('error', '已登陸')
            return res.redirect('back') //若已登陸返回原頁面
        }
        next()
    }
}
複製代碼

使用 MovieModel 中定義的 getMovies() 方法,查詢到 movies 表下的全部記錄,使用res.render() 方法渲染ejs模板,並傳入這些查詢到的記錄。

// routes/movies.js
// 顯示電影頁
router.get('/', function(req, res, next) {
    MovieModel.getMovies()
        .then(function (movies) {
            res.render('movies', {
                movies: movies
            })
        })
        .catch(next)
})
複製代碼

前端的 ejs 模板獲取到服務器響應傳入的多條記錄,使用 forEach方法將其依次渲染:

(components/movies-content.ejs 做爲組件,movies.ejs 使用include方法渲染多個 movies-content.ejs組件 )

//  views/components/movies-content.ejs 
<label><h5 class="white-text center-align" style="margin-top: 230px;">
      <%= movie.title %></h5></label>
   <div class="responsive-video center-align"  controls>
      <iframe width="853" height="480" src="<%= movie.src %>" frameborder="0" allowfullscreen>		</iframe>
   </div>
// views/movies.ejs
<%- include('header') %>
    <% movies.forEach(function (movie) { %>
        <%- include('components/movie-content', { movie: movie }) %>
    <% }) %>
<%- include('footer') %>
複製代碼

這樣,就完成了一個簡單的 用戶提交表單 -> 服務端存儲數據到數據庫 -> 服務端重渲染視圖 的先後端交互流程 。

項目的設計還涉及到用戶密碼的hash加密,時間日期的格式化,日誌的保存等,配置文件的更改及代碼風格等,但簡單的流程就如上所示。

TO DO

  • 增長用戶文章的分類與標籤功能
  • 增長文章的分頁顯示功能
  • 增長用戶的文章收藏功能
  • 增長電影的分類與標籤功能
  • 增長用戶的電影收藏功能
相關文章
相關標籤/搜索