node.js

node.js特性:

  1. 事件驱动
  2. 非阻塞IO模型(异步)

1. 读取文件

fs 是 file-system 的缩写,在 node 中如果想要进行文件操作,就必须引入 fs 这个核心模块。在 fs 这个核心模块中,就提供了所有的文件操作相关的 API,例如: fs.readFile 就是用来读取文件的。

  1. node 中没有DOM和BOM
  2. node 中的JavaScript具有操作位文件的能力(浏览器中的JavaScript没有操作文件的能力)

方法:

  1. 使用 require 方法加载 fs 核心模块
  2. 读取文件
    第一个参数:文件路径
    第二个参数:回调函数

文件操作中的相对路径可以省略 ./

var fs = require('fs');
fs.readFile('file.txt', function(error, data) {
	if(error) {
		console.log('读取文件失败');
	} else {
		console.log(data.toString());
	}
})
var fs = require('fs');
fs.readFile('file.txt', 'utf8', function(error, data) {

})

readFile 的第二个参数是可选的,传入 utf8 就是告诉它把读取到的文件直接按 utf8 编码,转成我们能认识的字符,除了这样来转换之外,也可以通过 data.toString() 的方式

回调函数成功
errornull
data数据(默认为二进制数据)
回调函数失败
error错误对象
dataundefined

2. 写文件

方法:

  1. 使用 require 方法加载 fs 核心模块
  2. 写文件
    第一个参数:文件路径
    第二个参数:要写入的文件内容
    第三个参数:回调函数
var fs = require('fs');
fs.writeFile('write.txt','你好,node',function(error){
	if(error) {
		console.log('文件写入失败');
	} else {
		console.log('文件写入成功');
	}
})
回调函数成功(文件写入成功)
errornull
回调函数失败(文件写入失败)
error错误对象

上述两个文件操作的 API 都是异步的

3. 简单的http服务

在 node 中专门提供了一个核心模块:http,帮助编写服务器。
方法:

  • 加载 http 核心模块
  • 使用 http.createServer() 方法创建一个 web 服务器,返回一个 Server 实例
  • 注册 request 请求事件,当客户端请求过来,就会自动触发服务器的 request 请求事件,然后执行第二个参数:回调处理函数。request 请求事件处理函数,需要接收两个参数:
  • request 请求对象:请求对象可以用来获取客户端的一些请求信息,例如请求路径
    例如:
    http://127.0.0.1:3000/ 请求路径为:/
    http://127.0.0.1:3000/a 请求路径为:/a
  • response 响应对象:响应对象可以用来给客户端发送响应信息
    response 对象有一个方法:write 可以用来给客户端发送响应数据,write 可以使用多次,但是最后一定要使用 end 来结束响应,否则客户端会一直等待

res.end()支持两种数据类型,一种是二进制,一种是字符串

  • 绑定端口号,启动服务器
var http = require('http');
var server = http.createServer();
server.on('request', function(request, response) {
	// console.log('收到服务器请求,请求路径是' + request.url)
	var url = request.url
	if (url === '/') {
		// response.write('index page')
		// response.end()
		response.end('index page')
	} else if (url === '/login') {
		response.end('login page')
	} else {
		response.end('404 Not Found.')
	}
});
server.listen(3000, function() {
	console.log('服务器启动成功了,可以通过 http://127.0.0.1:3000/ 来进行访问')
});

4. 简单的模块化

  1. require用来加载模块,例如:
    • 具名的核心模块:fshttp
    • 用户自己编写的文件模块(相对路径必须./,可以省略后缀名)
  2. 在 node 中,没有全局作用域,只有模块作用域
  3. require方法有两个作用:
    • 加载文件模块,并执行里面的代码
    • 拿到被加载文件模块导出的接口对象

在每个文件模块中都提供了一个对象:exportsexports默认是一个空对象,把所有需要被外部访问的成员挂载到这个exports对象中

// a.js
var bExports = require('./b')
console.log(bExports.add(10, 30))

