NodeJs——(16)用Nodejs 4.X版本,制作一个微博网站(多图,详细步骤)-阿里云开发者社区

开发者社区> 开发与运维> 正文
登录阅读全文

NodeJs——(16)用Nodejs 4.X版本,制作一个微博网站(多图,详细步骤)

简介: (填坑中,预计7月底完成) 最后更新时间7/28晚, 更新页面基本样式已有 范例网址:121.41.66.68 【0】涉及到的框架、引擎、数据库: ① express 4.X ② jade ③ mysql 5.6.x   注: ①内容较长,我会尽力把整个框架、结构、顺序、思考方式说明白。 ②基础是《node.js开发指南》这本书,作者:BYVoid。但他书的版本较

(填坑中,预计7月底完成)

最后更新时间7/28晚,

更新页面基本样式已有

范例网址:121.41.66.68


0】涉及到的框架、引擎、数据库:

express 4.X

jade

mysql 5.6.x

 

注:

①内容较长,我会尽力把整个框架、结构、顺序、思考方式说明白。

②基础是《node.js开发指南》这本书,作者:BYVoid。但他书的版本较老,很多东西现在已经无法应用,故进行更新,使用目前普遍的express 4.x版本(原书似乎是2.X版本),mysql(原书是mongodb),jade(原书是ejs

 

1】基本需求:

①有首页;

②支持注册;

③支持登录、登出;

④可以发表博客,发表的博客可以保存到数据库;

⑤可以查看博客,博客从数据库中读取,为了简化,这里设置为查看所有人的博客;

⑥查看博客时,初始查看的数量有限,但可以无限加载新的博客,直到查看完全部博客;

⑦一定程度上实现多语言(即可以切换显示的语言版本),但由于复杂度所限,因此只部分实现(但框架已建立好,可以通过继续完善代码实现整体的国际化);

⑧根据登录状态,对可以访问的页面进行控制(某些允许某些禁止)

 

 

2】前后端交互的简单过程:



3】关于客户端请求的几种情况(涉及到数据库的)



4npm

npm是包管理器,在新版本里是默认安装好的,可以输入:

npm -v

来查看npm的版本

 

 

 

5express框架:

首先安装基础的express框架,他是封装好的web开发框架,里面包含了:

①路由控制、

log显示、

③解析客户端请求、

cookies解析、

⑤静态文件的控制

等多种功能。

 

安装前注:

①有的人只需要简单的

npm install -g express

npm install -g express-generator

就可以愉快的跑起express了,有的人就像向我一样苦逼,尝试各种办法,最后勉强可以用。

 

如果在这两行命令后,输入(V是大写的)

express -V

会返回版本号,那么直接跳到最后来看,如果不是这样,可以参考我写的记录来安装。

 

或者直接看后面的终极解决方案

 

 

 

express设置全局方法:

ln -s /usr/nodejs4.4.7/node-v4.4.7-linux-x64/bin/express /usr/local/bin/express

其他需要全局的方法,理论上同理,即将nodejs安装目录下的bin文件夹下的模块,映射到/usr/local/bin/同名文件即可

 



express命令可以使用的人:

输入:

express -t jade myblog

 

效果是建立一个文件夹名为myblog的文件夹,里面会有一些文件。

正常如下图:



 

cd myblog

npm install

 

这时,npm会根据package.json来安装一些东西。

 

按提示输入:

SET DEBUG=myblog:*

npm start

 

可以启动项目。

本机的话,通过访问http://127.0.0.1:3000/ 来查看效果

服务器的话,访问其公网ip,端口是3000

 

查看package.json

"scripts": {
  "start": "node ./bin/www"
},

 

这条属性告诉我们,需要通过bin文件夹下的www来启动,这也就是上面npm start命令的作用。

 

www文件应该是设置自启动的,然而我这里并不需要。但若直接启动app.js是启动不了的,因为在www文件里面,设置了端口是3000,他是通过www文件来启动监听的

解决办法:

app.js里面,在最后一行代码之前,添加:

app.listen(80);

 

于是,便可以通过app.js来启动服务器了。

 

访问效果如图:



 

 

假如如果像我一样倒霉,无法用express命令,打开npm也特别慢,可以先找个系统,将这些文件下载好,然后将这些文件复制到不可以用express命令的linux系统下面。

 

 

或者看最后的终极解决方案


ps

如果npm很慢的话,可以考虑装cnpm

npm install -g cnpm --registry=https://registry.npm.taobao.org

 

然后在npm install这一步,使用cnpm install来替代

 

————————分割线————————

 

④超级终极解决方案:

我传一个装好express的压缩包,直接解压缩后就可以用。

链接:

http://download.csdn.net/detail/qq20004604/9587054



⑤另一个启动方法

即不通过app.js来启动;

在之前④的基础上,打开app.js,删除

app.listen(80);

 

打开package.json,将

"start":"node ./app.js"

改回

start":"node ./bin/www"

 

然后

cd bin

vi www

 

var port =normalizePort(process.env.PORT||'3000');

修改为

var port =normalizePort(process.env.PORT||'80');

 

然后

cd ..

npm start

 

启动成功,可以直接访问地址来访问页面

 

 

6】把启动的app.js放在后台运行,并且在操作端解除控制后依然可以运行

原本使用npm start的地方,输入

nohup npm start&

即可

 

 

7app.js之解释

app.js可以说是一切的根本,因此请看注释,解释了每行代码的作用:

var express = require('express');  //这个模块在node_modules文件夹中
var path = require('path'); //nodejs自带的,路径相关
var favicon = require('serve-favicon'); //node_modules文件夹中
var logger = require('morgan'); //日志相关,node_modules文件夹中,具体看第19行代码
var cookieParser = require('cookie-parser');//node_modules文件夹中,用来解析cookie的,被express所调用
var bodyParser = require('body-parser');    //用于解析请求体的(应该),被express所调用

var routes = require('./routes/index'); //这里是默认的路由,路径是routes/index.js
var users = require('./routes/users'); //这里是默认的路由,路径是routes/users.js
//关于路由的更多内容看下面的app.use('/', routes);和app.use('/users', users);的注释

var app = express();    //生成一个express的实例

//设置模板引擎
app.set('views', path.join(__dirname, 'views'));    //__dirname表示绝对路径
//console.log(__dirname)  //可以取消这一行注释,然后看看__dirname的效果
app.set('view engine', 'jade'); //表示express是使用jade格式的模板的


//下面这行代码是设置左上角的小图标的,将其命名为favicon.ico并放在public文件夹下,如果有的话,取消这行注释
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));

