• Nodejs入门


    一、nodejs简介

    nodejs的由来、解决的问题。
    nodejs是一个服务端工具,使用js语言,集成了自身的很多模块。
    nodejs特点:单线程、非阻塞IO、事件驱动。
    多线程在处理高并发的时候,需要的资源也会随着请求数增加而增加,
    在大多数场景下,我们的并发并不是很高,尤其是中小型站点,资源要求很低,响应速度还很快。
    nodejs让不适应于大型站点,毕竟大型站点是少数。
    为了处理请求更快,nodejs采用了非阻塞IO(异步IO),有了异步IO还是不能很好的完成单线程请求,
    我们还要有一个事件驱动机制,把回调结果及时传给之前的请求。

    二、nodejs中的模块

    1、模块A暴露,模块B引用
    模块A要被其他模块引用,必须先暴露对应的内容,可以是变量,也可以是函数、类等。
    一个模块的本质是一个函数,所以模块B引用模块A的时候,需要先导入。(函数有自己的命名空间,是私有属性和方法)

    2、查看模块是函数的方法:
    console.log(arguments.callee + '');

    可以得知实际的函数是:
    function (exports, require, module, __filename, __dirname) {
    console.log(arguments.callee + '');
    }

    3、模块中的所有代码都是函数体,并且在函数执行的同时传递进了5个实参
    exports:该对象用来将函数内部的局部变量或局部函数暴露到外部
    require:用来引入外部的模块
    module:代表的是当前模块本身, exports就是module的属性; 我们既可以使用 exports 导出,也可以使用module.exports导出
    __filename:当前模块的完整路径
    __dirname:当前模块所在文件夹的完整路径


    4、模块暴露的两种方法
    exports和module.exports

    (function(exports,require,module,__filename,__dirname){
    exports = module.exports={};
    ......
    return module.exports;
    })

    5个参数里面的module表示当前模块本身,exports是暴露模块的属性。


    二者的不同之处:
    ============================
    let site = '撩课学院';
    let func = ()=>{
    console.log(site);
    };
    let obj = {
    name: '张三'
    };


    exports.site = site;
    exports.func = func;
    exports.obj = obj;

    module.exports.site = site;
    module.exports.func = func;
    module.exports.obj = obj;

    //当二者通过属性(值类型,类似python中的不可变元素)进行对外暴露时,二者的引用地址是一样的
    //但是,当二者通过对象进行对外暴露时,相当于二者的引用地址已经改变了。
    //所以,通过exports方式到时候,在其他模块导入当前模块时,内容为空对象{},而module.exports为真正的对象。

    exports和module.exports的区别:
    exports只能使用 . 语法来对外暴露变量;
    module.exports即可以使用.语法,也可以赋值给一个对象来暴露
    exports指向的对象是module.exports的指针。
    /*
    module.exports = {
    site,
    func,
    obj
    };
    这里会输出
    { site: '撩课学院', func: [Function: func], obj: { name: '张三' } }
    */

    /*exports = {
    site,
    func,
    obj
    };
    这里会输出
    {}
    */
    ==============================================

    三、模块类型

    内建模块:由C++编写的,无需require,类似python中的abs、sum
    文件模块:自己写的模块
    核心模块:由node引擎提供的模块
    原生模块:fs/http/path等,需要require
    第三方模块:npm install的,别人写好的模块。类似python中通过pip安装的模块。

    注意:内建模块和原生模块的区别是需要require,类似python中的 abs模块和os模块的区别。abs模块无需import,而os模块需要import后才能使用。

    node是一个工具,它本身并不是一门语言,而是需要通过js来实现,而JavaScript中只保留了ECMAScrip,没有Dom和Bom。
    取而代之的是一堆的模块。

    四、npm(node package manager)

    node里面的包管理,通过npm init初始化生成包信息,package.json文件会有包管理信息,包括包名、版本信息。其他人可以根据package.json直接执行npm install就可以安装依赖,把环境跑起来。

    五、模块学习

    fs模块


    stream模块

    pipe管道

    http模块

     

    六、简易web服务器

    1、简易web服务器搭建
    const http = require('http');

    const server = http.createServer((req,res)=>{
    //各种中间介处理
    }).listen(3000,'127.0.0.1',()=>{
    console.log('server is running');
    });


    2、url解析方法
    //老的方式,url.parse
    const url = require('url');
    const myURL = url.parse('http://www.baidu.com:9999/p/a/t/h?name=xuequn&age=22');
    console.log(myURL);

    //新的方式,通过URL实例化一个对象
    const myURL = new URL('http://www.baidu.com:9999/p/a/t/h?name=xuequn&age=22');
    console.log(myURL);

    3、http日志记录和response头设置
    //通过写流直接wirte内容
    let out = fs.createWriteStream(path.join(__dirname,'requrest.log'));
    out.write('01method:'+req.method+' ');

    //response头设置
    const http = require('http');

    http.createServer((req, res)=>{
    console.log(res.headersSent ? '响应头已经发送' : '响应头未发送');
    // 设置隐式响应头
    res.setHeader('Content-Type', 'text/html;charset=utf-8');
    res.writeHead(200, 'ok');
    res.write('<h1>Hello, World!</h1>');
    // 本次响应结束
    res.end('<h1>你好,世界!</h1>');
    console.log(res.headersSent ? '响应头已经发送' : '响应头未发送');
    }).listen(3000, '127.0.0.1', ()=>{
    console.log('服务器已经启动~')
    });


    4、http处理post数据
    const http = require('http');
    const queryString = require('querystring');
    const util = require('util');

    let server = http.createServer((req,res)=>{
    let postData='';
    // post请求, 得做事件监听
    req.on('data', (data)=>{
    postData+=data;
    });

    // 监听数据接收完毕
    req.on('end', ()=>{
    //解析post数据
    postData = queryString.parse(postData);
    console.log(postData.user);
    console.log(postData.pwd);
    res.end('数据接收成功!');
    });
    }).listen(3000, '127.0.0.1');

    5、web服务器多页面处理
    原理:通过文件名和路由对比,读取文件,然后设置headers后,res.end返回数据到前端。

    6、web服务器多页面处理改进版本
    5中每次通过文件名和路由对比的方式对于页面比较多的情况,十分不友好。
    改进方法:通过判断前端请求的路由,读取出文件,然后根据文件的后缀进行headers设置后,然后返回给前端。

    七、express入门

    1、express入门
    express的核心:路由、视图、中间介。
    中间介通过next参数以及next()调用进行中间介的流动。

    视图用于实现业务逻辑的部分。
    路由是不同url对应不同的业务逻辑功能和页面反馈。

    典型的架构模式:MVC

    2、Express 应用程序生成器

    通过应用生成器工具 express-generator 可以快速创建一个应用的骨架。

    express-generator 包含了 express 命令行工具。通过如下命令即可安装:

    npm install express-generator -g
    

      -h 参数可以列出所有可用的命令行参数:

    $ express -h
    
      Usage: express [options] [dir]
    
      Options:
    
        -h, --help          输出使用方法
            --version       输出版本号
        -e, --ejs           添加对 ejs 模板引擎的支持
            --hbs           添加对 handlebars 模板引擎的支持
            --pug           添加对 pug 模板引擎的支持
        -H, --hogan         添加对 hogan.js 模板引擎的支持
            --no-view       创建不带视图引擎的项目
        -v, --view <engine> 添加对视图引擎(view) <engine> 的支持 (ejs|hbs|hjs|jade|pug|twig|vash) (默认是 jade 模板引擎)
        -c, --css <engine>  添加样式表引擎 <engine> 的支持 (less|stylus|compass|sass) (默认是普通的 css 文件)
            --git           添加 .gitignore
        -f, --force         强制在非空目录下创建
    

      例如,如下命令创建了一个名称为 myapp 的 Express 应用。此应用将在当前目录下的 myapp 目录中创建,并且设置为使用 Pug 模板引擎(view engine):

    $ express --view=pug myapp
    
       create : myapp
       create : myapp/package.json
       create : myapp/app.js
       create : myapp/public
       create : myapp/public/javascripts
       create : myapp/public/images
       create : myapp/routes
       create : myapp/routes/index.js
       create : myapp/routes/users.js
       create : myapp/public/stylesheets
       create : myapp/public/stylesheets/style.css
       create : myapp/views
       create : myapp/views/index.pug
       create : myapp/views/layout.pug
       create : myapp/views/error.pug
       create : myapp/bin
       create : myapp/bin/www
    

      然后安装所有依赖包:

    $ cd myapp
    $ npm install
    

      在 MacOS 或 Linux 中,通过如下命令启动此应用

    $ DEBUG=myapp:* npm start
    

      在 Windows 中,通过如下命令启动此应用:

    > set DEBUG=myapp:* & npm start
    

      

    然后在浏览器中打开 http://localhost:3000/ 网址就可以看到这个应用了。

    通过生成器创建的应用一般都有如下目录结构:

    .
    ├── app.js
    ├── bin
    │   └── www
    ├── package.json
    ├── public
    │   ├── images
    │   ├── javascripts
    │   └── stylesheets
    │       └── style.css
    ├── routes
    │   ├── index.js
    │   └── users.js
    └── views
        ├── error.pug
        ├── index.pug
        └── layout.pug
    
    7 directories, 9 files
    

      


    express脚手架目录结构:
    bin:服务器启动文件
    public:静态文件
    routes:路由文件
    views:视图文件
    app.js:项目入口文件

    八、MongoDB基础和CURD

    九、配置babel

    目的:转化高阶语法

    babel基础配置:
    a、新建.babelrc文件
    b、配置babel为开发环境
    {
    "presets": [
    "env"
    ]
    }
    c、npm install babel-preset-env --save-dev(编译环境准备)

    为什么要用--save-dev?生产环境不需要,上线部署:npm install --production


    d、npm i babel-register --save-dev(es6转es5的转换工具)

    babel-register可以理解成一个小插件,将es6的东西转成es5

    e、babel启动环境配置

    新建main.js

    1)中间过渡

    require('babel-register');
    require('./app');

    2)app.js

    // const express = require('express');
    import express from 'express'

    3)运行

    node main.js

    f、babel高阶语法转换过程

    1)安装

    npm install -g babel-cli
    npm install babel-cli --save-dev
    

      

    2)转化

    babel ./app.js

    3)保存转换后的文件到指定目录

    babel src -d dist

    4) 开发和生产环境分离配置
    package.json文件修改:
    "scripts": {
    "test": "echo "Error: no test specified" && exit 1",
    "dev": "node main.js",
    "build": "babel src -d dist",
    "start": "node dist/app.js"
    },
    a、开发环境
    npm run dev
    b、线上环境
    npm run build
    npm run start

    十、项目配置

    a、配置静态路径,并抽取到配置文件config.js
    import {join} from 'path';
    export default {
    viewsPath: join(__dirname, '../views'),
    publicPath: join(__dirname, '../public'),
    }
    b、配置公共资源访问路径app.js
    app.use(express.static(config.publicPath));

    c、配置模板引擎(nunjucks模板引擎能够作用到views文件夹中的模板)app.js
    nunjucks.configure(config.viewsPath, {
    autoescape: true,
    express: app,
    noCache: true // 不使用缓存,模板每次都会重新编译
    });
    d、引入路由
    import indexRouter from './../routes/index'
    e、挂载路由
    app.use(indexRouter);

    十一、自动重启更新操作

    npm i nodemon -g --save
    修改package.json文件中的启动方式:
    "scripts": {
    "test": "echo "Error: no test specified" && exit 1",
    "dev": "nodemon main.js",//开发环境
    "build": "babel src -d dist",// 打包
    "start": "node dist/app.js" // 启动打包后的文件
    },

    十二、使用nunjucks模板

    模块化思想
    和jinjia2类似

    基础模板制作:base抽取

     

    十三、nodejs中使用第三方模块

    a、安装
    npm i jquery --save
    b、配置路径
    //配置访问外部资源,通过静态static方式访问
    app.use('/node_modules', express.static(path.join(__dirname, '/node_modules')));
    c、引入
    //访问node_modules,其实就是后面的静态static路径
    <script src="node_modules/jquery/dist/jquery.js"></script>

    十四、文件上传

    服务端:
    1、原生方式提交:

    app.post('/', (req, res, next)=>{
    console.log('1111');
    let data = '';
    req.on('data', (chunk)=>{
    data += chunk;
    });
    req.on('end', ()=>{
    fs.writeFile(path.join(__dirname, 'data.txt'), data, (err)=>{
    if(!err){
    res.end('success!');
    }
    });
    });
    });
    

      


    2、formdata方式提交:

    app.post('/', (req, res, next) => {
    // 1. 创建实例
    let form = new formidable.IncomingForm();
    // 2. 指定文件的上传文件夹
    form.uploadDir = path.join(__dirname, 'dir');
    // 3. 指定文件的后缀
    form.keepExtensions = true;
    
    // 解析request发送过来的数据
    form.parse(req, function(err, fields, files) {
    if(err){
    throw err;
    }
    console.log(fields);
    console.log(files);
    res.end('success');
    });
    });
    

      

    客户端:
    1、原生方式
    原生方式提交,客户端无须操作。
    2、formdata上传

    $('#btn_sub').on('click', function () {
    var $form = $('form');
    $.ajax({
    url:$form.attr('action'),
    type:$form.attr('method'),
    //实例化formdata,会把input里面的键值对解析
    data: new FormData($form[0]),
    // 不要处理转化成一个查询字符串
    processData: false,
    contentType: false,
    success: function (data) {
    console.log(data);
    }
    })
    });
    

      

     

    
    
  • 相关阅读:
    问题解决(2)
    问题解决(1)
    ubuntu16.04spyder闪退
    ubuntu16.04安装caffe
    python做批量剪切、旋转等小程序
    html中如何使得改变背景的透明度时,背景上的文字透明度不被改变
    css下拉菜单制作
    float浮动
    css盒子模型
    css选择器,背景样式,文本属性
  • 原文地址:https://www.cnblogs.com/skyflask/p/11832163.html
Copyright © 2020-2023  润新知