node学习大纲1

node优势

  • 性能优势:
    nodejs PK php
    • 实际上nodejs性能比PHP高出86倍;
      1. nodejs 1s才能返回的东西,php需要86s;
      2. 假设PHP需要200台服务器,node需要3台;
  • 跟前台js配合方便
    • 比如gulp,bower,webpack等都需要和nodejs进行配合,实现编译部署等;
  • nodejs便于前端学习;因为他提供了一个共js运行的服务器环境;

nodejs-服务器;

注意:
1)写node不能有中文;2)新版nodejs都支持es6;

  • http的使用1:写服务器;
    服务器本身提供很多服务,具体要哪个服务通过端口号查找;
    比如:
    • 80 web
    • 110 邮件
    • 3306 数据库
      当然,端口可以自己定;一个端口只能有一个服务
  • req.url

文件操作fs 及 强行把异步编程同步;

  • fs.readFile(文件名,回调函数); 异步操作,所以有回调函数;
    • buffer原始的二进制数据;
    • 如果想看到文字,用toString();
  • fs.writeFile();
    • fs.write(文件名,内容,function(err){})
  • fs.mkdir('./album/aaa') 创建一个文件夹
  • fs.stat()
  • fs.readDir
  • 异步 VS 同步;
    • 异步:多个操作可以同步进行;前一次的操作,如果没完事,后一次也能开始;
    • 同步:一次一个;前面没完,后面无法开始;
  • fs配合http:server && file
    • 把文件放www目录下;
    • 注意异步问题;因为readFile是异步的;

如何接收前台的数据请求

  • 前台向后台发送数据请求的方式:
    • form表单:form必须有submit method action name value
    • ajax:判断浏览器
    • jsonp:三步
  • 对后台来说,他们3都一样,因为后台只接受前端发送的数据;
    • 前台<->后台 都是通过http请求;所以,后台只是接收了http请求;
    • 对后台,请求的方式不同,过来的内容接收方式不同:
      • get:数据在URL当中一起传输;
      • post:数据在请求体中传输;(头-header;身体-header);

get请求:

- querystring();
querystring.parse() 方法能把一个 URL 查询字符串(str)解析成一个键值对的集合。
- url.parse()
- 总结:get数据解析
    1. 自己切
    2. querystring.parse('k=v&k=v');
    3. url.parse(req.url,true);

post请求:后台接收post数据

  • 浏览器和服务器之间通信,有个脑袋(<32k)和身子(1G);
  • 注意:post数据比get大很多;意味着,处理方式有区别;
    • post很大,把大块的数据,切成小块分好几次发送;
    var str='';
    var i=0;
    //data:每当有一段数据到达的时候,就会发送一次;(很多次)
    req.on('data',function (data) {
        console.log(`第${i++}次`)
        str+=data;
    });
    //end-数据到达的时候(一次)
    req.on('end',function () {
        console.log(str);
    });
    

小实战:

  • 完整的服务器:接收-读取文件-server本身;
  • 用户注册登录;
    • 做前后台数据交互,先得把"接口"定义出来;
      • /user?act=reg&user=aaa&pass=123;
        {"ok":false,"msg":"原因"}
      • /user?act=login&user=aaa&pass=123;
        {"ok":true,"msg":"原因"}
        后台接口自己随意定,只要跟前台商量了,统一即可;
    • 前台对后台的请求一般有两种:
      • http://localhost:8080/1.html 对文件的访问
      • http://localhost:8080/user?act=login... 对接口的访问;

模块化--

  • 系统模块:http,querystring,url,fs;
  • 自定义模块:
  • 模块管理(包管理器)

自定义模块

  • 自定义模块
    • require 引入其他模块
    • exports "单独"对外输出
    • module.exports "批量"对外输出
      module.exports===exports =>true;
      注意:
      nodejs中不存在全局变量;
      1)引入自定义模块必须加./
      2)如果想对外输出对象,必须exports:
      优点:
      - 避免全局变量
      - 按需导出
  • 模块:就是文件和文件之间的关系;
  • npm:Nodejs package Manager(Nodejs包管理器)
    • 作用:
      1. 他提供了统一的下载途径;类似于360;
      2. 自动下载依赖;
    • 使用:安装的时候,注意所在目录;
      1. 下载 npm install xxxx
      2. 卸载 npm uninstall xxx
    • node_modules:存放模块使用;
      不仅能放别人的,也可以放自己;但是建议不要混搭;
    • require的查找顺序
      如果有"./"从当前目录找;
      如果没有"./",先从系统模块找,再从"node_modules"找,没有就报错;
    • 我们的依赖包,可能随时更新,我们永远想保持更新,或者保持某一个版本
    • 项目越来越大;我们可以用package.json来管理依赖;
      • dependencies:项目依赖
      • devDependencies:开发时候的依赖;

