nodejs相关总结

2018-08-12  本文已影响0人  宠辱不惊丶岁月静好

一、Node快速体验

1、 Node介绍

(1) Node.js是什么

(2) Node 能做什么

知乎 - Node.js能做什么,该做什么?

(3) 一些资源

① 文档

Node.js 官方文档
Node.js 中文文档(非官方)

② 书籍

深入浅出 Node.js
Node.js 权威指南
Node.js 实战
Node.js实战(第2季)

③ github资源

Node.js 包教不包会
ECMAScript 6 入门
七天学会 NodeJS

④ 社区

Node.js 中文社区

2. Node起步

(1)安装Node

对于已经装过的,重新安装就会升级

确认 Node 环境是否安装成功

打开命令行,输入 node --version

或者 node -v

(2)REPL环境(Read Eval Print Loop:交互式解释器:了解)

在命令行工具界面输入node 按回车 就进入到了REPL 环境

类似于浏览器中的 Console控制台 ,可以做一些代码测试。

按ctrl + 两次c 退出REPL环境

但是, 我们写代码肯定不是在控制台中写,而是写在一个单独的.js文件中.

(3)HelloWorld

  1. 新建一个 hello.js 并写入以下示例代码
    var message = 'Hello World!'
    console.log(message)
  1. 打开命令行并定位到 hello.js 文件所属目录
  2. 在命令行中输入 node hello.js 回车执行
    node hello.js

(4)Node中的js

node中的js和浏览器中的js不同:

二、Node中的模块和包管理器npm

1、Node中的模块体验

(1)文件读写

文件读取:

    // 1、引用fs核心模块
    var fs = require('fs');
    // 2、读取文件
    // fs.readFile中有两个参数:
    //     path: 要读取文件的路径
    //     callback:读取文件后面的回调函数
    //          err: 读取文件异常的异常信息
    //              如果文件读取出来err为null
    //              如果文件读取失败err为失败信息
    //          data: 文件中的内容
    //              如果文件读取成功,那么将来data会是一个十六进制的Buffer数组
    fs.readFile('./00.txt', function(err, data){
        // 输出文件中的内容
        console.log(err);
        console.log(data.toString());
    });

文件写入:

注意:

  • 在写入时会覆盖已有的内容

  • 如果写入的文件不存在,会自动创建

    // 1、引用fs核心模块
    var fs = require('fs');
    // 2、向文件中写入内容
    //  这个方法是用来覆盖原文件中的内容,
    // fs.wirteFile(file, data, callback)
    //      file:要写入内容的文件
    //      data:要写入的数据(可以为utf-8)
    //      callback:写入后的回调函数
    //          err: 写入失败后面的异常信息     
    fs.writeFile('./0000.txt', '天若有情天易老,人间正道是沧桑', function(err){
        if (err) {
            console.log(err.message);
        } else {
            console.log('写入成功');
        }
    });

文件追加写:

    // 核心模块:fs
    //      fs.readFile
    //      fs.writeFile
    //  思想:先读,然后追加,然后再写

    var fs =require("fs");
    // 1、读取
    fs.readFile("./00.txt", function(err, data){
        if(err) {
            console.log(err.message);
        } else {
            // 2、追加
            var str = "小猪配奇身上纹,掌声送给社会人";
            str = data + str;
            fs.writeFile("./00.txt", str, function(err) {
                if(err) {
                    console.log(err.message);
                } else {
                    console.log("写入成功");
                }
            });
        }
    });

(2)HTTP 服务

    // node把处理web服务器相关的功能 封装到了 http模块中
    // 1、导入http模块
    var http = require('http');
    // 2、使用http这个模块中的createServer()创建一个服务器实例对象
    var server = http.createServer();
    // 3、给服务器对象注册一个request事件,当浏览器有请求发送过来时,服务器会接收,并且执行后面的回调函数
    // 请求处理函数function(形参1,形参2){}
    // 形参1:request请求对象 获取到当前请求的路径,方法等信息
    // 形参2:response响应对象 发送响应数据
    server.on('request', function(request, response) {
        console.log('有浏览器连接上来了!');
        // 向客户端页面返回字符串
        response.write("hello node");
        // 结束响应
        response.end();
    });
    // 4、绑定端口号,启动web服务器
    server.listen(12345, function() {
        console.log(' 请访问http://localhost:12345');
    });

注意:

  1. 注册request处理函数 有两个形参 request和response 不要搞混
  2. 在写完服务器代码后 保存代码 ->在cmd中 node 文件名 然后回车执行
  3. 每次修改代码后 要重新在cmd中 node 文件名 执行这个文件
  4. !! 端口号尽量写的大一些 大于3000 否则容易和已经运行的软件所占用的接口相冲突!

2、小案例

(1)通过http模块写一个自己的服务器

