Home > Web Front-end > JS Tutorial > body text

node.js blog project development notes

亚连
Release: 2018-05-29 18:02:03
Original
2181 people have browsed it

This article summarizes the relevant steps and knowledge points for node.js blog project development. Interested friends can refer to it.

Modules that need to be installed

  • body-parser parses post requests

  • cookies Read and write cookies

  • express Build server

  • markdown Markdown syntax parsing generator

  • mongoose operation Mongodb database

  • swig template parsing engine

Directory structure

  • db database storage directory

  • models database model file directory

  • public public file directory (css, js, img)

  • routers routing file directory

  • schemas database structure file

  • views template view file directory

  • app.js startup file

  • package.json

app.js file

1. Create application and listening port

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");
});
Copy after login

2. Configure application template

  • Definition The template engine used app.engine('html',swig.renderFile) Parameter 1: The name of the template engine, which is also the suffix of the template file Parameter 2: Indicates the method used to parse and process the template content

  • Set the directory where template files are stored app.set('views','./views')

  • Register the template engine used app.set('view engine' ,'html')

3. Use the template engine to parse the file

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

4.Needed during the development process Cancel restrictions on template caching

swig.setDefaults({
 cache: false
});
app.set('view cache', false);
Copy after login

5. Set up static file hosting

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

Partition Module

  • Front module

  • Backend module

  • API module

// 根据不同的功能划分模块
app.use('/',require('./routers/main'));
app.use('/admin',require('./routers/admin'));
app.use('/api',require('./routers/api'));
Copy after login

For the admin module 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;
Copy after login

Frontend routing template

main module
/Homepage
/view content page

api module

/Homepage
/register User registration
/login User login
/comment Comment acquisition
/comment/post Comment submission

Backend (admin) Routing template

Homepage

/Backend Homepage

User Management

/user User List

Category Management

/category Category List
/category/add Category Add
/category/edit Category Modification
/category/delete Category Delete

Article content management

/article nei content list
/article/add content addition
/article/edit content modification
/article/delete Content deletion

Comment content management

/comment Comment list
/comment/delete Comment deletion

Function development order

Function module development sequence

  • User

  • Column

  • Content

  • Comments

Encoding order

  • Defining the design data storage structure through Schema

  • Functional logic

  • Page display

Connect to database (mongoDB)

Start MongoDB service Terminal:

mongod --dbpath=G:\data\db --port=27017

Start the service and set the storage address and port of the database

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");
    });
  }
});
Copy after login

Define the data table structure and model

For the user data table (users.js) in the schema folder:

var mongoose = require('mongoose');
module.exports = new mongoose.Schema({
  // 用户名
  username:String,
  // 密码
  password:String
});
Copy after login

Create the user.js model class in the models directory

var mongoose = require('mongoose');
var userSchema = require('../schemas/users');
module.exports = mongoose.model('User',userSchema);
Copy after login

Process user registration

The front-end submits the user name and password through ajax

url: /api/register

The back-end submits to the front-end ( POST) data analysis

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); // 数据保存成功 
  });
});
Copy after login

Usage of cookies module

Global (app.js) registration usage

// 设置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 
}));
Copy after login

swig template engine

  1. Variables

    {{ name }}

2. Attributes

{{ student.name }}

3.if judgment

{ % if name === 'Guo Jing ' % }

hello Brother Jing

{ % endif % }

4.for loop

// arr = [1, 2, 3]

{ % for key, val in arr % }

{ { key } } -- { { val } }

{ % endfor % }

5.set command

is used to set a variable and reuse it in the current context

{% set foo = [0, 1 , 2, 3, 4, 5] %}

{% extends 'layout.html' %} // Inherit a certain HTML template
{% include 'page.html' %} // Include A template to the current position
{% block main %} xxx {% endblock %} //Rewrite a certain block

6.autoescape automatic encoding

When you want to Display the HTML code generated by the backend in a certain p. It will be automatically encoded when the template is rendered, and
will be displayed in the form of a string. This situation can be avoided by:

<p id="article-content" class="content">
  {% autoescape false %}
  {{ data.article_content_html }}
  {% endautoescape %}
</p>
Copy after login

User Management and Paging

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(){ 
});
Copy after login

数据分页管理

两个重要方法

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 传给页面
});
Copy after login

文章的表结构

// 对于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 
});
Copy after login

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()));
});
Copy after login

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);
Copy after login

使文本域支持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();
  }
});
Copy after login

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();
    }
  });
});
Copy after login

随机用户头像生成

// 引入对应的库
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;
Copy after login

orm表单提交的小问题

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

上面是我整理给大家的,希望今后会对大家有帮助。

相关文章:

javascript实现文件拖拽事件

vue文件树组件使用详解

vue全局组件与局部组件使用方法详解

The above is the detailed content of node.js blog project development notes. For more information, please follow other related articles on the PHP Chinese website!

source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template