Node.js模块

1模块概述

● 在Node.js中,以模块为单位划分所有功能,并且提供了一个完整的模块加载机制,这时的我们可以将应用程序划分为各个不同的部分。
不可能用一个js文件去写全部的业务。肯定要有MVC。

● 狭义的说,每一个JavaScript文件都是一个模块;而多个JavaScript文件之间可以相互require,他们共同实现了一个功能,他们整体对外,又称为一个广义上的模块。
它的好处显而易见:
√ 减少重复代码量,增加可读性
√ 方便进行代码规划
√ 方便使用第三方模块

2模块的概念

假设目录结构:
这里写图片描述

0.注意事项:

require()引入的文件是以当前的文件的相对位置引入的。

1.引入需要的js文件中的变量

● Node.js中,一个JavaScript文件中定义的变量、函数,都只在这个文件内部有效。当需要从模块外部引用这些变量、函数时,必须使用exports对象进行暴露。使用者要用require()命令引用这个JS文件。
例1.
foo.js文件中的代码:

var msg = "你好";
// msg这个变量,是一个js文件内部才有作用域的变量。
//如果别人想用这个变量,那么就要用exports进行暴露。
exports.msg = msg;

使用者01.js:

//使用者用foo来接收exports对象,也就是说,这里的foo变量,就是文件中的exports变量。
var foo = require("./test/foo.js");

console.log(foo.msg);

结果为:‘你好’

例2.
foo.js文件中的代码:

//如果只有输出
console.log(‘ppppp’)

使用者02.js:

//使用者相当于直接调用foo.js。
var foo = require("./test/foo.js");

结果为:
这里写图片描述

2.向外暴露多个变量的函数

● 一个JavaScript文件,可以向外exports无数个变量、函数。但是require的时候,仅仅需要require这个JS文件一次。使用的它的变量、函数的时候,用点语法即可。所以,无形之中,增加了一个顶层命名空间。

扫描二维码关注公众号,回复: 886615 查看本文章

foo.js文件中的代码:
可以用exports暴露很多东西,比如函数、变量。

var msg = "你好";
var info = "呵呵";

function showInfo(){
     console.log(info);
}

exports.msg = msg;
exports.info = info;
exports.showInfo = showInfo;

使用者01.js:
只需要require一次。

//相当于增加了顶层变量。所有的函数以及变量都从这个顶层变量走
var foo = require("./test/foo.js")

console.log(foo.msg);
console.log(foo.info);
foo.showInfo();

结果为:‘你好’ ‘呵呵’ ‘呵呵’
02—案例04

Node中,js文件和js文件,就是被一个个exports和require构建成为网状的。
不是靠html文件统一在一起的。

3.暴露一个类

● 可以将一个JavaScript文件中,描述一个类。用
module.export = 构造函数名;
的方式向外暴露一个类。

foo.js文件中的代码:

function People(name,sex,age){
    this.name = name;
    this.sex = sex;
    this.age = age;
}

People.prototype = {
    sayHello : function(){
        console.log(this.name + this.sex + this.age);
    }
}

//此时,People就被视为构造函数,可以用new来实例化了。
module.exports = People;

使用者01.js:

var People = require("./test/People.js");
var xiaoming = new People("小明","男","12");
xiaoming.sayHello();

结果:”小明男12”
02—案例05

也就是说,js文件和js文件之间有两种合作的模式
1) 某一个js文件中,提供了函数,供别人使用。 只需要暴露函数就行了; exports.msg=msg;
2) 某一个js文件,描述了一个类。 module.exports = People;

4.引用node_modules目录下的文件

● 如果在require命令中,这么写:

//没有写./, 所以不是一个相对路径。是一个特殊的路径
var foo = require("foo.js");   

可以看到引用的不再是相对路径了,所以会直接去node_modules目录下找
那么Node.js将该文件视为node_modules目录下的一个文件

● node_modules文件夹并不一定在同级目录里面,在任何直接祖先级目录中,都可以。甚至可以放到NODE_PATH环境变量的文件夹中。这样做的好处稍后你将知道:分享项目的时候,不需要带着modules一起给别人。

● 我们可以使用文件夹来管理模块,比如

var bar = require("bar"); 

那么Node.js将会去寻找node_modules目录下的bar文件夹中的index.js去执行。
但是如果在node_modules目录下的bar文件夹中的index.js不存在,需要引用是app.js文件。需要用到package.json文件
每一个模块文件夹中,推荐都写一个package.json文件,这个文件的名字不能改。node将自动读取里面的配置。有一个main项,就是入口文件:

{
  "name": "kaoladebar",
  "version": "1.0.1",
  "main" : "app.js"
}6  

package.json文件,要放到模块文件夹的根目录去。
02—案例06

3 NPM

模块就是一些功能的封装,所以一些成熟的、经常使用的功能,都有人封装成为了模块。并且放到了社区中,供人免费下载。
这个伟大的社区,叫做npm。 也是一个工具名字 node package management
https://www.npmjs.com/