需求:将来有请求链接上来以后,服务器需求响应一个hello world的内容回浏览器

    var http = require("http");
    var server = http.createServer();
    // 如果需要响应在requrest事件后面的回调函数中有两个参数:
    //  request
    //  response
    // 参数:
    //  request:浏览器发送到服务器的请求
    //  response:服务器响应回浏览器的数据
    //      方法:
    //          write:向响应报文中写入一段要发送浏览器的数据,不会将数据立即响应回浏览器
    //          end:将数据响应回浏览器
    //          setHeader:设置响应头
    server.on('request', function(request, response){
        // 响应数据回浏览器要借助response
        // response.write('hello');
        // response.write(' world');
        // response.end('hello world');
        // 设置响应报文的响应头
        response.setHeader("content-type", "text/html;charset=utf-8");
        response.end('<doctype><html><head></head><body></body></html>');
    });
    //下一行listen方法中第二个参数可以指定自己的IP,也可以不写,不写时在浏览器访问localhost:3000即可
    server.listen(3000, "192.168.81.1", function(){
        console.log('服务器开启成功');
    });

(2)通过服务器响应一个完整的html页面回浏览器

js文件:

    var http = require("http");
    // 引用fs模块
    var fs = require('fs');
    var server = http.createServer();
    server.on('request', function(request, response){
        // response.setHeader("content-type","text/html;charset=utf-8");
        // response.end('');
        // 响应一个完整页面回浏览器的思路
        //  1、创建一个完整的html页面
        //  2、将这个页面中内容读取出来
        fs.readFile('./views/index.html', function(err, data){
            if(err) {
               return console.log(err.message);
            }
            //  3、将内容通过response.end响应回浏览器
            response.end(data);
        });
    });
    server.listen(3000, "192.168.81.1", function(){
        console.log('服务器开启成功');
    });

html文件:./views/index.html

    <body>
        <h1>你好,世界!</h1>
    </body>

(3)在上面基础上显示一张图片

js文件:

    var http = require("http");
    var fs = require('fs');
    var server = http.createServer();
    // request:所有浏览器发送到服务器的请求数据
    //    属性:
    //      url  
    server.on('request', function (request, response) {
        // 如果将来图片的请求过来服务器,服务器是没有作任何处理
        // 处理一个图片和页面的请求:
        //  约定:
        //      将来请求根目录时,是请求页面
        //      将来请求views/0.jpg时,是请求图片
        //  问题:如何得到请求的路径
        //      request.url
        // 判断:如果请求的 / ,响应页面回去
        //      如果请求的 /views/0.jpg响应图片回去
        if (request.url === '/') {
            fs.readFile('./views/index.html', function (err, data) {
                if (err) {
                    return console.log(err.message);
                }
                response.end(data);
            });
        } else if (request.url === '/views/0.jpg') {
            fs.readFile("./views/0.jpg", function(err, data){
                if (err) {
                    return console.log(err.message);
                }
                response.end(data);
            });
        }
    });
    server.listen(3000, "192.168.81.1", function () {
        console.log('服务器开启成功');
    });

html文件:./views/index.html

    <body>
        <h1>你好,世界!</h1>
        <!-- 因为这个路径压根就没有在服务器中被解析过,是浏览器来解析,因此使用绝对路径 -->
        <img src="/views/0.jpg" id="img">
    </body>

(4)在此基础上响应一个js文件

    var http = require("http");
    var fs = require('fs');
    var server = http.createServer();
    server.on('request', function (request, response) {
        // 处理根目录的请求
        if (request.url === '/') {
            fs.readFile('./views/index.html', function (err, data) {
                if (err) {
                    return console.log(err.message);
                }
                response.end(data);
            });
            // 处理了图片的请求
        } else if (request.url === '/views/0.jpg') {
            fs.readFile("./views/0.jpg", function(err, data){
                if (err) {
                    return console.log(err.message);
                }
                response.end(data);
            });
            // 处理jquery
        } else if (request.url === '/views/jquery.min.js') {
            fs.readFile("./views/jquery.min.js", function(err, data){
                if (err) {
                    return console.log(err.message);
                }
                response.end(data);
            });
        }
    });
    server.listen(3000, "192.168.81.1", function () {
        console.log('服务器开启成功');
    });

html:

    <body>
        <h1>你好,世界!</h1>
        <img src="/views/0.jpg" id="img">
        <input type="button" value="点我隐藏" id="btn">
    </body>
    <script src="/views/jquery.min.js"></script>
    <script>
         $("#btn").click(function(){
             $("#img").hide(1000);
         });
    </script>

(5)在此基础上统一处理静态文件

js文件:

    var http = require("http");
    var fs = require('fs');
    var server = http.createServer();
    server.on('request', function (request, response) {
        if (request.url === '/') {
            fs.readFile('./views/index.html', function (err, data) {
                if (err) {
                    return console.log(err.message);
                }
                response.end(data);
            });
        }   
        // 统一处理静态资源:
        // 判断请求路径中是否有携带views
        else if (request.url.indexOf("/views") != -1) {
            // 直接将对应的文件读取出来
            // 先将绝对路径转为相对路径
            var url = '.' + request.url;
            fs.readFile(url, function(err, data){
                if(err) {
                    return console.log(err.message);
                } 
                response.end(data);
            });
        }
    });
    server.listen(3000, "192.168.81.1", function () {
        console.log('服务器开启成功');
    });

html:

    <head>
        <link rel="stylesheet" href="/views/index.css">
    </head>
    <body>
        <h1>你好,世界!</h1>
        <img src="/views/0.jpg" id="img">
        <input type="button" value="点我隐藏" id="btn">
    </body>
    <script src="/views/jquery.min.js"></script>
    <script>
         $("#btn").click(function(){
             $("#img").hide(1000);
         });
    </script>

