关于Node.js
Node.js是什么
- Node 是一个让 JavaScript 运行在服务端的开发平台
Node.js能做什么
- web服务器后台
- 命令行工具
npm(node)
git(c语言)
hexo(node)
安装Node.js环境
-
下载:https://nodejs.org/en/download/
-
安装
-
确认环境是否安装成功
打开cmd,输入node --version 或者node -v -
环境变量
Hello World
- 创建编写js文件
- 打开终端,定位到脚本文件所属目录
- 输入node 文件名执行对应文件(文件名不能使用’node.js’)
- 解析执行js
核心模块加载
实例:var http = require('http');
Node中的js
- EcmaScript 没有DOM和BOM
- 核心模块
- 第三方模块
- 用户自定义模块
Node中引入其他js文件
- 在每个文件模块中都提供了一个对象:exports
- exports 默认是一个空对象
- 你要做的就是把所有需要被外部访问的成员挂载到这个 exports 对象中
Node读写文件
-
读取文件
-
var fs = require(‘fs’)
fs.readFile(’./文件路径’,对调函数) -
写入文件
-
var fs=require(‘fs’)
fs.writeFile(’./文件路径’,写入内容,回调函数)
用Node搭建简单服务器
-
加载http核心模块
-
var http = require(‘http’);
-
创建web服务器
var server = http.createServer(); -
处理请求
server.on(‘request’,function () {
console.log(‘收到客户端请求了’);
}); -
绑定端口号,启动服务器
server.listen(3000,function () {
console.log(‘服务器启动成功’);
})
Content-type
安装模板引擎
- npm install art-template
- 该命令在哪里执行,默认就会下载到node_modules中
- 模板引擎不关心字符串内容,只关心自己能认识的模板标记语法如{{ }},{{ }}语法被称之为mustache语法
Node中的模块系统
使用Node编写应用程序主要就是在使用:
-
EcmaScript语言
-
核心模块
文件操作的fs
http服务的http
url路径操作模块
path路径处理模块
os操作系统信息 -
第三方模块
art-template
必须通过npm下载 -
自定义模块
自己创建文件
什么是模块化
- 文件作用域
- 通信规则
加载require
导出
CommonJs模块规范
在Node中的JavaScript还有一个很重要的概念:模块系统
- 模块作用域
- 使用require方法加载模块
- 使用exports接口对象用来导出模块中的成员
如果一个模块需要直接导出某个成员,而非挂载,此时必须使用module.exports = 成员
加载require
语法:
var 自定义变量名称 = require(‘模块’)
两个作用:
- 执行被加载模块中的代码
- 得到被执行模块中exports导出接口对象
导出exports
- Node中是模块作用域,默认文件中所有成员只在当前文件模块有效
- 对于希望可以被其他模块访问的成员,我们就需要把这些公开的成员都挂载到exports接口对象中就可以了
导出多个成员(必须在对象中):
exports.a = 123
exports.b = ‘hello’
exports.c = function () {
console.log(‘ccc’)
}
exports.d = {
foo: ‘bar’
}
导出单个成员(拿到的就是:函数、字符串)
module.exports = ‘hello’
以下情况会覆盖:
module.exports = ‘hello’
module.exports = function (x,y) {
return x + y
}
也可以这样来导出多个成员:
module.exports = {
add: function () {
return x + y
},
str: ‘hello’
}
原理解析
exports是module.exports的一个引用
console.log(exports === module.exports) // => true
exports.foo = ‘bar’
//等价于
module.exports.foo = ‘bar’
exports和module.exports的区别
-
Node 为了简化操作,专门提供了一个变量:exports 等于 module.exports
-
真正去使用的时候:
导出多个成员:exports.xxx = xxx
导出多个成员也可以:module.exports = {
}
导出单个成员:module.exports
require方法加载规则
-
核心模块
模块名 -
第三方模块
模块名 -
用户自己写的
路径(./不能省略) -
优先从缓存加载
在一个文件加载过的不会再重复加载,重复使用require是为了获取成员 -
判断模块标识
核心模块
第三方模块
自己写的模块
注意:第三方模块node_modules最好放在根目录
package.json
建议每一个项目都要有一个package.json(包描述文件),此文件可通过npm init的方式初始化出来
建议执行npm install 包名 的时候都要加上 --save,用来保存依赖项信息
package.json和package-lock.json
npm 5以前是不会有package-lock.json这个文件的
当你安装包的时候,会自动创建或者更新package-lock.json这个文件
- npm5以后的版本安装包不需要加–save参数,它会自动保存依赖信息
- 当你安装包的时候,会自动创建或者更新package-lock.json这个文件
- package-lock.json这个文件会保存node_modules中所有包的信息(版本、下载地址),这样重新下载 npm install 的时候速度可以提升
- 从文件来看,有一个lock称之为锁
这个lock是用来锁定版本的,如果项目依赖了1.1.1版本,重新install其实会下载最新版本,而不是1.1.1;所以package-lock.json另一个作用就是锁定版本号,防止自动升级新版
path路径操作模块
-
path.basename 获取一个路径的文件名(默认包含扩展名)
-
path.dirname 获取一个路径中的目录部分
-
path.extname 获取一个路径的扩展名部分
-
path.parse 获取一个路径的扩展名部分
-
path.parse
把一个路径转为对象
root根路径
dir目录
base包含后缀名的文件名
ext后缀名
name不包括后缀名的文件名 -
path.join
推荐路径拼接方法 -
path.isAbsolute
判断一个路径是否是绝对路径
Node中的其他成员
在每个模块中,除了require、exports等模块相关API之外,还有两个特殊的成员
__dirname
动态获取 可以用来获取当前文件模块所属目录的绝对路径__filename动态获取
可以用来获取当前文件的绝对路径__dirname
和__filename
是不受执行node命令所属路径影响的
在文件操作中,使用相对路径是不可靠的,因为在Node中文件操作的路径被设计为相对于执行node命令所处的路径,所以可以把相对路径转为绝对路径来解决问题,即使用__dirname
和__filename
,推荐配合path.join()辅助拼接来避免拼接错误
注:模块中的路径标识和这里的路径没关系,不受node操作路径影响(相对于文件模块)
’
npm
- npm网站
- npm命令行工具
升级npm : npm install --global npm
npm常用命令
-
npm init
npm init -y 可以跳过向导,快速生成 -
npm install
简写:npm i
一次性把dependencies选项中的依赖项全部安装 -
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
查看制定命令的使用帮助
如忘记了uninstall命令的简写,可以输入npm uninstall --help
解决npm被墙问题
npm存储包文件的服务器在国外,有时候会被墙,速度慢
http://npm.taobao.org/淘宝开发团队把npm在国内做了备份
安装淘宝的cnpm:
npm install --global cnpm(可以在任意目录执行,--global表示安装到全局,接下来安装包时把之前的npm替换成cnpm)
如果不想安装cnpm又想使用淘宝服务器来下载:
npm install jquery --registry=https://registry.npm.taobao.org
但是每一次手动这样加参数很麻烦,所以可以把这个选项加入到配置文件
npm config set registry https://registry.npm.taobao.org
查看 npm配置信息
npm config list
文件操作路径和模块路径
-
文件操作路径
在文件操作的相对路径中
./data/a.txt相对于当前目录
data/a.txt相对于当前目录
/data/a.txt绝对路径,当前文件模块所处磁盘根目录
C:/xx/xx…绝对路径 -
模块操作路径
如果忽略了’ . ‘,则也是磁盘根目录
require(’/data/foo.js’)
相对路径
require(’./data/foo.js’)
//模块加载的路径中的相对路径不能省略/
静态服务
app.use(express.static('public'))
app.use('/static',express.static('public'))
修改代码自动重启
用nodemon第三方工具解决修改代码需要重启的问题
#所有需要–global来安装的包都可以在任意目录执行
npm install --global nodemon
安装完成后原来的“node 文件名” 改成"nodemon 文件名"
在Express中配置使用art-template模板引擎
在Express中获取表单GET请求参数
Express内置了一个API,可以直接通过req.query来获取
在Express获取表单POST请求体数据
在Express中没有内置获取POST请求体的API,这里要是用第三方包:body-parse
安装:
npm install --save body-parser
配置:
MongoDB
关系型数据库和非关系型数据库
表就是关系,或者说表与表之间存在关系
- 所有的关系型数据库都需要通过sql语言来操作
- 所有的关系型数据库在操作之前都需要设计表机构
- 而且数据表还支持约束
- 非关系型数据库非常灵活,有的就是key-value对
- MongoDB是最像关系型数据库的非关系型数据库
数据库-> 数据库
数据表->集合(数组)
表记录->文档对象 - MongoDB不需要设计表结构
启动和关闭数据库
启动:
mongodb默认使用执行mongod命令所处盘符根目录下的data/db作为自己的数据存储目录
所以在第一次执行该命令之前要先创建一个/data/db
修改默认的数据存储目录
mongod --dbpath=数据存储目录路径
停止
在开启服务的控制台,直接ctrl+c 即可停止
或者直接关闭开启服务的控制台
基本命令
- show dbs 查看显示所有数据库
- db 查看当前操作的数据库
- use 数据库名称 切换到指定的数据库(如果没有就会自动创建新的数据库)
- 插入数据
在Node中操作MongoDB数据
- 使用官方的mongodb包来操作
https://github.com/mongodb/node-mongodb-native
- 使用第三方mongoose来操作MongoDB数据库
第三方包:mongoose基于MongoDB官方的mongodb包再一次做了封装
npm install --save mongoose
mongoose
-
官网;http://mongoosejs.com/
-
官网指南;http://mongoosejs.com/docs/guide.html
-
官方API文档:http://mongoosejs.com/docs/api.html
官方指南 -
设计Schema发布Model
var mongoose = require('mongoose')
var Schema = mongoose.Schema
// 1. 连接数据库
// 指定连接的数据库不需要存在,当你插入第一条数据之后就会自动被创建出来
mongoose.connect('mongodb://localhost/itcast')
// 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)
- 新增数据
var admin = new User({
username: 'zs',
password: '123456',
email: 'admin@admin.com'
})
admin.save(function (err, ret) {
if (err) {
console.log('保存失败')
} else {
console.log('保存成功')
console.log(ret)
}
})
- 查询数据
查询所有
User.find(function (err,ret) {
if (err) {
console.log('查询失败')
} else {
console.log(ret)
}
})
条件查询
User.find({
username: 'root'
},function (err,ret) {
if (err) {
console.log('查询失败')
} else {
console.log(ret)
}
})
条件查询单个
User.findOne({
username: 'root'
},function (err,ret) {
if (err) {
console.log('查询失败')
} else {
console.log(ret)
}
})
- 删除数据
User.remove({
username: 'root'
},function (err,ret) {
if (err) {
console.log('删除失败')
} else {
console.log(ret)
}
})
- 更新数据
User.findByIdAndUpdate('5d303c0ec6e2e9137cd930d8',{
password: 'admin'
},function (err,ret) {
if (err) {
console.log('更新失败')
} else {
console.log('更新成功')
}
})