首頁 > web前端 > js教程 > node.js部落格專案開發經驗分享

node.js部落格專案開發經驗分享

小云云
發布: 2018-03-19 09:43:17
原創
2046 人瀏覽過

本文主要為大家總結了node.js部落格專案開發的相關步驟以及知識點分享,有興趣的朋友參考下,希望能幫助大家。

需要安裝的模組

  • #body-parser 解析post請求

  • cookies 讀寫cookie

  • express 建立伺服器

  • markdown Markdown語法解析產生器

  • #mongoose 操作Mongodb資料庫

  • swig 範本解析引擎

目錄結構

  • db 資料庫儲存目錄

  • models 資料庫模型檔案目錄

  • public 公用檔案目錄(css,js ,img)

  • routers 路由檔案目錄

  • #schemas 資料庫結構檔

  • views 範本視圖檔案目錄

  • app.js 啟動檔案

  • package.json

app.js 文件

1.建立應用程式、監聽埠

const app = express();

app.get('/',(req,res,next) => {
  res.send("Hello World !");
});
app.listen(3000,(req,res,next) => {
  console.log("app is running at port 3000");
});
登入後複製

2.設定套用範本

  • 定義使用的模板引擎app.engine('html',swig.renderFile) 參數1:模板引擎的名稱,同時也是模板檔案的後綴參數2:表示用於解析處理模板內容的方法

  • 設定模板檔案存放的目錄app.set('views','./views')

  • #註冊所使用的模板引擎app.set(' view engine','html')

3.用模板引擎去解析檔案

/**
 * 读取views目录下的指定文件,解析并返回给客户端 
 * 参数1:模板文件
 * 参数2:给模板传递的参数 
 */
 
res.render('index',{
  title:'首页 ',
  content: 'hello swig'
});
登入後複製

4.開發過程中需要取消範本快取的限制

swig.setDefaults({
 cache: false
});
app.set('view cache', false);
登入後複製

#5.設定靜態檔案託管

 // 当用户访问的是/public路径下的文件,那么直接返回
app.use('/public',express.static(__dirname + '/public'));
登入後複製


#分割模組

前台模組


# 後台模組


##API模組

// 根据不同的功能划分模块
app.use('/',require('./routers/main'));
app.use('/admin',require('./routers/admin'));
app.use('/api',require('./routers/api'));
登入後複製

對於管理員模組admin.js



var express = require('express');
var router = express.Router();

// 比如访问 /admin/user
router.get('/user',function(req,res,next) {
  res.send('User');
});
module.exports = router;
登入後複製





##前台路由+ 範本


main 模組

/ 首頁
/view 內容頁


##api模組


/首頁

/register 使用者註冊
/login 使用者登入

/comment 評論取得

/comment/post 評論提交


#後台(admin)路由+範本

首頁

/ 後台首頁

使用者管理

##/ user 使用者清單

    分類管理
  • /category 分類清單
  • /category/add 分類新增
  • /category/edit 分類修改

    /caterory /delete 分類刪除

  • 文章內容管理

  • /article nei內容清單
  • /article/add 內容新增

    /article/edit 內容修改

    /article/delete 內容刪除

評論內容管理

  • #/comment 評論清單

    /comment/delete 評論刪除

  • 功能開發順序
  • 功能模組開發順序
  • 使用者


#欄位


內容


評論

編碼順序

透過Schema定義設計資料儲存結構

功能邏輯

#頁面展示

#連線資料庫(mongoDB)

啟動MongoDB服務端:
mongod --dbpath=G:\data\db --port=27017


啟動服務設定資料庫的儲存位址以及連接埠

var mongoose = require('mongoose');
// 数据库链接
mongoose.connect("mongodb://localhost:27017/blog",(err) => {
  if(err){
    console.log("数据库连接失败");
  }else{
    console.log("数据库连接成功");
   // 启动服务器,监听端口 
   app.listen(3000,(req,res,next) => {
      console.log("app is running at port 3000");
    });
  }
});
登入後複製

定義資料表結構和模型


對於使用者資料表(users.js)在schema資料夾下:

var mongoose = require('mongoose');
module.exports = new mongoose.Schema({
  // 用户名
  username:String,
  // 密码
  password:String
});
登入後複製

在models目錄下建立user.js模型類別

##