去社区搜索需求,然后点进去,看api。
如果要配置一个模块,那么直接在cmd使用

npm install 【模块名字】

就可以安装。 模块名字全球唯一。加上—save就可以同步到package.json
安装的时候,要注意,命令提示符的所在位置。

1.我们的依赖包,可能在随时更新,我们永远想保持更新,或者某持某一个版本;
2.项目越来越大的时候,给别人看的时候,没有必要再次共享我们引用的第三方模块。

我们可以用package.json来管理依赖。
在cmd中,使用npm init可以初始化一个package.json文件,用回答问题的方式生成一个新的package.json文件。
使用

npm install

将能安装所有依赖。
npm也有文档,这是package.json的介绍:
https://docs.npmjs.com/files/package.json

4实例—引入外部router

router是外置的一个js文件,让程序可读性强

01.js:

var http = require("http");
var router = require("./router.js");

//创建服务器
var server = http.createServer(function(req,res){
    if(req.url == "/"){
        router.showIndex(req,res);
    }else if(req.url.substr(0,9) == "/student/"){
        router.showStudent(req,res);
    }else{
        router.show404(req,res);
    }
});

server.listen(3000,"127.0.0.1");

router.js (与01.js同级)

exports.showIndex = showIndex;
exports.showStudent = showStudent;
exports.show404 = show404;

function showIndex(req,res){
    res.writeHead(200,{"Content-Type":"text/html;charset=UTF8"});
    res.end("我是首页");
}

function showStudent(req,res){
    var id = req.url.substr(9,6);
    res.writeHead(200,{"Content-Type":"text/html;charset=UTF8"});
    res.end("我是学生页面" + id);
}

function show404(req,res){
    res.writeHead(404,{"Content-Type":"text/html;charset=UTF8"});
    res.end("404");
}

02—案例10

5原生的get请求

我们前面用到的都是get请求,现在我们来使用post请求
首先需要from.html来提交表单

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <form action=" http://127.0.0.1:3000/dopost" method="post" >
        <p>
            姓名 : <input type="text" name="name">
        </p>
        <p>
            性别 : 
             <input type="radio" name="sex" value="男"><input type="radio" name="sex" value="女"></p>
        <p>
            爱好:
            <input type="checkbox" name="hobby" value="睡觉" />睡觉
            <input type="checkbox" name="hobby" value="吃饭" />吃饭
            <input type="checkbox" name="hobby" value="足球" />足球
        </p>
        <p>
            <input type="submit" />
        </p>
    </form>
</body>
</html>

Node的js:

var http = require("http");
//可以将字符串转化为对象
var querystring = require("querystring");


//创建服务器
var server = http.createServer(function(req,res){
    //如果你的访问地址是这个,并且请求类型是post
    if(req.url == "/dopost" && req.method.toLowerCase() == "post"){
        var alldata = "";
        //下面是post请求接收的一个公式
        //node为了追求极致,它是一个小段一个小段接收的。
        //接受了一小段,可能就给别人去服务了。防止一个过大的表单阻塞了整个进程
        req.addListener("data",function(chunk){
            alldata += chunk;
        });
        //全部传输完毕
        req.addListener("end",function(){
            var datastring = alldata.toString();
            res.end("success");
            //将datastring转为一个对象
            var dataObj = querystring.parse(datastring);
            console.log(dataObj);
            console.log(dataObj.name);
            console.log(dataObj.sex);
        });
    }
});