// b.js
exports.add = function(x, y) {
	return x + y
}

如果一个模块需要直接导出某个(单个)成员,而非挂载的方式,那这个时候必须使用下面这种方式

module.exports = 'hello'

5. Content-Type

HTTP Content-Type 对照表

var http = require('http');
var fs = require('fs')
var server = http.createServer();
server.on('request', function(request, response) {
	var url = request.url;
	if (url === '/') {
		// text/plain 普通文本
		fs.readFile('./resource/index.html', function(error, data) {
			if (error) {
				response.setHeader('Content-Type', 'text/plain;charset=utf-8')
				response.end('文件读取失败,请稍后重试!')
			} else {
				response.setHeader('Content-Type', 'text/html;charset=utf-8')
				response.end(data)
			}
		})
	} else if (url === '/image') {
		fs.readFile('./resource/image.jpg', function(error, data) {
			if (error) {
				response.setHeader('Content-Type', 'text/plain;charset=utf-8')
				response.end('文件读取失败,请稍后重试!')
			} else {
				response.setHeader('Content-Type', 'image/jpeg')
				response.end(data)
			}
		})
	}
});
server.listen(3000, function() {
	console.log('服务器启动成功了,可以通过 http://127.0.0.1:3000/ 来进行访问')
});

6. 使用模板引擎

art-template 可以在浏览器中使用,也可以在 node 中使用

  • 安装
    文档: https://aui.github.io/art-template/
    npm install art-template (该命令在哪儿执行就会把包下载到哪儿,默认会下载到 node_modules 目录中,该目录不要改也不支持该)
  • 在需要使用的文件模块中加载 art-template,只需要使用 require 方法加载就可以了:var template = require(‘art-template’),参数中的 art-template 就是你下载的包的名字,也就是 (npm) install 的名字是什么,则你 require 中的就是什么
  • 查文档,使用模板引擎的 API

template.render('模板字符串',替换对象)

<!-- template.html -->
<!DOCTYPE html>
<html lang="zh">
	<head>
		<meta charset="UTF-8">
		<title>node</title>
	</head>
	<body>
		<p>大家好,我叫 {{ name }}</p>
		<p>我今年 {{ age }} 岁了</p>
		<p>我来自 {{ province }}</p>
		<p>我喜欢 {{ each hobbies }} {{ $value }} {{/each}}</p>
	</body>
</html>
// template.js
var template = require('art-template');
var fs = require('fs');
fs.readFile('./template.html', function(error, data) {
	if (error) {
		return console.log('读取文件失败')
	}
	// data 默认是二进制数据,模板引擎的 render 方法需要接收的是字符串
	// template.render('模板字符串',替换对象)
	var result = template.render(data.toString(), {
		name: 'Jack',
		age: 18,
		province: '山东',
		hobbies: [
			'代码',
			'听歌',
			'电影'
		]
	});
	console.log(result);
})

7. 静态资源

  • 浏览器收到 HTML 响应内容后,就要开始从上到下依次解析,当在解析的过程中,如果发现:linkscriptimgiframevideoaudio,等带有 src 或者 href (link中) 属性标签(具有外链的资源)的时候,浏览器会自动对这些资源发起新的请求。
  • 我们为了方便的统一处理这些静态资源,所以我们约定把所有的静态资源都存放在 public 目录中

indexOf()方法可返回某个指定的字符串值在字符串中首次出现的位置。

  • 注意:在服务端中,文件中的路径就不要去写相对路径了,因为这个时候所有的资源都是通过 url 标识来获取的,我的服务器开放了 /public/ 目录,所以这里的路径都写成:/public/xxx。/ 在这里就是 url 根路径的意思,浏览器在真正发请求的时候最终会把 http://127.0.0.1:3000 拼上。即把所有的路径都想象成 url 地址。

8. 重定向

