What can node.js do? I still don’t know what aspects he uses are quite widely, and I have no chance to come into contact with such projects. Just because I liked it, I made a website and backend in my spare time. I have deeply understood one truth that is, if you like a technology, you can play with it, but if you use it in a project, you must spend some time solving many problems.
Techniques used:
express + jade
sqlite + sequelize
redis
1. About Jade
Support include. For example: include ./includes/header header is a partial view, similar to the asp.net user control.
Support extends. For example: extends ../layout uses the master page layout.
The for loop is so simple.
The code copy is as follows:
each item in userList (the variable passed to the front end by the userList server)
tr
td #{item.username}
td #{item.telephone}
td #{item.email}
Like append:
The code copy is as follows:
extends ../admin_layout
append head
link(rel='stylesheet', href='/stylesheets/font-awesome.css')
script(src='/javascripts/bootstrap.js')
script(src='/javascripts/bootstrap-wysiwyg.js')
script(src='/javascripts/jquery.hotkeys.js')
Block content
append will place all steps and styles behind the head of the master page.
2.sequelize The framework for implementing ORM. Support sqlite mysql mongodb
Defining the model (article):
The code copy is as follows:
var Article = sequelize.define('Article',{
title:{
type:Sequelize.STRING,
validate:{}
},
content:{type:Sequelize.STRING,validate:{}},
icon:{type:Sequelize.STRING,validate:{}},
iconname:{type:Sequelize.STRING},
sequencing:{type:Sequelize.STRING,validate:{}}
},{
classMethods:{
//Article classification
getCountAll:function(objFun){
}//end getCountAll
}//end classMethods
});
Article.belongsTo(Category);
Article.belongsTo(Category); Each article has a category.
I wrote the paging-related methods to the time when initializing sequelize. In this way, there will be this method (pageOffset, pageLimit) when defining each model.
The code copy is as follows:
var sequelize = new Sequelize('database', 'username', 'password', {
// sqlite! now!
dialect: 'sqlite',
// the storage engine for sqlite
// - default ':memory:'
storage: config.sqlitePath,
define:{
classMethods:{
pageOffset:function(pageNum){
if(isNaN(pageNum) || pageNum < 1){
pageNum = 1;
}
return (pageNum - 1) * this.pageLimit();
},
pageLimit:function(){
return 10; // 10 items are displayed per page
},
totalPages:function(totalNum){
var total =parseInt((totalNum + this.pageLimit() - 1) / this.pageLimit()),
arrayTotalPages = [];
for(var i=1; i<= total; i++){
arrayTotalPages.push(i);
}
return arrayTotalPages;
}
},
instanceMethods:{
}
}
});
use:
The code copy is as follows:
Article.findAndCountAll({include:[Category],offset:Article.pageOffset(req.query.pageNum), limit:Article.pageLimit()}).success(function(row){
res.render('article_list', {
title: 'Article Management',
articleList : row.rows,
pages:{
totalPages:Article.totalPages(row.count),
currentPage:req.query.pageNum,
router:'article'
}
});
});
Save the model:
The code copy is as follows:
exports.add = function(req, res) {
var form = new formidable.IncomingForm();
form.uploadDir = path.join(__dirname, '../files');
form.keepExtensions = true;
form.parse(req, function(err, fields,files){
var //iconPath = files.icon.path,
//index = iconPath.lastIndexOf('/') <= 0 ? iconPath.lastIndexOf('//') : iconPath.lastIndexOf('/') ,
icon = path.basename(files.icon.path), // iconPath.substr(index + 1,iconPath.length - index),
iconname = files.icon.name;
var title = fields.title;
id = fields.articleId;
title = fields.title,
content = fields.content,
mincontent = fields.mincontent,
sequencing=fields.sequencing == 0 ? 0 : 1,
category = fields.category;
Article.sync(); //Create table if it does not exist.
Category.find(category).success(function(c){
var article = Article.build({
title : title,
content:content,
mincontent:mincontent,
icon:icon,
iconname:iconname,
sequencing:sequencing
});
article.save()
.success(function(a){
a.setCategory(c);
return res.redirect('/admin/article');
});
}); //end category
});
}
path.basename:
The code copy is as follows:
//iconPath = files.icon.path,
//index = iconPath.lastIndexOf('/') <= 0 ? iconPath.lastIndexOf('//') : iconPath.lastIndexOf('/') ,
icon = <strong>path.basename</strong>(files.icon.path), // iconPath.substr(index + 1,iconPath.length - index),
Get the file name, for example: /a/b/aa.txt => aa.txt. At first I used intercepting strings, which could also be implemented, but if the operating system is different, there will be problems. mac uses '/' . The following is '//' in window. I also discovered the problem after the deployment is completed. Later I found out that path.basename was replaced directly (if you read the document less, you will suffer a loss). I have a good impression of node.js to add 1 point. :)
3. Redis caches frequently queries and rarely changes data.
The code copy is as follows:
getCountAll:function(objFun){
redis.get('articles_getCountAll', function(err,reply){
if(err){
console.log(err);
return;
}
if(reply === null){
db.all('SELECT count(articles.CategoryId) as count,categories.name,categories.id FROM articles left join categories on articles.categoryID = categories.id group by articles.CategoryId ', function(err,row){
redis.set('articles_getCountAll',JSON.stringify(row));
objFun(row);
});
}else{
objFun(reply);
}
});
This method is defined in the model layer. Because it is Express, use the mvc method to develop as much as possible. In fact, route implements the controller layer function (route folder, which should be named controller).