server.listen(3000,"127.0.0.1");
[02—案例11](https://github.com/haochangdi123/cleanUP-Node.js/blob/master/02/11.js)

querystring API:
http://nodejs.cn/api/querystring.html#querystring_querystring_parse_str_sep_eq_options

6利用formidabled或去上传的图片和数据

首先也是利用form.html提交表单
注意用formidabled获取图片以及表单信息需要在form表单中加入enctype=”multipart/form-data”属性
API: 利用npm搜索formidabled就可以了
https://www.npmjs.com/package/formidable

1.提交

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <!--注意:enctype="multipart/form-data"-->
    <form action="http://127.0.0.1:3000/dopost" method="post" enctype="multipart/form-data">
        <p>
            姓名 : <input type="text" name="name">
        </p>
        <p>
            性别 : 
             <input type="radio" name="sex" value="男"><input type="radio" name="sex" value="女"></p>
        <p>
            爱好:
            <input type="checkbox" name="hobby" value="睡觉" />睡觉
            <input type="checkbox" name="hobby" value="吃饭" />吃饭
            <input type="checkbox" name="hobby" value="足球" />足球
        </p>
        <p>
            图片:
            <input type="file" name="tupian" />
        </p>
        <p>
            <input type="submit" />
        </p>
    </form>
</body>
</html>

这里写图片描述

Node的js:
Formidable的代码不用记住,可以直接去查看API

var http = require("http");
var formidable = require('formidable');

//创建服务器
var server = http.createServer(function(req,res){
    //如果你的访问地址是这个,并且请求类型是post
    if(req.url == "/dopost" && req.method.toLowerCase() == "post"){
        //Creates a new incoming form.
        var form = new formidable.IncomingForm();
        //设置文件上传存放地址(放置在同级的uploads文件夹下)
        form.uploadDir = "./uploads";
        //执行里面的回调函数的时候,表单已经全部接收完毕了。
        form.parse(req, function(err, fields, files) {
            if(err){
                throw err;
            }
            console.log(fields);
            console.log(files);
            //所有的文本域、单选框,都在fields存放;
            //所有的文件域,files
            res.writeHead(200, {'content-type': 'text/plain'});

            res.end("成功");
        });
    }
});

server.listen(3000,"127.0.0.1");

结果:
这里写图片描述
可以看到console.log了两个对象,第一个是fields,第二个是files,也就是上传的图片的相关信息
比如获取上传图片的名字:
files.tupian.name
上传后的图片:
这里写图片描述
02—案例12

2.更改上传的文件的名字

我们可以看到上传的图片我们是没有办法直接用的,必要要更改上传后文件的名字

var http = require("http");
var fs = require("fs");
var path = require("path");
//下面的不是自带的模块,需要install
var formidable = require('formidable');
var sd = require("silly-datetime");


//创建服务器
var server = http.createServer(function(req,res){
    //如果你的访问地址是这个,并且请求类型是post
    if(req.url == "/dopost" && req.method.toLowerCase() == "post"){
        //Creates a new incoming form.
        var form = new formidable.IncomingForm();
        //设置文件上传存放地址
        form.uploadDir = "./uploads";
        //执行里面的回调函数的时候,表单已经全部接收完毕了。
        form.parse(req, function(err, fields, files) {
            if(err){
               throw err;
            }
            //时间,使用了第三方模块,silly-datetime
            var ttt = sd.format(new Date(), 'YYYYMMDDHHmmss');
            var ran = parseInt(Math.random() * 89999 + 10000);
            //获取上传文件的扩展名
            var extname = path.extname(files.tupian.name);
            //执行改名
            var oldpath = __dirname + "/" + files.tupian.path;
            //新的路径由三个部分组成:时间戳、随机数、拓展名
            var newpath = __dirname + "/uploads/" + ttt + ran + extname;

            //改名
            fs.rename(oldpath,newpath,function(err){
                if(err){
                    throw Error("改名失败");
                }
                res.writeHead(200, {'content-type': 'text/plain'});
                res.end("成功");
            });
        });
    }else if(req.url == "/"){
        //呈递form.html页面
        fs.readFile("./form.html",function(err,data){
            res.writeHead(200, {'content-type': 'text/html'});
            res.end(data);
        })
    }else{
        res.writeHead(404, {'content-type': 'text/html'});
        res.end("404");
    }
});

server.listen(3000,"127.0.0.1");

结果:
这里写图片描述
02—案例13

7一些常用的后台模板引擎—ejs

<a href="<%= url %>"><img src="<%= imageURL %>" alt=""></a>

数据绑定,就成为一个完整的html字符串了。
前台的模板,我们现在要学习的是后台的模板。
后台模板,著名的有两个,第一个叫做ejs; 第二个叫做jade。

是npm第三方包。

1.先说EJS

Embedded JavaScript templates
API:npm 搜索ejs
https://www.npmjs.com/package/ejs
安装ejs安装包

后台模板引擎

  <ul>
        <% for(var i = 0 ; i < news.length ; i++){ %>
            <li><%= news[i] %></li>
        <% } %>
  </ul>
var dictionary = {
        a:6,
        news : ["今天好开心 ","好好学习","哈哈哈哈哈"]
};

例如:
目录结构
这里写图片描述
Index.ejs

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <h1>好高兴啊,今天我买了一个iphone<%= a %>s</h1>
    <ul>
        <%
            for(var i = 0 ; i < news.length ; i++){
                if(news[i].count > 15){
        %>
                <li><%= news[i].title %></li>
        <%
                }
            }
        %>
    </ul>
</body>
</html>

Node 01.js
API:npm 搜索ejs
https://www.npmjs.com/package/ejs
安装ejs安包

var ejs = require("ejs");
var fs = require("fs");
var http = require("http");


var server = http.createServer(function(req,res){
    fs.readFile("./views/index.ejs",function(err,data){
        //绑定模板
        var template = data.toString();
        var dictionary = {
            a:6,
            news : [
                {"title":"我爱你","count":10},
                {"title":"哈哈哈哈","count":20},
                {"title":"逗你玩儿的","count":30}
            ]
        };
        var html = ejs.render(template,dictionary);

        //显示
        res.writeHead(200,{"Content-Type":"text/html;charset=UTF8"});
        res.end(html);
    });
});

server.listen(3000,"127.0.0.1");

结果:
只有count>15的才显示
这里写图片描述
02—案例15

githup地址:https://github.com/haochangdi123/cleanUP-Node.js

猜你喜欢

转载自blog.csdn.net/haochangdi123/article/details/78390434