(6) 完成仿apache的目录浏览功能

步骤:

  • 服务器
    • 1、创建一个服务器
    • 2、如果将来浏览器请求静态页面,我们就将一个静态文件返回到浏览器
    • 4、服务器接收到浏览器的请求,将当前目录下的所有的路径读取出来,并且返回给浏览器的异步对象
  • 浏览器
    • 3、通过浏览器发送一个异步请求到服务器,去请求当前服务器的目录数据(getPath)
    • 5、浏览器接收数据,并且将数据渲染到页面上

js文件:

    // 创建一个服务器
    // 1、引用http模块
    var http = require('http');
    var fs = require('fs');

    // 2、创建一个服务器对象
    var server = http.createServer();

    // 3、设置request事件
    server.on('request', function (req, res) {
        // 3.1、请求请求参数
        var url = req.url;
        // 3.2、判断是否请求的是首页  /
        if (url === '/') {
            // 将首页的静态文件响应回浏览器
            // 先通过fs模块将内容读取出来
            fs.readFile('./views/index.html', function(err, data){
                if(err) {
                    return console.log(err.message);
                } 
                res.end(data);
            });
        }
        // 3.3、判断是否请求的是静态文件
        else if (url.indexOf('/views') != -1) {
            fs.readFile('.' + url, function(err, data){
                if(err) {
                    return console.log(err.message);
                } 
                res.end(data);
            });
        }
        // 3.4、判断请求的是否是getPath
        else if (url === '/getPath') {
            //将当前目录下的所有的路径读取出来,并且返回给浏览器的异步对象
            fs.readdir('./', function(err, files){
                if(err) {
                    return console.log(err.message);
                }
                // 将files数组转为json格式的字符串
                var str = JSON.stringify(files);
                // console.log(str);
                // 响应回浏览器
                res.end(str);
            });
        }
    });
    // 4、开启监听
    server.listen(3000, '192.168.81.1', function () {
        console.log('开启成功');
    });

但是此方法在打开网页后会出现小bug,即文件和目录分不清,图标都会显示文件夹的样子;文件大小和修改时间显示不正确,若要修复bug这需要后面的知识。

