# nodejs
## nodejs是什么
- 是运行在服务器上的JavaScript
- 是一个javascript运行时环境,不是语言 不是框架 是一个环境 一个平台
##nodejs的特性
* 单线程
* 非阻塞IO
* 基于事件模型
* 服务端的javascript
## nodejs中的javascript
###ECMAScript
+ 也就是js的基本语法 node中同样适用
+ `没有bom 和 dom 的api`
###模块系统
+ 一些特性 :
* 在 Node 中没有全局作用域的概念
* 在 Node 中,只能通过 require 方法来加载执行多个 JavaScript 脚本文件
* require 加载只能是执行其中的代码,文件与文件之间由于是模块作用域,所以不会有污染的问题
- 模块完全是封闭的
- 外部无法访问内部
- 内部也无法访问外部
- 模块作用域固然带来了一些好处,可以加载执行多个文件,可以完全避免变量命名冲突污染的问题
* 但是某些情况下,模块与模块是需要进行通信的
* 在每个模块中,都提供了一个对象:`exports`
* 该对象默认是一个空对象
* 你要做的就是把需要被外部访问使用的成员手动的挂载到 `exports` 接口对象中
* 然后谁来 `require` 这个模块,谁就可以得到模块内部的 `exports` 接口对象
####核心模块
* 定义
* 核心模块是由 Node 提供的一个个的具名的模块,它们都有自己特殊的名称标识,例如
- fs 文件操作模块
* http 网络服务构建模块
* os 操作系统信息模块
* path 路径处理模块
* 。。。。
* 所有核心模块在使用的时候都必须手动的先使用 `require` 方法来加载,然后才可以使用,例如:
- `var fs = require('fs')`
## 系统核心模块
### http模块(http)(用于搭建服务器)
> 引入 模块 `var http = require('http')`
#### 搭建服务器
**注意 :一次响应对应一次请求**
```javascript
//引入http模块
var http = require('http')
//创建server服务
var server = http.createServer()
//监听请求
server.on('request',function (req,res) {
console.log(req.url)
//设置响应头中的contenttype为 utf-8 防止乱码
res.setHeader('Content-Type', 'text/plain; charset=utf-8')
//设置响应体 并 结束本次响应
res.end('天干物燥 小心火烛')
})
//开启服务
server.listen('3000',function () {
console.log('服务已经启动了~');
})
```
- 创建服务器 回调函数中的 req res 的 一些属性和方法
* 属性: req.url 拿到的是请求的路径
* 方法: res.setHeader('Content-Type', 'text/plain; charset=utf-8')
设置响应头中的contenttype为 utf-8 防止乱码
* 方法: res.write() 可以用来给客户端发送响应数据
* 方法: res.end()
不传参 :告诉客户端,我的话说完了,你可以呈递给用户了
传参('字符串') : 会将响应结束 并把字符串响应给客户端
* 属性: req.socket.remoteAddress 用于获取请求的 客户端IP地址
* 属性: req.socket.remotePort 用于获取请求的 客户端端口号
* 属性: res.statuscode 设置状态码 301 表示永久重定向 302 表示临时重定向
* 通常和res.setHeader('Location','/') 搭配使用 用于重定向 页面
### 文件系统模块(fs)
> 想用着个模块这得 先引入这个 模块 `var fs = require('fs')`
#### 一些文件操作相关api
- 读文件 操作 `fs.readFile()`
``` javascript
fs.readFile('文件名',function(err,data){
//如果出错 直接return 响应体信息
//res 是创建服务器时的 响应体参数
if (err) return res.end('出错啦!!!')
res.end(data)
})
//这个方法可以传入第二个参数 是可选的 传了 就表示 返回的结果是utf-8 的字符
fs.readFile('文件名','utf8',function(err,data){
//如果出错 直接return 响应体信息
//res 是创建服务器时的 响应体参数
if (err) return res.end('出错啦!!!')
res.end(data)
})
```
- 写文件操作 `fs.writeFile`()
```javascript
fs.writeFile('./data/你好.md', '大家好,给大家介绍一下,我是Node.js', function (error) {
// console.log('文件写入成功')
// console.log(error)
if (error) {
console.log('写入失败')
} else {
console.log('写入成功了')
}
})
```
- 读取文件目录 `fs.readdir()`
```javascript
fs.readdir('E:/wsTest', function (err, files) {
if (err) {
return console.log('目录不存在')
}
console.log(files)
//这个返回的files 是一个数组
// [ '.idea', '.vscode', '24', 'node_modules', 'package-lock.json' ]
})
```
### URL模块(url)
> 引入模块 一般用于解析 `var url = require('url')`
#### api
- url.parse('www.baidu.com?name=xxx&pwd=xxx',true) 返回一个 url对象
+ 如果有传第二个参数 true 那么其中的query 为装成对象 不传则是 name=xxx&pwd=xxx
```javascript
Url {
protocol: null,
slashes: null,
auth: null,
host: null,
port: null,
hostname: null,
hash: null,
search: '?name=xxx&pwd=xxx',
query: { name: 'xxx', pwd: 'xxx' },
pathname: 'www.baidu.com',
path: 'www.baidu.com?name=xxx&pwd=xxx',
href: 'www.baidu.com?name=xxx&pwd=xxx'
}
```
## npm
新版本node.js安装的时候会自动安上npm
- 是什么 ? `NodeJs中的包管理工具 ` [ `是一个网站`](https://www.baidu.com/link?url=m ... e5a000000065ba69444) 是一个命令行工具
- 可以用来干什么? 用来管理nodejs的包 下载安装第三方模块 也可以直接上传模块至网站
---
#### 怎么用? 一些npm 常用命令
+ npm init 在当前目录生成package.json文件
+ npm init -y 可以跳过向导 直接在当前目录生成package.json文件
+ npm install 讲当前目录的package.json文件中的 依赖项全部下载安装
+ npm install 包名 下载这个包
+ npm install 包名 --save 下载这个包 并 在package.json中 添加信息至 依赖项中(dependencies )
+ npm install 包名@版本号 下载这个包的这个版本
+ npm uninstall 包名 移除这个包
+ npm uninstall 包名 --save 移除这个包 并在package.json中的依赖也移除
+ npm help 查看使用帮助
+ npm 命令(install) --help 查看此命令的帮助 忘记简写可以这么用
+ npm -i npm -g 可以升级npm
**所有install 可以简写成 i 所有 uninstall可以简写成 un -**
**--save -S -- global -g**
---
#### npm被墙问题
- 因为npm服务器架设在国外 所以访问速度慢 怎么解决?
- 国内淘宝开发团队 搞了一个npm的镜像 cnpm
- 在npm中 输入命令 安装cnpm `npm install cnpm -g` -g代表全局安装
- 然后使用的时候 就得用 cnpm去下载安装第三方包(模块)
- 不想安装cnpm怎么办? 改变npm的 资源库指向淘宝的镜像资源库(每10分钟同步一次) (个人理解)
- 写进配置文件中 `npm config set registry htts://registry.npm.taobao.org`
- 配置完之后 可以输入命令 `npm config list `查看一下是否配置成功
## 第三方模块
**任何第三方模块都需要先用 npm 下载安装后 才能引入**
### art-template(art-template)
> 同样的 引入第三方模块也是先加载这个模块 `var template = require('art-template')`
---
#### 在nodejs中使用art-template 和 相关api
```javascript
//准备好 模板文件 tpl.html
fs.readFile('./tpl.html', function (err, data) {
if (err) {
return console.log('读取文件失败了')
}
// 默认读取到的 data 是二进制数据
// 而模板引擎的 render 方法需要接收的是字符串
// 所以我们在这里需要把 data 二进制数据转为 字符串 才可以给模板引擎使用
var ret = template.render(data.toString(), {
name: 'Jack',
age: 18,
province: '北京市',
hobbies: [
'写代码',
'唱歌',
'打游戏'
],
title: '个人信息'
})
console.log(ret)
})
```
---
### nodemon(让代码修改完直接重启)
> 作用就是让代码修改完可以自动重启
>
> 这是一个第三方命令行工具 他是基于nodejs 开发的 要独立安装
1. *安装*
```shell
npm i nodemon -g //在全局安装
nodemon --version //可以看nodemon的版本 就可以判断有没有安装成功
```
2. 使用
```shell
//在启动时服务时 直接用nodemon 来启动即可
node app.js 换成 nodemon app.js 就可以了
nodemon会监视文件的变化 当文件变化的时候 会自动重启服务器
```
---
### MD5 加密(blueimp-md5)
## [**Express(express)!!!!!!!!!!!!!!!!!!!!** ](http://www.expressjs.com.cn/)
---
- express是一个 基于 node.js平台 `快速的` `开放的` `极简的` web开发框架
- 提供了一套强大的api
---
### 使用express的小demo
```javascript
//0. 安装
// 1. 引包
var express = require('express')
// 2. 创建你服务器应用程序
// 也就是原来的 http.createServer
var app = express()
// 在 Express 中开放资源就是一个 API 的事儿
// 公开指定目录
// 只要这样做了,你就可以直接通过 /public/xx 的方式访问 public 目录中的所有资源了
app.use('/public/', express.static('./public/'))
app.use('/static/', express.static('./static/'))
app.use('/node_modules/', express.static('./node_modules/'))
// 模板引擎,在 Express 也是一个 API 的事儿
// 得到路径
// 一个一个的判断
// 以前的代码很丑
app.get('/about', function (req, res) {
// 在 Express 中可以直接 req.query 来获取查询字符串参数
console.log(req.query)
res.send('你好,我是 Express!')
})
app.get('/pinglun', function (req, res) {
// req.query
// 在 Express 中使用模板引擎有更好的方式:res.render('文件名, {模板对象})
// 可以自己尝试去看 art-template 官方文档:如何让 art-template 结合 Express 来使用
})
// 当服务器收到 get 请求 / 的时候,执行回调处理函数
//第一个参数时请求路径 不包括参数的
app.get('/', function (req, res) {
// `` 是模板字符串 内容支持换行 和 解析变量 不过变量要${变量名} 使用 es6的语法
res.send(`
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Document</title>
</head>
<body>
<h1>hello Express!你好</h1>
</body>
</html>
`)
})
// 相当于 server.listen
app.listen(3000, function () {
console.log('app is running at port 3000.')
})
```
- req.path 为请求的路径
- req.query 直接 req.query 来获取查询字符串参数( `get请求` ) 返回的是一个对象
- res.send('字符串') 发送响应体
- res.redirect('') 用来重定向url
---
### express中获取get请求参数
- req.query 直接 req.query 来获取查询字符串参数( `get请求` ) 返回的是一个对象
---
### express中获取post请求参数
> 一个第三方模块 包
**需要使用到[中间件](http://www.expressjs.com.cn/resources/middleware.html) [body-parser](http://www.expressjs.com.cn/en/r ... re/body-parser.html) **
1. *安装*
```shell
npm i body-parser -s
```
2. *配置*
```javascript
var express = require('express')
var bodyParser = require('body-parser')
var app = express()
// 配置body-parser
// 添加这个配置 会让req 的属性多出一个body 里面存放的就是 post请求的数据 是一个对象
// 直接req.body 获取
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))
// parse application/json
app.use(bodyParser.json())
```
3. *使用*
```javascript
app.use(function (req, res) {
res.setHeader('Content-Type', 'text/plain')
res.write('you posted:\n')
res.end(JSON.stringify(req.body, null, 2))
})
//以上都是官网示例代码
```
---
### express中使用 [art-template](http://aui.github.io/art-template/zh-cn/)
> express中使用art- template 首先要安装 art-template 和 express-art-template
>
> 要有相关配置才能正常使用 详细如下
>
> 核心方法 res.render('index.html',{模板里写的对象:要替换的对象})
1. *安装*
```shell
npm i art-template -s //安装art-template 安装这个是因为 下面那个还是依赖的这个
npm i express-art-template -s //安装 express-art- template
```
2. *配置*
```javascript
var express = require('express');
var app = express();
//配置art-template
//第一个参数 是 解析这种扩展名的 就使用 art-template模板引擎
app.engine('art', require('express-art-template'));
//如果想改变 render 第一个参数 页面的默认所在目录views 用下面这条代码改
app.set('views',你想要改的路径);
```
3. *使用*
```javascript
app.get('/', function (req, res) {
//不配置 express-art-template 是没有render这个方法的
res.render('index.art', {
user: {
name: 'aui',
tags: ['art', 'template', 'nodejs']
}
});
});
```
---
### express中的静态资源服务
**使用**
> ```javascript
> var express = require('express')
> var app = express()
> //公开public目录 和 node_moudle目录
> app.use('/public/',express.static('./public/'))
> app.use('/node_modules/', express.static('./node_modules/'))
>
> ```
- 小注意的点
+ 上面代码块中 app.use()的第一个参数 才是 你访问的时候具体写的路径
+ 推荐写成和要公开目录一样的名字 一目了然
+ 第二个参数就是要公开的目录路径
+ 如果只写一个参数的话 那就是可以省略/public/(示范而已)不写
---
### express中路由
> 就是监听 url 又可以分为get post ..请求来分别监听
- 将原来的写在入口模块(app.js)中的 `app.get()app.post()`单独拿出来 作为一个路由模块(router.js)单独存在
- 因为入口模块(`app.js`)职责主要是
- 创建服务
- 做一些服务相关配置
- 模板引擎啊(template....)
- body-parser(解析表单 post请求)
- 提供静态资源服务啊(app.use('/public/',express.static('./public/'))
- .......
- 挂载 路由
- 监听端口 并启动服务
- 而路由模块职责(`router.js`)主要是
- 处理路由
- 根据不同的请求方式(get/post) 请求路径设置相应的请求函数(一般都是封装起来的)
- 划分模块还是为了提高 开发效率 增强代码的可维护性
---
### express中使用session
## require 相关
### require 的一些小说法
- require 是一个方法
- 它的作用就是用来加载模块的
- require 方法有两个作用:
1. 加载文件模块并执行里面的代码
2. 拿到被加载文件模块导出的接口对象
在每个文件模块中都提供了一个对象:`exports`
` exports` 默认是一个空对象
你要做的就是把所有需要被外部访问的成员挂载到这个 `exports` 对象中
- 在 Node 中,模块有三种:
+ 具名的核心模块,例如 fs、http
+ 用户自己编写的文件模块
* 相对路径必须加 ./
* 可以省略后缀名
* 相对路径中的 ./ 不能省略,否则报错
-在 Node 中,没有全局作用域,只有模块作用域
+ 外部访问不到内部
+ 内部也访问不到外部
+ 默认都是封闭的
- 既然是模块作用域,那如何让模块与模块之间进行通信
+ 有时候,我们加载文件模块的目的不是为了简简单单的执行里面的代码,更重要是为了使用里面的某个成员
---
### exports 和 moudle.exports
- 模块中导出多个成员和导出单个成员
- exports 和 module.exports 的区别
+ 每个模块中都有一个 module 对象
+ module 对象中有一个 exports 对象
+ 我们可以把需要导出的成员都挂载到 module.exports 接口对象中
+ 也就是:`moudle.exports.xxx = xxx` 的方式
+ 但是每次都 `moudle.exports.xxx = xxx` 很麻烦,点儿的太多了
+ 所以 Node 为了你方便,同时在每一个模块中都提供了一个成员叫:`exports`
+ `exports === module.exports` 结果为 `true`s
+ 所以对于:`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 的是moule.exports **
### require加载规则
#### 优先从缓存加载
- 比如在a.js中 引入b.js 再在b.js中引入 c.js 这时 再在a.js中引入c.js 那么这时系统不会再加载 c.js 这里 是引入时为了拿到 c.js中`exports`挂载的对象
#### 自定义模块加载规则
....
#### 系统模块加载规则
...
#### 第三方模块加载规则
...
## 客户端渲染 和 服务端渲染
### 客户端渲染
![](G:\web前端资料\14Nodejs教程精讲(7天+5天赠送)\nodejs资料(7天)\02\code\客户端渲染.png)
### 服务端渲染
![](G:\web前端资料\14Nodejs教程精讲(7天+5天赠送)\nodejs资料(7天)\02\code\服务端渲染.png)
+ 说白了就是在服务端使用模板引擎
+ 模板引擎最早诞生于服务端,后来才发展到了前端
### 服务端渲染和客户端渲染区别
- 服务端渲染和客户端渲染的区别
+ 客户端渲染不利于 SEO 搜索引擎优化
+ 服务端渲染是可以被爬虫抓取到的,客户端异步渲染是很难被爬虫抓取到的
+ 所以你会发现真正的网站既不是纯异步也不是纯服务端渲染出来的
+ 而是两者结合来做的
+ 例如京东的商品列表就采用的是服务端渲染,目的了为了 SEO 搜索引擎优化
+ 而它的商品评论列表为了用户体验,而且也不需要 SEO 优化,所以采用是客户端渲染
---
## MongoDB
> [参考教程](http://www.runoob.com/mongodb/mongodb-tutorial.html)
## 单线程
- 缺点
- 无法利用多核cpu
- 一个用户造成线程崩溃,真个服务器都会崩溃
- 大量的计算占用cpu导致无法继续调用异步IO
- 优点
- 操作系统完全不在有线程创建,销毁的时间开销
- 减少的内存的开销,操作系统饿内存换页
- 不再向多线程编程一样处处在意状态的同步问题
- 一个8G的内存服务器,可以同时处理超过4w用户的连接
[**摘自**](https://blog.csdn.net/lmj170/article/details/79482310)
|
|