让客户端重定向:

  • 状态码设置为 302 (临时重定向)
    response.statusCode = 302
  1. 301 永久重定向,浏览器会记忆
  2. 302 临时重定向,浏览器不记忆
  • 在响应头中通过 Location 告诉客户端往哪儿重定向
    response.setHeader('Location','/')

如果客户端发现收到服务器的响应状态码是 302 就会自动去响应头中找 Location,然后对该地址发起新的请求,所以你就能看到客户端自动跳转了

9. 路径解析

使用 url.parse 方法将路径解析为一个方便操作的对象,第二个参数为 true 表示直接将查询字符串转为一个对象,通过 query 属性访问

var url = require('url')
url.parse(request.url, true)

10. require 方法加载规则

  • 优先从缓存加载
  • 判断模块标识:require('模块标识')
    • 核心模块
      • 模块名
    • 第三方模块
      • 模块名
    • 自己写的模块
      • 路径

11. package.json 包说明文件

建议每一个项目都要有一个package.json文件(包描述文件)。
方法:

  1. package.json文件通过npm init的方式来自动初始化出来。
  2. 安装第三方包的时候加上--save(位置可在报名前也可在包名后),可以保存依赖项信息。
npm install jquery --save

若第三方包被误删,可通过npm install指令自动把package.json中的dependencies中的所有依赖项都下载下来。

11.1 package-lock.json

npm 5 以前没有 package-lock.json 这个文件,当你安装包的时候,npm 都会自动生成或者更新这个文件。

  • npm 5 以后的版本安装包不需要加 --save 参数,它会自动保存依赖信息。
  • 当你安装包的时候,会自动创建或者是更新 package-lock.json 这个文件
  • package-lock.json 这个文件会自动保存 node_modules 中所有包的信息(版本、下载地址),这样的话如果误删,重新 npm install 的时候速度就会得到提升。
  • package-lock.json 中的 lock 称之为锁,是用来锁定第三方包的版本的。

12. npm

node package manager

npm --version: 查看 npm 版本
npm install --global npm :升级 npm

