一、前言
本次内容主要包括:
1.node.js中的模块系统
2、解决上篇中服务器响应的汉字乱码问题
二、知识
1、node中的模块 分为三种:
核心模块(node定义的如前面用到的fs,http模块)
第三方模块
自定义模块。可以通过require()加载第三模块
2、node.js中没有全局作用域,只有模块作用域,(也就是说,不同模块之间的属性和方法互不干扰)
aa.js
var foo = 'aaa'; console.log('a start'); require('./bb.js');//这里用node.js来加载了一个我们自定义的模块 console.log('a end'); console.log(foo);
bb.js
console.log('b start'); var foo='bbb'; console.log('b end');
在aa.js中定义了一个foo='aaa' ,在bb.js中定义了一个foo="bbb"按照我们之前的思维,打印出来的应该是bbb,因为后面的内容会将aa.js中定义的内容覆盖,,,但是node中没有全局作用域, aa.js和bb.js中的内容是互补干扰的
3.如何让模块之间通信
如果模块和模块之间不能相互访问到各自里面定义的方法,那么加载模块将是毫无意义的,因为加载模块的目的不是简单的执行里面的代码,而是使用里面的方法,
看看require的作用:加载模块并执行代码,还可以拿到被加载模块导出的对象,拿到这个导出的对象之后,就可以访问挂载到这个对象里的一些属性和方法
例一:访问挂载对象上的属性
a.js
console.log('ajs start'); //利用require的第二个作用:拿到被加载模块导出的对象 var bExport=require('./b.js'); console.log(bExport.foo); console.log('a ends');
b.js
console.log('b start'); exports.foo="200"; console.log('b end');
在a.js中就可以通过,对象.的方式访问到我挂在exports上面的属性和方法,
例二:访问挂载对象上的方法
a.js
console.log('a start'); var Bexports=require('./b2.js'); console.log(Bexports.foo(10,20)); console.log('a ends');
exports.foo = function(a,b){ return a+b; } exports.foo()
3.解决服务器响应汉字的时候乱码的问题
// 在服务端默认发送的数据,其实是 utf8 编码的内容
// 但是浏览器不知道你是 utf8 编码的内容
// 浏览器在不知道服务器响应内容的编码的情况下会按照当前操作系统的默认编码去解析
// 中文操作系统默认是 gbk
// 解决方法就是正确的告诉浏览器我给你发送的内容是什么编码的
// 在 http 协议中,Content-Type 就是用来告知对方我给你发送的数据内容是什么类型
// res.setHeader('Content-Type', 'text/plain; charset=utf-8')
// res.end('hello 世界')
可以找一个网站访问一下,然后在控制台中拿到响应的内容
写一段脚本测试一下:
var http = require('http'); var server = http.createServer(); server.on('request',function(request,response){ var url = request.url; if(url=='/plain'){ response.setHeader('Content-Type','text/plain; charset=utf-8'); response.end('text/plain表示返回的是普通文本'); }else if(url=='/html'){ response.setHeader('Content-Type','text/html; charset=utf-8'); response.end('<h1>hello html <a href="http://www.baidu.com">点我</a></h1>') } }); server.listen(3000,function(){ console.log('启动服务器'); });
测试如下:
所以我们在请求服务的时候,要加上一个响应类型,告诉服务器给你发送的数据是什么类型
4、利用fs模块配合来处理和响应不同的数据(图片,文本,html)
(1)项目目录结构如图所示:resource中存在各种不同类型的数据
(2)http.js如下
// 1. 结合 fs 发送文件中的数据 // 2. Content-Type // http://tool.oschina.net/commons // 不同的资源对应的 Content-Type 是不一样的 // 图片不需要指定编码 // 一般只为字符数据才指定编码 var http = require('http') var fs = require('fs') var server = http.createServer() server.on('request', function (req, res) { // / index.html var url = req.url if (url === '/') { // 我们要发送的还是在文件中的内容 fs.readFile('./resource/index.html', function (err, data) { if (err) { res.setHeader('Content-Type', 'text/plain; charset=utf-8') res.end('文件读取失败,请稍后重试!') } else { // data 默认是二进制数据,可以通过 .toString 转为咱们能识别的字符串 // res.end() 支持两种数据类型,一种是二进制,一种是字符串 res.setHeader('Content-Type', 'text/html; charset=utf-8') res.end(data) } }) } else if (url === '/xiaoming') { // url:统一资源定位符 // 一个 url 最终其实是要对应到一个资源的 fs.readFile('./resource/ab2.jpg', function (err, data) { if (err) { res.setHeader('Content-Type', 'text/plain; charset=utf-8') res.end('文件读取失败,请稍后重试!') } else { // data 默认是二进制数据,可以通过 .toString 转为咱们能识别的字符串 // res.end() 支持两种数据类型,一种是二进制,一种是字符串 // 图片就不需要指定编码了,因为我们常说的编码一般指的是:字符编码 res.setHeader('Content-Type', 'image/jpeg') res.end(data) } }) } }) server.listen(3000, function () { console.log('Server is running...') })
三、总结
1、文件之间通过require加载,因为有模块作用域,所以不会有污染的问题
2、模块作用域,可以同时加载多个文件,可以避免变量命名冲突问题
3、模块间的通信需要将通信变量或者函数挂在到 exports中
4、核心模块:由Node提供的一个具有特殊名字的模块