html:

      <style>
        h1 {
          border-bottom: 1px solid #c0c0c0;
          margin-bottom: 10px;
          padding-bottom: 10px;
          white-space: nowrap;
        }

        table {
          border-collapse: collapse;
        }

        th {
          cursor: pointer;
        }

        td.detailsColumn {
          -webkit-padding-start: 2em;
          text-align: end;
          white-space: nowrap;
        }

        a.icon {
          -webkit-padding-start: 1.5em;
          text-decoration: none;
        }

        a.icon:hover {
          text-decoration: underline;
        }

        a.file {
          background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAABnRSTlMAAAAAAABupgeRAAABHUlEQVR42o2RMW7DIBiF3498iHRJD5JKHurL+CRVBp+i2T16tTynF2gO0KSb5ZrBBl4HHDBuK/WXACH4eO9/CAAAbdvijzLGNE1TVZXfZuHg6XCAQESAZXbOKaXO57eiKG6ft9PrKQIkCQqFoIiQFBGlFIB5nvM8t9aOX2Nd18oDzjnPgCDpn/BH4zh2XZdlWVmWiUK4IgCBoFMUz9eP6zRN75cLgEQhcmTQIbl72O0f9865qLAAsURAAgKBJKEtgLXWvyjLuFsThCSstb8rBCaAQhDYWgIZ7myM+TUBjDHrHlZcbMYYk34cN0YSLcgS+wL0fe9TXDMbY33fR2AYBvyQ8L0Gk8MwREBrTfKe4TpTzwhArXWi8HI84h/1DfwI5mhxJamFAAAAAElFTkSuQmCC ") left top no-repeat;
        }

        a.dir {
          background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAd5JREFUeNqMU79rFUEQ/vbuodFEEkzAImBpkUabFP4ldpaJhZXYm/RiZWsv/hkWFglBUyTIgyAIIfgIRjHv3r39MePM7N3LcbxAFvZ2b2bn22/mm3XMjF+HL3YW7q28YSIw8mBKoBihhhgCsoORot9d3/ywg3YowMXwNde/PzGnk2vn6PitrT+/PGeNaecg4+qNY3D43vy16A5wDDd4Aqg/ngmrjl/GoN0U5V1QquHQG3q+TPDVhVwyBffcmQGJmSVfyZk7R3SngI4JKfwDJ2+05zIg8gbiereTZRHhJ5KCMOwDFLjhoBTn2g0ghagfKeIYJDPFyibJVBtTREwq60SpYvh5++PpwatHsxSm9QRLSQpEVSd7/TYJUb49TX7gztpjjEffnoVw66+Ytovs14Yp7HaKmUXeX9rKUoMoLNW3srqI5fWn8JejrVkK0QcrkFLOgS39yoKUQe292WJ1guUHG8K2o8K00oO1BTvXoW4yasclUTgZYJY9aFNfAThX5CZRmczAV52oAPoupHhWRIUUAOoyUIlYVaAa/VbLbyiZUiyFbjQFNwiZQSGl4IDy9sO5Wrty0QLKhdZPxmgGcDo8ejn+c/6eiK9poz15Kw7Dr/vN/z6W7q++091/AQYA5mZ8GYJ9K0AAAAAASUVORK5CYII= ") left top no-repeat;
        }

        a.up {
          background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAmlJREFUeNpsU0toU0EUPfPysx/tTxuDH9SCWhUDooIbd7oRUUTMouqi2iIoCO6lceHWhegy4EJFinWjrlQUpVm0IIoFpVDEIthm0dpikpf3ZuZ6Z94nrXhhMjM3c8895977BBHB2PznK8WPtDgyWH5q77cPH8PpdXuhpQT4ifR9u5sfJb1bmw6VivahATDrxcRZ2njfoaMv+2j7mLDn93MPiNRMvGbL18L9IpF8h9/TN+EYkMffSiOXJ5+hkD+PdqcLpICWHOHc2CC+LEyA/K+cKQMnlQHJX8wqYG3MAJy88Wa4OLDvEqAEOpJd0LxHIMdHBziowSwVlF8D6QaicK01krw/JynwcKoEwZczewroTvZirlKJs5CqQ5CG8pb57FnJUA0LYCXMX5fibd+p8LWDDemcPZbzQyjvH+Ki1TlIciElA7ghwLKV4kRZstt2sANWRjYTAGzuP2hXZFpJ/GsxgGJ0ox1aoFWsDXyyxqCs26+ydmagFN/rRjymJ1898bzGzmQE0HCZpmk5A0RFIv8Pn0WYPsiu6t/Rsj6PauVTwffTSzGAGZhUG2F06hEc9ibS7OPMNp6ErYFlKavo7MkhmTqCxZ/jwzGA9Hx82H2BZSw1NTN9Gx8ycHkajU/7M+jInsDC7DiaEmo1bNl1AMr9ASFgqVu9MCTIzoGUimXVAnnaN0PdBBDCCYbEtMk6wkpQwIG0sn0PQIUF4GsTwLSIFKNqF6DVrQq+IWVrQDxAYQC/1SsYOI4pOxKZrfifiUSbDUisif7XlpGIPufXd/uvdvZm760M0no1FZcnrzUdjw7au3vu/BVgAFLXeuTxhTXVAAAAAElFTkSuQmCC ") left top no-repeat;
        }

        html[dir=rtl] a {
          background-position-x: right;
        }

        #listingParsingErrorBox {
          border: 1px solid black;
          background: #fae691;
          padding: 10px;
          display: none;
        }
      </style>
    <body>
      <div id="listingParsingErrorBox" i18n-values=".innerHTML:listingParsingErrorBoxText">糟糕!Google Chrome无法解读服务器所发送的数据。请<a href="http://code.google.com/p/chromium/issues/entry">报告错误</a>,并附上<a href="LOCATION">原始列表</a>。</div>
      <span id="parentDirText" style="display:none" i18n-content="parentDirText">[上级目录]</span>
      <h1 id="header" i18n-content="header">C:\dev\ 的索引</h1>
      <table>
        <thead>
          <tr class="header" id="theader">
            <th i18n-content="headerName" onclick="javascript:sortTable(0);">名称</th>
            <th class="detailsColumn" i18n-content="headerSize" onclick="javascript:sortTable(1);">大小</th>
            <th class="detailsColumn" i18n-content="headerDateModified" onclick="javascript:sortTable(2);">修改日期</th>
          </tr>
        </thead>
        <tbody id="tbody">
          <tr>
            <td data-value=".."><a class="icon up" href="#">[上级目录]</a></td>
            <td class="detailsColumn" data-value="0"></td>
            <td class="detailsColumn" data-value="0"></td>
          </tr>
        </tbody>
      </table>
    </body>
    <script src="/views/jquery.min.js"></script>
    <!-- 3、通过浏览器发送一个异步请求到服务器,去请求当前服务器的目录数据 -->
    <script>
      $.ajax({
        url: '/getPath',
        type: 'GET',
        dataType: 'json',
        success: function(data){
          // console.log(data);
          // 通过js动态生成html代码
          var str = '';
          for(var i = 0; i < data.length; i ++) {
            str += "<tr>";
            str += '<td data-value="播放器/"><a class="icon dir" href="#">'+ data[i] +'</a></td>';
            str += '<td class="detailsColumn" data-value="0"></td>';
            str += '<td class="detailsColumn" data-value="1489037313">2018/8/11 下午1:28:33</td>';
            str += '</tr>';
          }
          // 将data动态渲染到页面上
          $('#tbody').append(str);
        }
      })
    </script>

(7)使用fs核心模块来判断路径是否为文件&文件夹

    var fs = require('fs');
    var str = './01.js';
    // 可以使用fs核心模块中的方法来进行判断
    // fs.stat用来判断路径的状态
    //  path:要判断的路径
    //  callback:判断之后的回调函数
    //      err:异常信息
    //      stats:状态对象(obj)
    //          size:大小
    //              如果是文件有大小
    //              如果是目录,没有大小
    //          mtime:内容被修改的时间
    fs.stat(str, function(err, stats){
        if(err) {
            return console.log(err.message);
        }
        // console.log(stats);
        if(stats.isFile()) {
            console.log(str + '是文件');
            console.log(stats.size);
        } else {
            console.log(str + '是目录');
        }
    });

(8)仿apach的目录浏览功能-服务器渲染

    var http = require('http');
    var fs = require('fs');
    //下载使用npm下载art-template 第三方包,用来渲染数据到html结构中
    var template = require('art-template');
    // 创建一个服务器
    var server = http.createServer();
    // 设置请求事件
    server.on('request', function (req, res) {
        // 如果读取根目录,并数据 + html结构响应回去
        var url = req.url;
        // 判断
        if (url === '/') {
            // 得到html结构
            //  readFile读取出来 的内容是十六进制的buffer数组
            fs.readFile('./views/index.html', function (err, data) {
                if (err) {
                    return console.log(err.message);
                }
                // res.end(data);
                // 得到数据
                fs.readdir('./', function (err1, files) {
                    if (err1) {
                        return console.log(err1.message);
                    }
                    // 区分文件和文件夹
                    var fileArr = [];
                    var dirArr = [];
                    var count = 0;
                    for (var i = 0; i < files.length; i++) {
                        (function (i) {
                            fs.stat(files[i], function (err2, stat) {
                                count ++;
                                if (err2) {
                                    return console.log(err2.message);
                                }
                                if (stat.isFile()) {
                                    fileArr.push({
                                        name: files[i],
                                        type: 'file',
                                        size: stat.size,
                                        time: stat.mtime
                                    });
                                } else {
                                    dirArr.push({
                                        name: files[i],
                                        type: 'dir',
                                        size: stat.size,
                                        time: stat.mtime
                                    });
                                }
                                if (count === files.length) {
                                    var newArr = dirArr.concat(fileArr);
                                    // newArr 就是我们要的数据对象
                                    // 将数据与结构结合
                                    // 数据: newArr [{name: ,type:'',size:'',time:''}]
                                    // 结构:data
                                    // 问题:如何装饰数据与结构结合:
                                    //    找第三方包:art-template可以用来帮助我们完成这个操作
                                    var htmlStr = template.render(data.toString(), {
                                        newArr: newArr
                                    });
                                    res.end(htmlStr);
                                }
                            });
                        })(i);
                    }
                })
            });
        }
    })
    // 开启服务器
    server.listen(3000, function () {
        console.log('running');
    });

3、 Node中的模块系统

(1)什么是模块?

(2)导入模块(require方法)

(3)导出模块

模块中定义的变量是局部的,

那如何在A模块使用B模块中定义好的变量呢?

这个问题, 就涉及到了模块加载机制

导出模块中的变量
验证module.exports与exports的关系:
    1)console.log(module.exports === exports);
    2)exports.a = 123;
    3)exports = fucntion() {}
    4)exports = modules.exports =  fucntion() {}
导入模块foo.js
    var a = 10;
    var b = 20;
    function add(){};

    module.exports.a = a;
    module.exports.b = b;
    module.exports.add = add;

    // 可以理解为在模块的末尾有这样一句代码: return module.exports;
    // return module.exports;
导入模块main.js
    // 1 导入模块
    var foo = require('./foo.js');
    // 2 使用模块中的成员                  
    console.log(foo.add);
    console.log(foo.a);

(4)模块加载机制

(5)模块分类及第三方模块(包)的使用

4、art-template 第三方包

(1)使用art-template

    // 1、遍历对象
    // var template = require('art-template');
    // // 有html结构
    // var str = '<ul><li><%=name%></li><li>{{age}}</li></ul>';
    // // 也有数据
    // var obj = {
    //     name: '张三',
    //     age: 18
    // };
    // // 结合
    // //  render可以结合html结构和数据
    // //      str:结构
    // //      obj:数据
    // var htmlStr = template.render(str, obj);
    // console.log(htmlStr);

    // 2、遍历数组
    var template = require('art-template');
    // 准备结构
    var str = '<ul>{{each arr}}<li>{{$index}}----{{$value.name}}----{{$value.age}}</li>{{/each}}</ul>';
    // 数据
    var arr = [
        {name: '张三', age: 18},
        {name: '李四', age: 30}
    ]
    // 结合
    var htmlStr = template.render(str, {
        arr: arr
    });
    console.log(htmlStr);

    //需要结合
    //  art-template的使用步骤:
    //  1、下载
    //  2、在html结构中书写art-template的语法
    //      输出:
    //          {{name}}
    //      条件:
    //          {{if 条件}} ... {{else if 条件}}... {{else}}
    //      循环
    //          {{each 数据}} {{$index}} {{$value}}  {{/each}}
    //  3、通过nodejs代码将结构与数据结合起来

(2)使用url核心模块来将参数转为对象

    // url核心模块可以帮助我们将路径后面的参数得到
    //  url: http://192.168.11.1:8080/abc/index.html?name=abc&age=18

    // 引用
    var url = require('url');
    // pase路径
    var strUrl = 'http://192.168.11.1:8080/abc/index.html?name=abc&age=18';
    var urlObj = url.parse(strUrl, true);
    console.log(urlObj);

5、npm包管理器

(1) npm 是什么

(2)npm 命令行工具

(3)package.json

(4) package-lock.json

三、ECMAScript 6

一般情况下不建议在window环境下面使用ES6

1、 严格模式

    'use strict'

2、 申明一个变量(let)

3、 申明一个常量 (const)

4、 字符串的一些扩展方法的使用

5、 模板字符串

6、 解构赋值