常用命令:

  • npm init:生成 package.json 文件
  • npm init --yes:跳过向导,快速生成 package.json 文件
    • 简写:npm init -y
  • npm install:一次性把dependencies选项中的依赖项全部安装
    • 简写:npm i
  • npm install 包名:只下载
    • 简写:npm i 包名
  • npm install --save 包名:下载并保存依赖项(package.json 文件中的dependencies
    • 简写:npm i -S 包名
  • npm uninstall 包名:只删除,如果有依赖项会依然保存
    • 简写:npm un 包名
  • npm uninstall --save 包名:删除的同时也会依赖信息也去除
    • 简写:npm un -S 包名
  • npm help:查看使用帮助
  • npm 命令 --help:查看指定命令的使用帮助,例如:npm uninstall --help
  • npm install --save bootstrap@3.3.7:安装指定版本的包

12.1 解决 npm 被墙问题

npm 存储包文件的服务器在国外,有时候会被墙,速度很慢。
淘宝 NPM 镜像:http://npm.taobao.org/
方法:

  1. 安装淘宝的 cnpm:npm install --global cnpm
  2. 接下来安装包的时候把之前的 npm 替换成 cnpm

不安装 cnpm 使用淘宝的服务器来下载包的方法:
npm install 包名 --registry=https://registry.npm.taobao.org
但是每次这样做很麻烦,所以我们可以把这个选项加入配置文件中:
npm config set registry https://registry.npm.taobao.org
只要经过了上面命令的配置,则以后所有的 npm install 都会默认通过淘宝的服务器来下载。

查看上面的 npm 配置信息方法:
npm config list

13. express

http://expressjs.com/
安装:

npm install --save express

使用:

// 1. 引包
var express = require('express')

// 2. 创建你的服务器应用程序,也就是原来的 http.createServer
var app = express()

// 公开指定目录
// 只要这样做了,就可以直接通过 /public/xx 的方式访问 public 目录中的所有资源了,例如:http://127.0.0.1:3000/public/js/main.js
app.use('/public/',express.static('./public/'))

// 当服务器收到 get 请求 / 的时候,执行回调处理函数
app.get('/',function(req,res){
	res.send('hello express')
})

// 当服务器收到 get 请求 /about 的时候,执行回调处理函数
app.get('/about',function(req,res){
	// 在 express 中可以直接通过 req.query 来获取查询字符串参数,(get 方法)
	console.log(req.query)
	res.send('你好,我是 express')
})

// 相当于server.listen
app.listen(3000,function(){
	console.log('app is running')
})

req.query 只能拿 get 请求参数

13.1 基本路由

  1. get:
app.get('/',function(req,res){
	res.send('hello express')
})
  1. post:
app.post('/',function(req,res){
	res.send('hello express')
})

13.2 静态资源服务

当以 /public/ 开头的时候,去 ./public/ 目录中找对应资源,例如:http://127.0.0.1:3000/public/js/main.js

app.use('/public/',express.static('./public/'))

当省略第一个参数时,则可以通过省略 /public 的方式来访问,例如:http://127.0.0.1:3000/js/main.js

app.use(express.static('./public/'))

13.3 配置使用 art-template 模板引擎

安装:

npm install --save art-template
npm install --save express-art-template

配置:

app.engine('html', require('express-art-template'));

使用:

var express = require('express')

var app = express()

app.use('/public/',express.static('./public/'))

app.engine('html', require('express-art-template'))

app.get('/',function(req,res){
	res.render('404.html')
})

app.get('/admin',function(req,res){
	res.render('admin/index.html',{
		title:'管理系统'
	})
})

app.get('/post',function(req,res){
	res.send('/post html')
})

app.listen(3000,function(){
	console.log('running ...')
})
  1. 配置使用 art-template 模板引擎,第一个参数,表示当渲染以 .html 结尾的文件的时候,使用 art-template 模板引擎,express-art-template 是专门用来在 express 中把 art-template 整合到 express中的,虽然这里不需要加载 art-template,但是也必须安装,原因在于 express-art-template 依赖了 art-template
  2. express 为 response 响应对象提供了一个方法:renderrender 方法默认是不可以使用的,但是如果配置了模板引擎就可以使用了:
    res.render('HTML模板名',{模板数据})
    第一个参数不能写路径,默认会去项目中的 views 目录查找该模板文件,也就是说,express 有一个约定:开发人员把所有的视图文件都放到 views 目录中
  3. 如果想要修改默认的 views 目录,则可以:
    app.set('views',render函数的默认路径)

13.4 在 express 中获取表单 get 请求参数

req.query

13.5 在 express 中获取表单 post 请求体数据

body-parser 文档链接
在 express 中没有内置获取表单 post 请求体的 API,这里我们需要使用一个第三方包:body-parser

  1. 安装:
npm install --save body-parser
  1. 配置:
var express = require('express')
// 引包
var bodyParser = require('body-parser')

var app = express()

// 配置 body-parser,只要加入这个配置,则在 req 请求对象上会多出来一个属性:body,也就是说你就可以直接通过 req.body 来获取表单请求数据了
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))

// parse application/json
app.use(bodyParser.json())
  1. 使用:
app.use(function (req, res) {
  res.setHeader('Content-Type', 'text/plain')
  res.write('you posted:\n')
  res.end(JSON.stringify(req.body, null, 2))
})

14. MongoDB

MongoDB 菜鸟教程
MongoDB 是一个基于分布式文件存储的数据库,是一个介于关系数据库和非关系数据库之间的产品。

  1. 安装:
    MongoDB 官网链接
    安装完毕后需配置环境变量:将 C:\Program Files\MongoDB\Server\4.2\bin添加到环境变量的 Path 中。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  2. 检查安装结果:
    在 cmd 中输入命令:mongod --version

14.1 启动和关闭数据库

启动:
打开 cmd,输入:

mongod

MongoDB 默认使用 mongod 命令所处盘根目录下的 /data/db 作为自己的存储目录,所以在第一次执行前先自己手动创建一个 /data/db

