一、Node.js是什么
- Node.js不是一门语言不是库不是框架
- Node.js是javascript运行时环境。简单来说就是Node.js可以解析和执行js代码,现在js可以脱离浏览器运行
- 浏览器中的js
- Ecmascript(基本语法,if,var,function)
- DOM
- BOM
- Node 中的 JavaScript
- 没有DOM BOM(不能识别window和document)
- EcmaScript
- Node.js不操作页面,为js提供一些服务器端的操作:文件的读写,网络服务的搭建,网络通信等
- event-driven事件驱动、非阻塞i/o模型、轻量高效
二、Node.js使用
1、文件的操作
终端用node 文件名开打开文件
fs 是 file-system 的简写,就是文件系统的意思,在 Node 中如果想要进行文件操作,就必须引入 fs 这个核心模块 var fs = require(‘fs’)
- 读文件fs.readFile
fs.readFile('./data/a.txt', function (error, data) {
//第一个参数就是要读取的文件路径
// 第二个参数是一个回调函数
if(error){
console.log('有错误')
}else{
console.log(data.toString())
}
}
成功——data 数据,error undefined没有数据
失败—— data undefined没有数据,
- 写文件 fs.writeFile(文件路径,写入的内容,回调函数)
- 读取文件夹的目录 fs.readdir()
2、服务器的操作
- 创建一个 Web 服务器
// 1. 加载 http 核心模块
var http = require('http')
// 2. 使用 http.createServer() 方法创建一个 Web 服务器,返回一个 Server 实例
var server = http.createServer()
// 3.当客户端请求过来,就会自动触发服务器的 request 请求事件,然后执行第二个参数:回调处理函数
server.on('request', function () {
console.log('收到客户端的请求了')
})
// 4. 绑定端口号,启动服务器
server.listen(3000, function () {
console.log('服务器启动成功了,可以通过 http://127.0.0.1:3000/ 来进行访问')
})
- request 请求事件处理函数
server.on('request', function (request, response) {
console.log('收到客户端的请求了,请求路径是:' + request.url)
//request.url是 http://127.0.0.1:3000/ 后边的东西
// response 对象有一个方法:write 可以用来给客户端发送响应数据
// write 可以使用多次,但是最后一定要使用 end 来结束响应,否则客户端会一直等待
response.write('hello')
response.write(' nodejs')
// 告诉客户端,我的话说完了,你可以呈递给用户了
response.end()
})
可以直接一句话 response.end(‘hello nodejs’)。响应内容只能是二进制或字符串
http.createServer(function(request,response){
response.writeHead(200, {"Content-Type": "text/plain"});
response.write("Hello World");
response.end();
}).listen(888);
- 页面重定向
- 状态码设置为 302 临时重定向(301永久重定向)
response.statusCode = 302
- 在响应头中通过 Location 告诉客户端往哪儿重定向
response.setHeader('Location', '/')
- 状态码设置为 302 临时重定向(301永久重定向)
3、核心模块
文件操作的fs模块、http服务构建的http模块、path路径操作模块、os操作系统信息模块等等。使用模块就要先引入var fs = require('fs)
var http = require('http')
4、require
require 是一个方法,它的作用就是用来加载模块的。在 Node 中,模块有两种:- 具名的核心模块,例如 fs、http(fs是动态读取文件信息)
- 用户自己编写的文件模块
相对路径必须加 ./
可以省略后缀名
相对路径中的 ./ 不能省略,否则报错
注意:
- 在 Node 中,没有全局作用域,只有模块作用域
- 外部访问不到内部, 内部也访问不到外部。默认都是封闭的
- 有时候,我们加载文件模块的目的不是为了简简单单的执行里面的代码,更重要是为了使用里面的某个成员
5、http
-
端口号
- ip 地址定位计算机
- 端口号定位具体的应用程序
- 端口号的范围是0-65536之间,一些计算机默认的端口号例如80 最好不要使用
-
Content-Type
- 服务器最好把每次响应的数据是什么内容类型都告诉客户端,而且要正确的告诉
- 不同的资源对应的 Content-Type 是不一样,具体参照:http://tool.oschina.net/commons
- 对于文本类型的数据,最好都加上编码,目的是为了防止中文解析乱码问题
- res.setHeader(‘Content-Type’, ‘text/plain; charset=utf-8’)——普通文本
- res.setHeader(‘Content-Type’, ‘text/html; charset=utf-8’) ——html 格式的字符串
-
通过网络发送文件
- 发送的并不是文件,本质上来讲发送是文件的内容
- 当浏览器收到服务器响应内容之后,就会根据你的 Content-Type 进行对应的解析处理
6、apache目录文件
得到某目录下的文件名和目录名 fs.readdir- 获取文件目录
- 将得到的文件名和目录名替换到 template.html 中
data = data.replace('^_^', content)
- 发送解析替换过后的响应数据res.end(data)
- 打开服务器就可以获取到想要得到的文件名和文件目录
7、模板引擎art-template
可以在浏览器中使用也可以在node中使用- 在浏览器中使用
- 首先安装npm install art-template
- 在浏览器中需要引用 lib/template-web.js 文件
- 模板引擎不关心你的字符串内容,只关心自己能认识的模板标记语法,例如 {{}}
<script type="text/template" id="tpl">
{{ name }}
</script>
<script>
var ret = template('tel',{
name:'jack'
})
</script>
//模板的循环
{{each 数组]}
{{$value}}
{{/each}}
- 在node中使用
- 在需要使用的文件模块中加载 art-template
require('art-template')
- 使用render渲染
- 在需要使用的文件模块中加载 art-template
var ret = template.render(data.toString(), {
name: 'Jack',
})
- 服务端渲染和客户端渲染的区别 (服务端渲染就是在服务端使用模板引擎)
- 客户端渲染不利于 SEO 搜索引擎优化
- 服务端渲染是可以被爬虫抓取到的,客户端异步渲染是很难被爬虫抓取到的
- 所以你会发现真正的网站既不是纯异步也不是纯服务端渲染出来的
- 而是两者结合来做的
- 例如京东的商品列表就采用的是服务端渲染,目的了为了 SEO 搜索引擎优化
- 而它的商品评论列表为了用户体验,而且也不需要 SEO 优化,所以采用是客户端渲染
8、路由模块
var url = require('url')
var obj = url.parse('/pinglun?name=的撒的撒&message=的撒的撒的撒', true)
参数为true的时候可以获取到后面的search值,并将其转为对象格式
query: { name: '的撒的撒', message: '的撒的撒的撒' }
9、导出成员exports 和 module.exports
- 每个模块中都有一个 module 对象
- module 对象中有一个 exports 对象
- 我们可以把需要导出的成员都挂载到 module.exports 接口对象中
- 也就是:
moudle.exports.xxx = xxx
的方式 - 但是每次都
moudle.exports.xxx = xxx
很麻烦,点儿的太多了 - 所以 Node 为了你方便,同时在每一个模块中都提供了一个成员叫:
exports
exports === module.exports
结果为true
- 所以对于:
moudle.exports.xxx = xxx
的方式 完全可以:expots.xxx = xxx
- 当一个模块需要导出单个成员的时候,这个时候必须使用:
module.exports = xxx
的方式 - 不要使用
exports = xxx
不管用 - 因为每个模块最终向外
return
的是module.exports
- 而
exports
只是module.exports
的一个引用 - 所以即便你为
exports = xx
重新赋值,也不会影响module.exports
- 但是有一种赋值方式比较特殊:
exports = module.exports
这个用来重新建立引用关系的 - 总结:最后 return 的是 module.exports,不是 exports,所以你给 exports 重新赋值不管用。 多个成员可以
moudle.exports.xxx = xxx
或expots.xxx = xxx
,单个成员的时候只能module.exports = xxx
10、require优先缓存加载
a加载过b,当再次require时不会重新加载。可以拿到其中的接口对象,但是不会重复执行里边的代码。目的:避免重复加载,提高模块加载效率11、require模块查找机制
- 优先从缓存加载
- 核心模块
- 路径形式的文件模块 ./ …/
- 第三方模块(凡是第三方模块都必须通过 npm 来下载)
- 既不是核心模块、也不是路径形式的模块
- 先找到当前文件所处目录中的 node_modules 目录
- node_modules/art-template/
- node_modules/art-template/package.json
- node_modules/art-template/package.json 里main属性中就记录了 art-template 的入口模块
- package.json 文件不存在或者 main 指定的入口模块是也没有。node 会自动找该目录下的 index.js
- 如果以上所有任何一个条件都不成立,则会进入上一级目录中的 node_modules 目录查找
- 一个项目有且仅有一个 node_modules 而且是存放到项目的根目录。最后找不到就会报错
三、nodemon自动重启模块
- 全局安装
npm install -g nodemon
- 本地安装
npm i nodemon -D
- 启动应用
nodemon [your node app]