请求静态资源,注意mime类型;

路径

  • require()中的路径,从当前这个js文件出发,找到别人;
  • require()哪个文件的时候,就会执行哪个文件;
  • fs等其他的模块用到路径的时候,都是相对于cmd命令光标所在的位置;所以,如果层级嵌套的画,建议用绝对路径__dirname;

post请求之文件上传

  • formidable模块;- 读文档
  • fs.rename改名;

ejs模版

  • 后台模板;著名的有两个,ejs,jade;
  • 需要安装包:ejs;
  • 两个例子:1)直接替换字符串 2)替换页面模板并展示;
  • ejs花式模版
    <%for(var i=0; i
  • 我爱吃<%= news[i]%>
  • <%}%>

原生node的问题

- 呈递静态页面不方便;需要处理每个http请求;
- 路由处理代码不直观清晰,需要进行很多判断
- 不能集中精力写业务,需考虑很多其他的东西;

express的本质

  • 首先,明白express是非破坏式的;比如req和res的功能改进,res.write和end都有,但是多了res.send();
    send(字符串和对象都ok)而res.write(string||buffer);
  • express三步走:
    1. 创建服务
    2. 监听
    3. 处理请求

express整体感知

  • express三大能力:
    1. 强大的路由能力;
    2. 静态资源
    3. 模版引擎的配合

路由能力:接收请求方式;常用的有: get()/post()/use()

  1. 这里的网址不分大小写
  2. RESTful路由设计
    一个路径 "/student",http的method不同,他的功能就不同
    • get 读取学生信息
    • add 添加学生信息
    • delete 删除学生信息;
  3. 路由的基本使用
app.get('/haha',function (req,res) {
    res.send('这是hahaa')
});
//正则路由,未知不分用()分组,通过req.params[0]来获取对应的参数;
app.get(/\/student\/(\d{4})/,function (req,res) {
    console.log(req.params)
    res.send('学生信息,学号:'+req.params[0])
});
//express自带的具有正则功能的路由,未定的用:代表,通过req.params.xxx获取参数;
app.get("/teacher/:gonghao",function (req,res) {
    console.log(req.params)
    res.send('老师信息,工号:'+req.params.gonghao);
});
//某个人的某个id
app.get("/:username/:id",function (req,res) {
    console.log(req.params)
    res.send('老师信息,工号:'+req.params.gonghao);
});

静态资源

//当访问/的时候,可以不写路由,直接调用静态文件的index.html;
app.use(express.static('./public'));

模版引擎的配合

//1:设置渲染的模版引擎为ejs;
app.set('view engine','ejs');
//2:views目录,是默认的,所以渲染模版的时候,可以省略相对路径;
app.get('/haha',function (req,res) {
    res.render('haha',{
        news:['原生javascript','node','html5+css3']
    })
});

express的get和post请求

  • get请求的参数在URL中,原生node,需要使用URL模块来识别参数字符串;在express中,直接用req.query对象即可;
  • post请求在express中不能直接获得,必须使用body-parser模块,才能用req.body得到参数,但如果表单中含有文件上传,那么还需要使用formidable模块;

中间件 middleware

  • 路由get,post这些东西;就是中间件,中间件讲究顺序,匹配上第一个之后,就不会往后匹配了;next函数才能够继续往后匹配;所以,get和post对路由卡的很死;
  • 解决方式1:写路由的时候,具体的往上写,抽象的往下写;
app.get('/admin/login',function (req,res,next) {
    console.log('2');
    res.send('管理员登录');
    next();
});

app.get('/:username/:id',function (req,res,next) {
    console.log('1');
    res.send('管理员登录'+req.params.username)
});
  • 解决方式2:条件判断
app.get('/:username/:id',function (req,res,next) {
    var username=req.params.username;
    //检索数据库,如果username不存在,那么next();
    if(username){
        console.log('1');
        res.send('用户信息')
    }else{
        next();
    }

});
app.get('/admin/login',function (req,res,next) {
    console.log('2');
    res.send('管理员登录');
    next();
});
  • app.use()也是一个中间件,与get和post不同的是,他的网址不是精确匹配的,而是能够有小文件夹拓展的;如下;
    • 当你不写路径的时候,就相当于'/',即相当于所有网址;
    • 所以,一般用use当接盘侠;
// GET 'http://www.example.com/admin/new'
app.use('/admin',function (req,res) {
    console.log(req.originalUrl); //  '/admin/new'
    console.log(req.baseUrl); //  '/admin'
    console.log(req.path);// '/new'
    res.send('你好')
});