var mongoose = require('mongoose');
var userSchema = require('../schemas/users');
module.exports = mongoose.model('User',userSchema);
登入後複製


#處理使用者註冊

前端透過ajax提交使用者名稱和密碼


url: /api/register

後端對前端提交(POST)的資料解析

var bodyParser = require('body-parser');
// bodyParser 配置
// 通过使用这一方法,可以为req对象添加一个body属性
app.use( bodyParser.urlencoded({extended:true}));

// 在api模块中:
// 1.可以定义一个中间件,来统一返回格式
var responseData;
router.use( function(req,res,next){ // path默认为'/',当访问该目录时这个中间件被调用
  responseData = {
     code:0,
    message:''
  };
  next();
});

router.post('/register',(req,res,next) => {
  console.log(req.body);
  // 去判断用户名、密码是否合法
  // 判断是否用户名已经被注册
  // 通过 res.json(responseData) 给客户端返回json数据
  
  // 查询数据库
  User.findOne({  // 返回一个promise对象
      username: username
  }).then(function( userInfo ) {
      if( userInfo ){ // 数据库中有该条记录
      ...
     res.json(responseData);
     return;
    }
    // 给数据库中添加该条信息
    var user = new User({ username:username,password:password });
    return user.save(); // 返回promise对象
  }).then(function( newUserInfo ){
      console.log(newUserInfo);
    res.json(responseData); // 数据保存成功 
  });
});
登入後複製


#cookies 模組的使用

全域(app.js)註冊使用

// 设置cookie
// 只要客户端发送请求就会通过这个中间件
app.use((req, res, next) => {
  req.cookies = new cookies(req, res);

  /**
   * 解析用户的cookies信息
   * 查询数据库判断是否为管理员 isAdmin
   * 注意:查询数据库是异步操作,next应该放在回调里边
   */
  req.userInfo = {};
  if (req.cookies.get("userInfo")) {
    try {
      req.userInfo = JSON.parse(req.cookies.get("userInfo"));
      // 查询数据库判断是否为管理员
      User.findById(req.userInfo._id).then(function (result) {
        req.userInfo.isAdmin = Boolean(result.isAdmin);
        next();
      });
    } catch (e) {
      next();
    }
  } else {
    next();
  }
});

// 当用户登录或注册成功之后,可以为其设置cookies
req.cookies.set("userInfo",JSON.stringify({
   _id:result._id,
  username:result.username 
}));
登入後複製

swig範本引擎

#1.變數

##{{ name } }

2.屬性


{{ student.name }}


3.if判斷

{ % if name === '郭靖' % }

hello 靖哥哥

{ % endif % }

##4. for迴圈


// arr = [1, 2, 3]######{ % for key, val in arr % }###########{ % endfor % }############5.set指令###### ####用來設定一個變量,在目前上下文中重複使用#########{% set foo = [0, 1, 2, 3, 4, 5] %}###### #{% extends 'layout.html' %} // 繼承某一個HTML模板###{% include 'page.html' %} // 包含一個模板到目前位置###{% block main %} xxx { % endblock %} //重寫某一區塊############6.autoescape 自動編碼#######

当想在某个p中显示后端生成的HTML代码,模板渲染时会自动编码,
以字符串的形式显示。通过以下方式,可以避免这个情况:

<p id="article-content" class="content">
  {% autoescape false %}
  {{ data.article_content_html }}
  {% endautoescape %}
</p>
登入後複製

用户管理和分页

CRUD用户数据