修改默认存储目录:

mongod --dbpath=数据存储目录路径

每次启动都需要输入此命令

关闭:
Ctrl + C

14.2 连接和退出数据库

连接:
打开控制台,输入:

mongo

退出:

exit

14.3 基本命令

控制台 cmd 命令:

  • show dbs:查看显示所有数据库
  • db:查看当前操作的数据库
  • use 数据库名称:切换到指定的数据库(如果没有会新建)
  • show collections:显示当前数据库中的集合(类似关系数据库中的表)
  • db.cats.find():对于当前数据库中的 cats 集合进行数据查找(由于没有条件,会列出所有数据)

14.4 在 Node 中操作 MongoDB 数据库

14.4.1 使用官方的 mongodb 包来操作

官方 mongodb 包链接(npm)
官方 mongodb 包链接(GitHub)

14.4.2 使用第三方 mongoose 来操作 MongoDB 数据库

mongoose 官网链接
官方指南
官方 API 文档
第三方包 mongoose 基于 MongoDB 官方的 mongodb 包再做了一次封装。
安装:

npm install mongoose --save

起步:

const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:27017/test', {useNewUrlParser: true});

const Cat = mongoose.model('Cat', { name: String });

const kitty = new Cat({ name: 'Zildjian' });
kitty.save().then(() => console.log('meow'));

14.4.3 增删改查

完整官方指南:

var mongoose = require('mongoose')

// 架构
var Schema = mongoose.Schema

// 1. 连接数据库,指定连接的数据库不需要存在,当你插入第一条数据之后就会自动被创建出来
mongoose.connect('mongodb://localhost/itcast',{useNewUrlParser: true})

// 2. 设计集合结构(表结构)
// 字段名称就是表结构中的属性名称
var userSchema = new Schema({
	username: {
		type: String,
		// 必须有,不能为空
		required: true
	},
	password: {
		type: String,
		required: true
	},
	email: {
		type: String
	}
})

// 3. 将文档结构发布为模型
// mongoose.model 方法就是用来将一个架构发布为 model
// 第一个参数:传入一个大写名词单数字符串用来表示数据库名称,mongoose 会自动将大写名词的字符串生成小写复数的集合名称,例如这里的 User 最终会变成 users 集合名称
// 第二个参数:架构 Schema
// 返回值:模型构造函数
var User = mongoose.model('User', userSchema)
  1. 增加数据:
// 4. 对 users 集合中的数据进行增删改查
var admin = new User({
	username: '张三',
	password: '123456',
	email: 'admin@admin.com'
})

admin.save(function(err, ret) {
	if (err) {
		console.log('保存失败')
	} else {
		console.log('保存成功')
		console.log(ret)
	}
})
  1. 查询数据:

2.1 查询所有数据:

User.find(function(err, ret) {
	if (err) {
		console.log('查询失败')
	} else {
		console.log(ret)
	}
})

2.2. 按条件查询,得到一个数组:

User.find({
	// 查询条件
	username: '张三'
}, function(err, ret) {
	if (err) {
		console.log('查询失败')
	} else {
		console.log(ret)
	}
})

2.3 按条件查询,查询匹配的第一个,得到一个对象:

User.findOne({
	// 查询条件
	username: '张三',
	password: '123456'
}, function(err, ret) {
	if (err) {
		console.log('查询失败')
	} else {
		console.log(ret)
	}
})
  1. 删除数据:

3.1 根据条件删除所有:

User.remove({
	// 删除条件
	username: '张三'
}, function(err, ret) {
	if (err) {
		console.log('删除失败')
	} else {
		console.log('删除成功')
		console.log(ret)
	}
})

3.2 根据条件删除一个:

Model.findOneAndRemove(conditions,[options],[callback])

3.3 根据 id 删除一个:

Model.findByIdAndRemove(id,[options],[callback])
  1. 更新(修改)数据:

4.1 根据条件更新所有:

Model.update(conditions,doc,[options],[callback])

4.2 根据指定条件更新一个:

Model.findOneAndUpdate([conditions],[update],[options],[callback])

4.3 根据 id 更新一个

User.findByIdAndUpdate('5d67b2e50620924ad093faf1', {
	password: '123'
}, function(err, ret) {
	if (err) {
		console.log('更新失败')
	} else {
		console.log('更新成功')
		console.log(ret)
	}
})

15. Promise

为了解决回调地狱嵌套所带来的问题,所以在 EcmaScript 6 中新增了一个 API:Promise
基本语法:

// 在 EcmaScript 6 中新增了一个 API Promise
// Promise 是一个构造函数

var fs = require('fs')

// 1. 创建 Promise 容器,Promise 容器一旦创建,就立即开始执行里面的代码
// resolve 解决,reject 失败,Promise 容器默认为pending状态
var p1 = new Promise(function(resolve, reject) {
	fs.readFile('./views/index.html', 'utf8', function(err, data) {
		if (err) {
			// 把容器的 pending 状态变为 rejected
			reject(err)
		} else {
			// 把容器的 pending 状态变为 resolved
			resolve(data)
		}
	})
})

// 当 p1 成功了,then 方法接收的第一个function 就是容器中的 resolve,第二个就是容器中的 reject
p1.then(function(data) {
	console.log(data)
}, function(err) {
	console.log(err)
})

完整示例:

var fs = require('fs')

// 1. 创建 Promise 容器,Promise 容器一旦创建,就立即开始执行里面的代码
// resolve 解决,reject 失败,默认为pending状态
var p1 = new Promise(function(resolve, reject) {
	fs.readFile('./views/index.html', 'utf8', function(err, data) {
		if (err) {
			// 把容器的 pending 状态变为 rejected
			reject(err)
		} else {
			// 把容器的 pending 状态变为 resolved
			resolve(data)
		}
	})
})

var p2 = new Promise(function(resolve, reject) {
	fs.readFile('./views/post.html', 'utf8', function(err, data) {
		if (err) {
			reject(err)
		} else {
			resolve(data)
		}
	})
})

var p3 = new Promise(function(resolve, reject) {
	fs.readFile('./views/404.html', 'utf8', function(err, data) {
		if (err) {
			reject(err)
		} else {
			resolve(data)
		}
	})
})

// 当 p1 成功了,then 方法接收的第一个function 就是容器中的 resolve,第二个就是容器中的 reject
p1.then(function(data) {
		console.log(data)
		// 当 p1 读取成功的时候,当前函数中 return 的结果就可以在后面的 then 中 function 接收到,当 return 一个 Promise 对象的时候,后续的 then 中方法的第一个参数会作为 p2 的 resolve(成功)
		return p2
	}, function(err) {
		console.log(err)
	})
	// p2 的 resolve(成功)
	.then(function(data) {
		console.log(data)
		return p3
	})
	// p3 的 resolve(成功)
	.then(function(data) {
		console.log(data)
	})

15.1 封装 Promise 版本的 readFile API

var fs = require('fs')

function pReadFile(filePath) {
	return new Promise(function(resolve, reject) {
		fs.readFile(filePath, 'utf8', function(err, data) {
			if (err) {
				// 把容器的 pending 状态变为 rejected(失败)
				reject(err)
			} else {
				// 把容器的 pending 状态变为 resolved(解决)
				resolve(data)
			}
		})
	})
}

pReadFile('./views/index.html')
	.then(function(data) {
		console.log(data)
		return pReadFile('./views/post.html')
	})
	.then(function(data) {
		console.log(data)
		return pReadFile('./views/404.html')
	})
	.then(function(data) {
		console.log(data)
	})

16. 服务器自动重启

nodemon 是一个基于 node.js 开发的一个第三方命令行工具。

  1. 安装
    npm install --global nodemon:安装

nodemon --version:查看版本号,检测是否安装成功

  1. 使用方法:
nodemon app.js
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值