render和send的区别:

  • 渲染内容用res.render()比如,渲染ejs模版内容;默认渲染的都是views文件夹中的;可以省略'./views/'直接写入文件的具体名称:res.render('index.ejs',{news:[1,2,3]})
  • 快速测试页面,使用res.send();
  • 如果想使用不同的状态码 res.status(404).send('we cannot find that!');
  • 如果想使用不同的Content-Type,可以:res.set('Content-Type':'text/html');

后台MVC小项目:我的影集

  • M:数据models; V:视图views;C:控制器controller(router);
  • 指按模块来开发,不要放在同一个文件夹中;减少彼此之间的耦合;
  • 基本架构:遵循mvc的思想,创建如下目录:
models     模型:具体的业务都在这里面;所以,真正在干活的都是models
views      视图
controller (router)函数的罗列;
public     静态资源文件夹
uploads    下载内容
app.js     主入口文件
  • 路由的设计,都在controller
  • 初步框架如下
const express=require('express');
const bodyparser=require('body-parser');
const router=require('./controller');//自定义路由模块

const app=express();
app.listen(8080);
//设置模版引擎
app.set('view engine','ejs');
//设置路由中间件;
//静态页面
app.use(express.static('./public'));
app.use(express.static('./uploads'));//uploads被静态了
//各种请求
//首页
app.get('/',router.showIndex);
app.get('/:album',router.showAlbum);
app.get('/up',router.showUp);
app.post('/up',router.dopost);
//最后的中间件;
app.use((req,res)=>{
    res.render('404');
});
  • node中全是回调函数,所以我们自己封装的函数中如果有异步,比如I/O,那么就得用回调函数的方法封装;

express中的cookie和session

cookie:

  • 产生的原因:
  • cookie:保存数据,保存在浏览器端;在浏览器或客户端保存一些数据;并且每次向服务器发送请求的时候,都会带过来;
    • 缺点:但凡保存在客户端的东西,都不可信,因为用户可以很方便的修改;
  • cookie:大小有限;只有4K;
  • cookie两件事:
    • 设置cookie
    • 读取cookie:读取需要用到cookie-parser
  • cookie可用签名signed做到防止篡改
app.use(cookieParser('sdkfjsdfsf'));//是为了读取cookie;
app.get('/',function (req,res) {
    //种个cookie
    req.secret='sdkfjsdfsf';//签名后的cookie
    res.cookie('username','leiei',{
        signed:true
    })
    console.log(req.signedCookies) //签名后的cookie
    res.send(req.cookies);//存没有签名的cookie
});
  • cookie总结:
    1. cookie的空间非常小。必须省着用;

    2. cookie安全性差;

      • 校验cookie是否被篡改过;(用signed)
    3. 添加和读取,删除cookie

      • 添加:res.cookie(名字,值,{
        path:'/aaa'
        maxAge:毫秒
        signed:是否需要签名 true/false //能不签就不签;
        (signed必须配合secret)
        })
      • 读取,用中间件cookie-parser
      app.use(cookieParser('密钥'))
      app.get('/',function(){
          req.cookies//未签名版
          req.signedCookies //签名版
      )
      
      • 删除cookie:res.clearCookie('user');
    4. 密钥四步走:secret ; app.use(cookieParser('密钥')) ; signed:true ; req.signedCookies;

session

  • session:保存数据,保存在服务器;

  • session:只要服务器有地就存;大小无限了;

  • session不可能独立存在,有cookie才有session;

    • session原理:第一次浏览器访问服务器,cookie为空;服务器给该用户种个cookie{sessionid:xx};
    • cookie中会有session的id;服务器利用session的id,找到session相关的文件;
    • 隐患:session劫持
      • 解决措施:1)更换session; 2)cookie加密;
  • session:

    • 读取session:cookie-session
    • 使用方式;
    var ary=[];
    for(var i=0; i<1000000; i++){
        ary.push('sig_'+Math.random())
    }
    app.use(cookieParser());
    app.use(cookieSession({
        name:'lei',//更改session的id的名字;
        keys:ary,
        maxAge:2*3600*1000//2小时
    }));
    app.get('/',function (req,res) {
        if(req.session['count']==null){
            req.session['count']=1;
        }else{
            req.session['count']++;
        }
        console.log(req.session);
        res.send(req.session['count'].toString())
    })
    
    • 获取:req.session;
    • 删除:delete req.session;
  • session小总结:

    • session依赖cookie;所以cookie-session必须先引入cookie-parser;
    app.use(cookieParser());
    app.use(cookieSession({
        keys:
    }));
    

你可能感兴趣的:(node学习大纲1)