const User = require(&#39;../models/user&#39;);

// 查询所有的用户数据
User.find().then(function(users){

});

// 根据某一字段查询数据
User.findOne({
  username:username
}).then(function(result){

});

// 根据用户ID查询数据
User.findById(id).then(function(user){

});

// 根据ID删除数据
User.remove({
  _id: id
}).then(function(){

});

// 修改数据
User.update({
  _id: id
},{
  username: name
}).then(function(){ 
});
登入後複製

数据分页管理

两个重要方法

limit(Number): 限制获取的数据条数

skip(Number): 忽略数据的条数 前number条

忽略条数:(当前页 - 1) * 每页显示的条数

// 接收传过来的page
let query_page = Number(req.query.page) || 1;
query_page = Math.max(query_page, 1); // 限制最小为1
query_page = Math.min(Math.ceil(count / limit), query_page); // 限制最大值 count/limit向上取整


var cur_page = query_page; // 当前页
var limit = 10; // 每页显示的条数
var skip = (cur_page - 1) * limit; //忽略的条数

User.find().limit(limit).skip(skip).then(function(users){
  ...
 // 将当前页 page 传给页面
 // 将最大页码 maxPage 传给页面
});
登入後複製

文章的表结构

// 对于content.js
var mongoose = require(&#39;mongoose&#39;);
var contentSch = require(&#39;../schemas/contentSch&#39;);

module.exports = mongoose.model(&#39;Content&#39;,contentSch);


// contentSch.js
module.exports = new mongoose.Schema({
  
  // 关联字段 - 分类的id
  category:{
    // 类型
    type:mongoose.Schema.Types.ObjectId,
    // 引用
    ref:&#39;Category&#39; 
  },
  
  // 内容标题
  title: String,
  
  // 简介
  description:{
    type: String,
    default: &#39;&#39; 
  },
  
  // 内容
  content:{
    type:String,
    default:&#39;&#39;
  }
});

// 文章查询时关联category字段
Content.find().populate(&#39;category&#39;).then(contents => {
  // 那么通过这样的方式,我们就可以找到Content表中的
  // 关联信息   content.category.category_name 
});
登入後複製

MarkDown语法高亮

在HTML中直接使用

<link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/default.min.css">
<script src="http://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js"></script>

<script src="https://cdn.bootcss.com/marked/0.3.17/marked.min.js"></script>

// marked相关配置
marked.setOptions({
  renderer: new marked.Renderer(),
  gfm: true,
  tables: true,
  breaks: false,
  pedantic: false,
  sanitize: true,
  smartLists: true,
  smartypants: false,
  highlight: function (code) {
    return hljs.highlightAuto(code).value;
  }
});

// MarkDown语法解析内容预览
$(&#39;#bjw-content&#39;).on(&#39;keyup blur&#39;, function () {
  $(&#39;#bjw-previous&#39;).html(marked($(&#39;#bjw-content&#39;).val()));
});
登入後複製

node环境中使用

// 在模板页面引入默认样式
<!--语法高亮-->
<link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/default.min.css">

const marked = require(&#39;marked&#39;);
const hljs = require(&#39;highlight.js&#39;);

// marked相关配置
marked.setOptions({
  renderer: new marked.Renderer(),
  gfm: true,
  tables: true,
  breaks: false,
  pedantic: false,
  sanitize: true,
  smartLists: true,
  smartypants: false,
  highlight: function (code) {
    return hljs.highlightAuto(code).value;
  }
});

// 对内容进行markdown语法转换
data.article_content_html = marked(article.content);
登入後複製

使文本域支持Tab缩进

$(&#39;#bjw-content&#39;).on(&#39;keydown&#39;,function(e){
  if(e.keyCode === 9){ // Tab键
     var position = this.selectionStart + 2; // Tab === 俩空格
    this.value = this.value.substr(0,this.selectionStart) + " " + this.value.substr(this.selectionStart);
    this.selectionStart = position;
    this.selectionEnd = position;
    this.focus();
    e.preventDefault();
  }
});
登入後複製

layer 弹框

// 显示弹框
function showDialog(text, icon, callback) {
  layer.open({
    time: 1500,
    anim: 4,
    offset: &#39;t&#39;,
    icon: icon,
    content: text,
    btn: false,
    title: false,
    closeBtn: 0,
    end: function () {
      callback && callback();
    }
  });
});
登入後複製

随机用户头像生成

// 引入对应的库
const crypto = require(&#39;crypto&#39;);
const identicon = require(&#39;identicon.js&#39;);

// 当用户注册时,根据用户的用户名生成随机头像
let hash = crypto.createHash(&#39;md5&#39;);
hash.update(username);
let imgData = new identicon(hash.digest(&#39;hex&#39;).toString());
let imgUrl = &#39;data:/image/png;base64,&#39;+imgData;
登入後複製

orm表单提交的小问题

当使用form表单提交一些代码的时候,会出现浏览器拦截的现象,原因是:浏览器误以为客户进行xss攻击。所以呢解决这个问题也很简单,就是对提交的内容进行base64或者其他形式的编码,在服务器端进行解码,即可解决。

以上是node.js部落格專案開發經驗分享的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板