app.use(logger('dev')); //设置日志显示,如果不需要的话可以注释掉这行代码,建议练手的时候不要注释掉
//可替换参数有default,combined,common,short,tiny,dev(相对tiny有染色)。可以自己试试效果,默认是dev

app.use(bodyParser.json()); //解析客户端的请求,通常是通过post发送的内容
app.use(bodyParser.urlencoded({extended: false})); //另一种解析方式,具体不太明白(如果上面解析失败的话会通过这个来)
app.use(cookieParser());    //cookies的解析
app.use(express.static(path.join(__dirname, 'public')));    //普通静态html文件、js文件、css文件,都放在public文件夹下,可以直接通过url来访问

//路由的处理
app.use('/', routes);   //假如访问的网址是根目录,例如http://121.41.66.68/,交给routes这个js文件来处理,具体请查看routes
app.use('/users', users);   //假如访问的是/users这样的路径,那么交给users这个js文件来处理,具体略
//我们最后要对这个路由进行处理,让他按照我们想要的方式来做

//这里对非法路径进行处理的,next表示这是一个中间件(即执行完他之后,还会执行下一个,而不是直接在这里结束了)
//如果上面没有静态文件(29行)、没有找到被路由处理的文件(32,33行),就会交给这个来处理。
app.use(function (req, res, next) {
    var err = new Error('Not Found');
    err.status = 404;
    next(err);  //由下面的2个app.use中的一个来处理(一般是第一个,除非第一个被注释)
});