(1) 字符串的解构赋值

    const [a, b, c, d, e] = 'hello';
    a // "h"
    b // "e"
    c // "l"
    d // "l"
    e // "o"

(2)对象解构

    var obj = {
      name: '张三',
      age: 18
    }
    var {name, age} = obj;
    name // 张三
    age  // 18      

(3) 数组的解构

    var arr = ['a', 'b', 'c']
    var [x, y, z] = arr;
    x // 'a'
    y // 'b'
    z // 'c'

(4)其它特点

7、 箭头函数的推演

8、 对象中属性的简写

    //es5中对象: {add:add, substrict:substrict}
    //es6中对象: {add, substrict}  注意这种写法的属性名称和值变量是同一个名称才可以简写,否则要想es5那样的写法,例如: {addFun:add}
    var name = '李四';
    var age = 20;
    // ES6之前
    var obj = {
        name: name,
        age: age
    }
    //ES6之后
    var obj = {
        name,
        age
    }
    console.log(obj.name, obj.age);

9、 对象中方法的简写

    //es5中对象: {add:function(){}, substrict:function(){}}
    //es6中对象: {add(){}, substrict(){}}
    //ES6之前
    var obj = {
        name,
        age,
        sayHi: function(){
            console.log(`大家好,我叫${this.name}, 今年${this.age}岁了`);
        }
    }
    // ES6之后
    var obj = {
        name,
        age,
        sayHi(){
            console.log(`大家好,我叫${this.name}, 今年${this.age}岁了`);
        }
    }
    obj.sayHi();

10、promise

    // 需求:依次将三个文件中的内容读取出来并且输出: 0 ~ 1 ~ 2
    var fs = require('fs');
    // 读取0文件
    fs.readFile('./file/0.txt', function (err0, data0) {
        if (err0) {
            return console.log(err0.message);
        }
        console.log(data0.toString());
        // 读取1文件
        fs.readFile('./file/1.txt', function (err1, data1) {
            if (err1) {
                return console.log(err1.message);
            }
            console.log(data1.toString());
            // 读取2文件
            fs.readFile('./file/2.txt', function (err2, data2) {     
                if (err2) {
                    return console.log(err2.message);
                }
                console.log(data2.toString());
            });
        });
    });
    // 回调地狱

使用promise解决回调地狱

    // var p = new Promise(function(reject, resolve){
    //     if () {
    //         // 如果成功执行reject
    //     } else{
    //         // 如果失败执行resolve
    //     }
    // });

    // // 需求:依次将三个文件中的内容读取出来并且输出: 0 ~ 1 ~ 2
    // 创建一个promise对象读取0文件
    var fs = require('fs');
    // 一旦Promise被创建:
    //      promise的状态为: pending 等待
    //      promise执行以后,状态会发生改变
    //          pending -- fulfilled 说明执行成功  执行resolve方法
    //          pending -- rejected 说明执行失败  执行reject
    //          一旦对应的状态确定,就无法改变
    var p0 = new Promise(function (resolve, reject) {
        fs.readFile('./file/0.txt', function (err, data) {
            if (err) {
                reject(err);
            } else {
                resolve(data);
            }
        });
    });
    // 读取1文件
    var p1 = new Promise(function (resolve, reject) {
        fs.readFile('./file/1.txt', function (err, data) {
            if (err) {
                reject(err);
            } else {
                resolve(data);
            }
        });
    });
    // 调用:than
    p0
        .then(data => {
            console.log(data.toString());
            // 不返回值任何内容:返回值 为undefined
        })
        .then((res) => {
            console.log(res); // undeinfed
            console.log('第二个then方法'); 
            // 返回值为非promise对象
            return 'abc';
        })
        .then((str) => {
            console.log(str);// abc
            console.log('第三个then方法');
            // 返回值为promise对象
            return p1;
        })
        .then((data) => {
            console.log(data.toString());
            console.log('第四个then方法');
        });

四、Express

1、起步

安装:

    npm install --save express

hello world:

    // 引入express第三方包
    var express = require('express')
    // 创建一个express对象(express用来搭建web服务:相当于创建一了个服务器对象)
    var app = express()

    // 将来浏览器发送get请求,请求网站的根目录,会执行后面的回调函数
    //  回调函数有两个参数:
    //      req:请求对象
    //      res:响应对象
    app.get('/', function (req, res) {
      res.send('Hello World!')
    })

    // 开启监听:监听3000商品,
    // 当开启成功以后会执行后面的回调函数
    app.listen(3000, function () {
      console.log('Example app listening on port 3000!')
    })

基本路由:

    app.get('/', function (req, res) {
      res.send('Hello World!')
    })

    app.post('/', function (req, res) {
      res.send('Got a POST request')
    })

    app.put('/user', function (req, res) {
      res.send('Got a PUT request at /user')
    })

    app.delete('/user', function (req, res) {
      res.send('Got a DELETE request at /user')
    })

2、Express 中外置路由使用

router.js 文件代码如下:

    // 1. 加载外置路由 express 模块
    var express = require('express')

    // 2. 调用 express.Router() 方法,得到一个路由容器实例
    var router = express.Router()

    // 3. 为 router 添加不同的路由
    router.get('/', function (req, res) {
      res.send('hello express')
    })

    router.get('/add', function (req, res) {
      res.send('add')
    })

    // 4. 将 router 路由容器导出(路由对象暴露给外界)
    module.exports = router

在 app.js 文件中:

    // 使用express搭建服务
    var express = require('express')

    // 1. 加载路由模块
    var router = require('./router')

    var app = express()

    // 2. 将路由模块导出的路由容器 router 通过 app.use() 方法挂载到 app 实例上
    //    这样的话 app 实例程序就拥有了 router 的路由了
    app.use(router)

    // 把所有的路由添加到一个新的文件中(外置路由)

    // 开启监听
    app.listen(3000, function () {
      console.log('running...')
    })

3、res.render方法

index.js

    // res.render方法用来渲染html文件的
    var express = require('express');

    var app = express();
    // 注册 art-template
    app.engine('html', require('express-art-template'));

    // 注册路由
    app.get('/', (req,res) => {
        // 将静态页面响应回浏览器
        // 特点:它在渲染的时候会去一个固定的路径下面去找对应的art文件
        res.render('index.html', {
            name: '张三',
            age: 18
        });
    })

    app.listen(3000, () => {
        console.log('running');
    });

index.html

    <body>
        <ul>
            <li>{{name}}</li>
            <li>{{age}}</li>
        </ul>
    </body>

4、在 Express 中处理静态资源

    app.use(express.static('public'))
    app.use(express.static('files'))

    app.use('/public', express.static('public'))
    app.use('/aaa', express.static('public'))

    app.use('/static', express.static(path.join(__dirname, 'public')))

index.js

    // 引入express第三方包
    var express = require('express');
    // 创建一个express对象(express用来搭建web服务:相当于创建一了个服务器对象)
    var app = express();

    // 设置静态文件的路径
    // app.use(express.static('imgs')); // 设置完成以后,将来可以访问imgs中的静态文件
    // app.use('/imgs', express.static('imgs'));
    app.use('/abc', express.static('imgs'));


    // 注册模板引擎
    app.engine('html', require('express-art-template'));

    // 渲染静态文件
    app.get('/', function (req, res) {
        res.render('index.html');
    });

    app.listen(3000, function () {
        console.log('running');
    });

index.html

    <body>
        <img src="/abc/4.jpg" alt="">
    </body>

5、express 的中间件

五、使用nodejs来操作数据库

1、连接数据库

    // 使用nodejs来链接mysql
    // 1、引包
    var mySql = require('mysql');
    // 2、设置连接参数
    var connection = mySql.createConnection({
        host: 'localhost',
        user: 'root',
        password: '123456',
        database: 'class_one'
    });
    // 3、开启连接
    connection.connect();
    // 4、执行sql语句
    var strSql = 'SELECT * FROM person';
    connection.query(strSql, (err, result, fields) => {
        if (err) {
           return console.log(err.message);
        }
        console.log(result);
        // [ RowDataPacket { id: 1, name: '张三', age: 18, gender: '男' },
        // RowDataPacket { id: 3, name: '王五', age: 22, gender: '男' } ]
        console.log(fields);
        // 存储的是表中字段的信息
    });


2、增删改查

    // 引包
    var mysql = require('mysql');
    // 建立连接
    var connection = mysql.createConnection({
        host: 'localhost',
        user: 'root',
        password: '123456',
        database: 'class_one'
    });
    // 开启连接
    connection.connect();
    // 执行sql说到语句
    // 查询
    //      result: 就是数据表中的数据
    //      fields: 数据表中的字段的属性说明
    var strSql = 'SELECT * FROM person';
    // 新增
    //      result: OkPacket对象,这是一个成功对象,说明对数据库的操作成功了
    //          affactedRows: 受影响的行数
    //      fields: undeinfed
    var strSql = 'INSERT INTO person (name, age, gender) VALUES ("赵六", "33", "男")';
    // 修改
    //      result: OkPacket对象,这是一个成功对象,说明对数据库的操作成功了
    //          affactedRows: 受影响的行数
    //      fields: undeinfed
    var strSql = 'UPDATE person SET name="无情", age="80" WHERE id = 1'
    // 删除
    //      result: OkPacket对象,这是一个成功对象,说明对数据库的操作成功了
    //          affactedRows: 受影响的行数
    //      fields: undeinfed
    var strSql = 'DELETE FROM person WHERE id = 5'
    connection.query(strSql, (err, result, fields) => {
        if (err) {
            return console.log(err.message);
        }
        console.log(result);
        console.log(fields);
    });

六、cookie和session

1、cookie

server.js(服务器)

    var fs = require('fs');
    var express = require('express');
    var bodyParser = require('body-parser')
    var app = express();



    app.use(bodyParser.urlencoded({ extended: false }))
    app.use(bodyParser.json())

    // 设置静态文件
    app.use('/node_modules', express.static('node_modules'));

    // 1.0 设置路由
    // 设置一个首页
    app.get('/', function(req, res){
        // 请求头会带上一个cookie
        // console.log(req.headers.cookie);
        // 验证用户是否登录:只要判断请求头中是否带有cookie
        if (req.headers.cookie === "uName=admin") {
            // 说明登录过:
            res.send('用户已经登录过了,直接访问根上当');
        } else{
            res.send('<script>alert("用户还没有登录");window.location="/login"</script>');
        }
    });

    // 得到登录页面
    app.get('/login', function(req, res){
        fs.readFile('./views/login.html', function(err, data){
            res.end(data);
        });
    });

    // 完成提交数据的逻辑
    app.post('/login', function(req, res){
        // body-parser
        var uName = req.body.uName;
        var pwd = req.body.pwd;
        // 判断
        if (uName === "admin" && pwd === "888") {
            // 要将用户的登录信息保存起来:用cookie来保存
            // 向响应报文头中加入一段内容:cookie
            res.writeHead(200, {
                'set-cookie': 'uName=' + uName
            });
            // 登录成功
            // res.json({
            //     status: 200,
            //     msg: '成功'
            // });
            res.end(JSON.stringify({
                status: 200,
                msg: '成功'
            }));
        } else{
            // 登录失败
            res.json({
                status: 500,
                msg: '不成功'
            });
        }
    });
    app.listen(3000, function() {
        console.log('running');
    });

./views/login.html(客户端)

        <style>
            table {
                width: 400px;
                height: 200px;
                border-collapse: collapse;
                margin: 0 auto;
            }

            td {
                border: 1px solid #ccc;
            }
        </style>
    <body>
        <form id="form">
            <table>
                <tr>
                    <td>用户名:</td>
                    <td><input type="text" id="uName" name="uName"></td>
                </tr>
                <tr>
                    <td>密 码:</td>
                    <td><input type="text" id="pwd" name="pwd"></td>
                </tr>
                <tr>
                    <td></td>
                    <td><input type="button" id="login" value="登录"></td>
                </tr>
            </table>
        </form>
    </body>
    <script src="../node_modules/jquery/dist/jquery.min.js"></script>
    <script>
        // 给登录按钮注册事件
        $("#login").on('click', function (e) {
            e.preventDefault();// 阻止默认事件
            // 得到参数
            var params = $("#form").serialize();
            // var data = `uName=${$('#uName').val()}&pwd=${$('pwd').val()}`;
            // 将参数提交到服务器
           var ajax = $.ajax({
                url: '/login',
                type: 'POST',
                data: params,
                dataType: 'JSON'
            });
            // promise
            ajax.then(data => {
                // 判断状态
                if (data.status === 200) {
                    alert(data.msg);
                    // 跳转到首页
                    window.location = '/'
                } else {
                    // 跳转到登录页面
                    alert(data.msg);
                    window.location('/login');
                }
            });
        })
    </script>

2、session

server.js(服务器)

    var fs = require('fs');
    var express = require('express');
    var bodyParser = require('body-parser')
    var cookieSession = require('cookie-session');
    var app = express();

    app.use(bodyParser.urlencoded({ extended: false }))
    app.use(bodyParser.json())

    // 设置静态文件
    app.use('/node_modules', express.static('node_modules'));

    // 注册cookiesession
    app.use(cookieSession({
        name: 'session',
        keys: ['key1', 'key2']
    }))

    // 1、设置路由
    // 设置一个首页
    app.get('/', function(req, res){
       // 得到session
       // console.log(req.session.uName);
       var session = req.session.uName;
       if (session) {
           res.send('用户已经登录过一');
       } else {
           res.send('<script>alert("用户还没有登录");window.location="/login"</script>');
       }
    });

    // 得到登录页面
    app.get('/login', function(req, res){
        fs.readFile('./views/login.html', function(err, data){
            res.end(data);
        });
    });

    // 完成提交数据的逻辑
    app.post('/login', function(req, res){
        // body-parser
        var uName = req.body.uName;
        var pwd = req.body.pwd;
        // 判断
        if (uName === "admin" && pwd === "888") {
            // 要将用户的登录信息保存起来:用session来保存
            req.session.uName = uName;
            res.end(JSON.stringify({
                status: 200,
                msg: '成功'
            }));
        } else{
            // 登录失败
            res.json({
                status: 500,
                msg: '不成功'
            });
        }
    });
    app.listen(3000, function() {
        console.log('running');
    });

./views/index.html(客户端)

    <body>
        <form id="form">
            <table>
                <tr>
                    <td>用户名:</td>
                    <td><input type="text" id="uName" name="uName"></td>
                </tr>
                <tr>
                    <td>密 码:</td>
                    <td><input type="text" id="pwd" name="pwd"></td>
                </tr>
                <tr>
                    <td></td>
                    <td><input type="button" id="login" value="登录"></td>
                </tr>
            </table>
        </form>
    </body>
    <script src="../node_modules/jquery/dist/jquery.min.js"></script>
    <script>
        // 给登录按钮注册事件
        $("#login").on('click', function (e) {
            e.preventDefault();// 阻止默认事件
            // 得到参数
            var params = $("#form").serialize();
            // var data = `uName=${$('#uName').val()}&pwd=${$('pwd').val()}`;
            // 将参数提交到服务器
           var ajax = $.ajax({
                url: '/login',
                type: 'POST',
                data: params,
                dataType: 'JSON'
            });
            // promise
            ajax.then(data => {
                // 判断状态
                if (data.status === 200) {
                    alert(data.msg);
                    // 跳转到首页
                    window.location = '/'
                } else {
                    // 跳转到登录页面
                    alert(data.msg);
                    window.location('/login');
                }
            });
        })

    </script>
上一篇 下一篇

猜你喜欢

热点阅读