//原注释说是会对错误进行加亮处理
//这部分和下面的区别在于,这部分会将错误信息暴露给用户,而下面的不会,因此注释掉这部分
//if (app.get('env') === 'development') {
//    app.use(function (err, req, res, next) {
//        res.status(err.status || 500);
//        res.render('error', {
//            message: err.message,
//            error: err
//        });
//    });
//}

// production error handler
// no stacktraces leaked to user
app.use(function (err, req, res, next) {
    res.status(err.status || 500);
    res.render('error', {   //这里的error指调用views下的error模板
        message: err.message,
        error: {}
    });
});

//这是我自行添加的,用于显示服务器启动的时间
console.log("Server start at :" + new Date());

//导出app,在./bin/www里会被调用
module.exports = app;




8】页面关系结构

请忽略文件名的大小写问题(手动微笑)


 

 

因此,首先有三个需要我们自定义的路由:

①当访问根/时,输出index

②当访问/login时,输出login

③当访问/reg时,输出reg

 

其他可能的路由:

④后续可能添加的页面,暂缺;

⑤不符合要求的页面,输出404express已经完成)

 

 

 

9index页面需要包含的功能:



10index的路由:

查看app.js中的代码:

app.use('/', routes);  

这部分代码已经说明了,当访问根的时候,交给routes来处理;

 

再次查看导入routes的地方:

var routes = require('./routes/index');

说明负责这部分的文件是routes文件夹的index文件

 

这时打开index.js

router.get('/', function(req, res, next) {
  res.render('index', { title: 'Express' });
});

这部分代码,表示当访问根的 ’/’ 页面时,由index这个引擎模板来处理,模板中的title变量,其值为Express

 

————————————————————————

代码说明:

router.get('/'

以上这段代码是在路由基础上进行二段捕获url的,举例:

①假如在app.js里,

app.use('/',

然后在路由的处理里,是

outer.get('/'

那么最终针对的url/

 

②假如在app.js里,

app.use('/test',

然后在路由的处理里,是

outer.get('/'

那么最终针对的url/test

 

③假如在app.js里,

app.use('/,

然后在路由的处理里,是

outer.get('/test'

那么最终针对的url依然是/test

 

④假如在app.js里,

app.use('/testA,

然后在路由的处理里,是

outer.get('/testB'

那么最终针对的url/testA/testB

 

⑤捕获优先度说明:

首先根据app.js中的app.use出现顺序决定,假如②和③同时出现,那么看②和③在app.js中的代码谁先出现,就交给谁来处理;

 

再不调用next()方法的情况下,只会被最先出现的那个处理;

 

如果第一个调用了next()方法,那么第一个处理完后会执行第二个的

————————————————————————

 

index.js代码说明:

var express = require('express'); //调用express
var router = express.Router();  //生成express的Router方法的一个实例

//处理函数
router.get('/', function (req, res, next) {  //捕获根url
    res.render('index', {title: 'Express'});
    //res.render方法渲染一个引擎模板,
    //第二个参数是一个对象,对象里的变量可以在引擎中使用,
    //第三个参数是回调函数,提供两个参数,分别是err和html,err是错误,html是渲染后的页面。如果使用这个回调函数,那么将不会自动响应,即要用户自己写返回html的命令
});

module.exports = router;


注意,被引擎渲染的文件,默认是在myblog/views文件夹下

 


11】使用Bootstrap界面

让我们自己设计界面不是不可以,不过太麻烦,因此我和原书保持一致,使用Twitter Bootstrap风格的页面。

 

下载他的压缩包文件,并解压缩他,

css文件放在项目myblog/public/stylesheets下;

img文件夹直接复制粘贴在myblog/public下;

js文件放在myblog/public/javascripts下,

 

我的Bootstrap的版本是v2.3.2

另外,下载jquery,命名为jq.js,放在myblog/public/javascripts


 

12index.jade说明

下来我们就要修改jade文件了,如果不知道怎么使用的话,可以看我的博客:

http://blog.csdn.net/qq20004604/article/details/51773574

extends layout

block content
  h1= title
  p Welcome to #{title}

第一行的extends layout表示他导入的layout模板(即layout.jade

 

block content表示以下这部分将套入layoutcontent位置

 

内容略。

 

这时候再过去看layout.jade

doctype html
html
  head
    title= title
    link(rel='stylesheet', href='/stylesheets/style.css')
  body
    block content

 

他导入的是style.css这个样式表,页面的title是变量title

上面的index.jade中的内容将导入这里的block content区域(因为变量名一样,会对应替换)。

 

其结构大概如下:


 

然后我们根据自己实际需求来改造:

 

直接给出代码:

首先在stylesheets文件夹下创建一个blog.css文件,内里样式为:

body {
    padding-top: 60px;
    padding-botom: 40px;
}

#textarea {
    resize: none;
    width: 300px;
    height: 100px;
    cursor: text;
}

#postBlog {
    position: relative;
    left: 20px;
    vertical-align: top;
}

#clearBlog {
    position: relative;
    left: -90px;
    top: 27px;
    width: 110px;
    height: 44px;
}

.myalert {
    position: absolute;
}

.displayNONE {
    display: none;
}

#scrollToFoot {
    border: 1px solid #ccc;
    text-align: center;
    font-size: 18px;
    padding: 20px 0;
}

fotter p {
    margin-top: 40px;
    padding-top: 20px;
    border-top: 1px solid #aaa;
    font-size: 18px;
}

.row {
    color: #555;
}

 

 

其次是layout.jade

doctype html
html
    head
        title MyBlog By qq20004604
        link(rel='stylesheet', href='./stylesheets/bootstrap.min.css')
        link(rel='stylesheet', href='./stylesheets/bootstrap-responsive.min.css')
        link(rel='stylesheet', href='./stylesheets/blog.css')
        script(type="text/javascript",src='javascripts/jq.js')
        script(type="text/javascript",src='javascripts/bootstrap.min.js')
        script(type="text/javascript",src='javascripts/blog.js')
    body
        div.navbar.navbar-fixed-top
            div.navbar-inner
                div.container
                    a.btn.btn-navbar(data-toggle="collapse",data-target=".nav-collapse")
                        span.icon-bar
                        span.icon-bar
                        span.icon-bar
                    a.brand(href="/") MyBlog
                    div.nav-collapse
                        ul.nav
                            li
                                a(href="/") 首页
                            li
                                a(href="/logout") 登出
                            li
                                a(href="/login") 登入
                            li
                                a(href="/reg") 注册
                            li
                                a(href="/language") 切换语言
        div#contrainer.container
            block content
            hr
        fotter
            p   作者:王冬   QQ:20004604

 

效果如图:


 

然后是index.jade

extends layout
block content
    div.hero-unit
        h1  我的博客
        p   这个是基于Nodejs作为后台,jade作为模板来,使用了Express作为框架
            br
            br
            //这部分暂时用1替代,后续会被更新
            if(1)
                br
                br
                a.btn.btn-primary.btn-large(href="/login")  登录
                a.btn.btn-large(href="/reg")    立即注册
            else
                textarea#textarea.uneditable-input
                button#postBlog.btn.btn-large 提交微博
                button#clearBlog.btn.btn-large 清空
            div#submitError.alert.alert-error.displayNONE.myalert
            div#submitSuccess.alert.alert-success.displayNONE

    div.row.content
        div.span4
            h2  烟雨江南说
            p   当欲望没有了枷锁,就没有了向前的路
            p   只有转左,或者向右
            p   左边是地狱,右边也是地狱
        div.span4
            h2  烟雨江南说
            p   那些都是极好极好的
            p   可是我偏偏不喜欢
        div.span4
            h2  烟雨江南说
            p   我不怕傻
            p   只怕
            p   遇不到
            p   可以让我变傻的人
        div.span4
            h2  烟雨江南说
            p   人在年轻的时候总会有些莫名的坚持,
            p   并且以此感动着自己,
            p   却时常会在不经意间让真正重要的东西从指间流走。
        div.span4
            h2  烟雨江南说
            p   记忆真是一种奇怪的东西,
            p   有时候会涤荡所有的苦难,只留下温情,
            p   有时候却磨灭掉曾有的欢乐,唯剩下苍白和丑陋。
        div.span4
            h2  烟雨江南说
            p   那存在的,都是幻影。
            p   那永恒的,终将毁灭。
            p   世界万物,缤纷色彩,都是被蒙蔽的人心罢了。
        div.span4
            h2  烟雨江南说
            p   诸神以真相示人,而世人却视而不见
        div.span4
            h2  烟雨江南说
            p   只有绵羊会向狮子要求平等,
            p   而狮子们从来不会这样想。
        div.span4
            h2  烟雨江南说
            p   愿迷途的旅人,从此得享安息。
            p   因理想而不朽,因归返而救赎。
    div#scrollToFoot 滚动到底部然后加载内容

 

效果如图:


 

 

但此时,上面的页面切换目前还都是无效状态;

滚动然后加载内容,也正处于无效状态;

注册和登录按钮,点击后也无法正常跳转;

 

我们需要依次解决这些问题。

 

 

13】登录页面

接下来我们添加登录页面的路由和模板。

 

路由,打开app.js,在

app.use('/', routes); 
app.use('/users', users);

 

之前添加

var reg = require('./routes/reg');
var login = require('./routes/login');

 

之后添加:

app.use('/reg', reg);    //注册的,reg.js来处理
app.use('/login', login);  //登录的,login来处理

这样的话,就添加了注册和登录页面的路由了,但目前,我们还缺其具体文件和代码。

 

进入routes文件夹,创建reg.jslogin.js

reg.js

var express = require('express'); //调用express模块
var router = express.Router();  //调用模块的Router方法
router.get('/', function (req, res, next) {
    res.render('reg')
});
module.exports = router;

login.js

var express = require('express'); //调用express模块
var router = express.Router();  //调用模块的Router方法
router.get('/', function (req, res, next) {
    res.render('login')
});
module.exports = router;

现在又缺模板文件了。

进入views文件夹,创建reg.jadelogin.jade

reg.jade

extends layout
block content
    form.form-horizontal(method="post")
        fieldset
            legend  注册
            div.control-group
                label.control-label(for="username") 用户名
                div.controls
                    input.input-xlarge#username(type="text",name="username")
                    p.help-block    你的账户名称,用于登录和提示

            div.control-group
                label.control-label(for="password") 口令
                div.controls
                    input.input-xlarge#password(type="password",name="password")

            div.control-group
                label.control-label(for="password-repeat")  重复输入口令
                div.controls
                    input.input-xlarge#password-repeat(type="password",name="password-repeat")

            div.form-actions
                button.btn.btn-priamry(type="submit")   注册

login.jade

extends layout
block content
    form.form-horizontal(method='post')
        fieldset
            legend  登录
            div.control-group
                label.control-label(for='username') 用户名
                div.controls
                    input.input-xlarge#username(name='username',type='text')
            div.control-group
                label.control-label(for='password') 密码
                div.controls
                    input.input-xlarge#password(name='password',type='password')
            div.form-actions
                button.btn.btn-primary(type="submit") 登录

这个时候,注册和登录页面已经可以访问了(虽然还没有添加逻辑)


版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享: