js是一门客户端语言,且是一门脚本语言,也就是说只能在浏览器上运行,且只能依赖HTML才能运行。
为了提高js的格调,让js脱离浏览器也能运行,一代大神Ryan Dahl在2009年,通过分析将谷歌中V8引擎(即谷歌浏览器中的js解析器),分离出来,进行二次封装,做出了一款软件,叫node.js。
这款软件中可以运行js代码,且不需要依赖浏览器和HTML。
所以说,node.js本质上是一个js除了浏览器之外的运行环境,使得js除了是一门客户端语言外,还是一门和Java、PHP、Ruby平起平坐的客户端语言。
使用node.js注意
1.node.js实现了js代码在浏览器外执行,所以在node.js中无法运行DOM和BOM代码
2.node,js除了EcmaSrcipt外,还内置了很多其他Api
3.node.js让js在写前端代码的基础上,可以写后端代码,因为node.js可以构建服务器
中文文档
下载安装
nodejs是执行js代码的环境,执行方式有两种:
1.在node.js直接执行代码(类似于在浏览器控制台写js代码并执行)
在命令行中输入node,敲回车,就进入了nodejs的控制台,操作跟浏览器的控制台一样
node
console.log(111)
退出这个控制台,通过两次ctrl+c或者.exit命令。
这种方式无法用来开发代码,因为我们也从不在浏览器的控制台开发代码
2.使用nodejs执行js文件
新建js文件,书写规范的js代码,通过命令行的node命令执行这个文件。
执行的文件有两种方式
①当前命令行不在文件所在的文件夹下,此时需要文件的绝对路径 - 不常用
②当前命令行在文件所在的文件夹下,此时使用文件的相对路径即可 - 常用
因为node命令执行js文件的时候,只能指定一个js文件,所以我们在开发的时候只能将项目所有代码写在一个文件中,可是这样不利于我们进行分工合作,也不利于后期项目的维护,所以需要对js代码进行模块化管理。
所有前端的模块化,都是将一个js 当做是一个模块,多个模块之间可以互相导入使用
CommonJS是nodejs中自带的模块化规范,只能在nodejs中使用,导出使用module.exports关键字 ,导出使用require关键字。
// 导入
require(被导入的模块)
// 导出
module.exports = {数据}
module.exports.键 = 值
exports.键 = 值
一个文件就是一个独立的模块,可以理解为是一个独立的作用域,别的模块需要用到这个作用域中的数据,就需要将这个作用域中的数据导出,可以理解为函数返回数据的意思。
a.js导出:
let a = 10
module.exports = a // 数据a就被导出了 - 这种导出方式只能导出一个数据
module.exports = {a} // 对象被导出了 - 通常要导出多个数据就使用这种导出方式
module.exports.a = a // 导出了一个对象 - 这种导出方式可以在多个地方导出数据
为了让导出变得更简单,commonjs规范中,在每个模块中定义了一个变量exports,并将module.exports赋值给了exports,导出时可以使用exports:
exports = {a}
exports.a = a
注意:使用exports导出的时候,千万不能直接给exports赋值,因为导出功能是由module.exports提供的,如果直接给exports赋值,就将exports的内存空间换成另外一个数据空间了,将失去导出功能。
b.js导入:
let data = require('./a.js')
导入的就是导出的数据,导出数据就接受到数据,导出对象就接收到对象。
注意:导入的文件是自定义的,那路径中的./是不能省略的。导入文件的后缀可以省略,因为nodejs中能被导入的只能是js文件。
在nodejs中被导入的模块分三种:
1.自定义模块 - 路径中的./不能省略
2.内置模块 - 只需要导入模块名称,不需要路径,因为默认会在系统中找这个文件
3.第三方模块 - 别人写好的js文件,我们需要导入使用,所以必须提前下载好才能导入使用
fs(file system)模块提供了用于文件进行交互的相关方法。
const fs = require('fs')
// 写入数据(覆盖)
fs.writeFile(文件路径,待写入的数据,err => {}) // 异步写入文件
fs.writeFileSync(文件路径,待写入的数据) // 同步写入文件
// 读取文件中数据
fs.readFile(文件路径, 'utf-8’,(err,data) => {}) // 异步读取文件
fs.readFileSync(文件路径, 'utf-8’) // 同步读取文件
// 第二个参数是可选项,如果不加的话,默认读取出来的buffer(用16进制来描述2进制数据流的格式)数据,需要通过buffer.toString()才能转成字符串
// 判断文件是否存在
let ret = fs.existsSync(path)
// 获取文件信息(异步)
fs.stat(文件,(err,stats) => {
stats.isDirectory() // 是否是目录
stats.isFile() // 是否为文件
stats.size // 文件大小(以字节为单位)
})
// 给文件中追加内容
fs.appendFile(文件路径,待写入的数据,err => {}) // 异步追加
fs.appendFileSync(文件路径,待写入的数据) // 同步追加
// 删除文件(异步)
fs.unlink(文件路径,err => {})
// 文件重命名
fs.renameSync(旧的文件路径, 新的文件路径)
os(operation system)模块提供了与操作系统相关的实用方法和属性。
const os = require('os')
// 换行符
os.EOL //根据操作系统生成对应的换行符 window \r\n,linux下面 \n
// cpu相关信息
os.cpus()
// 总内存大小 (单位 字节)
os.totalmem()
// 空余内存大小 (单位 字节)
os.freemem()
path模块用于处理文件和目录(文件夹)的路径。
const path = require('path')
// 获取路径最后一部内容,一般用它来获取文件名称
path.basename('c:/a/b/c/d.html') // d.html
// 获取目录名,路径最后分隔符部分被忽略
path.dirname('c:/a/b/c/d.html') // c:/a/b/c
// 获取路径中文件扩展名(后缀)
path.extname('c:/a/b/c/d.html') // .html
// 给定的路径连接在一起
path.join('/a', 'b', 'c') // /a/b/c
__dirname:是nodejs提供的一个内置变量,代表当前文件所在位置的绝对路径
斜杠和反斜杠:通常用来分割路径,“某个文件夹下”的意思,在window系统中,斜杠和反斜杠的意义是一样的,但是建议写斜杠,反斜杠在代码中有特殊含义,转义的意思,在服务器系统中,默认路径就是使用斜杠
url字符串是结构化的字符串,包含多个含义不同的地方。解析字符串后返回的URL对象,每个属性对应字符串的各个组成部分。
const url = require('url');
const href = 'http://www.xxx.com:8080/pathname?id=100#bbb'
// 解析网址,返回Url对象
// 参2 如果为true 则 query获取得到的为对象形式
url.parse(href,true)
//以一种 Web 浏览器解析超链接的方式把一个目标 URL 解析成相对于一个基础 URL。
url.resolve('https://lynnn.cn/foo/bar',../'bar') // https://lynnn.cn/bar
用于解析和格式化URL查询字符串(URL地址的get形式传参)的实用工具。
const querystring = require('querystring')
// query字符串转为对象
querystring.parse('foo=bar&abc=xyz')
querystring.decode('foo=bar&abc=xyz')
// 对象转为query字符串
querystring.stringify({ foo: 'bar',abc: 'xyz'})
querystring.encode({ foo: 'bar',abc: 'xyz'})
服务器指的是用来提供服务的,无论本机还是其他计算机,只要能提供服务就可以将它称之为服务器。
我们这里所说的服务器,应该叫做web服务器,一般指的是网站服务器,就是能提供网站访问服务软件或程序,目前最主流的三个web服务器软件是Apache、Nginx、IIS。
// 导入http模块
const http = require('http')
// 创建web服务对象实例
const server = http.createServer()
// 绑定监听客户端请求事件request
// on方法做事件监听
server.on('request', (request, response) => {})
/*
request变量和response变量都是对象
request对象中包含了跟客户端请求相关的信息,例如:请求方式、请求路径、请求头 。。。
请求方式:request.method 值是大写的方法
请求路径:request.url 值是从network中看到的请求路径(不是完整的请求地址)
请求头:request.header 值是从network中看到的请求头
response对象是用来提供的响应的对象,其中方法居多
结束响应:response.end() 如果不结束响应,客户端在访问的时候会一直转
响应内容:
response.end(数据) response.end除了有结束响应的功能,还可以给客户端响应内容,内容格式要求:字符串/buffer
response.write(数据)
设置响应头:response.setHeader(键, 值)
设置响应状态码和响应头:
response.writeHead(状态码, 状态描述, {响应头})
*/
server.listen(8080, () => { // 这里的第二个参数回调函数可以省略
console.log('服务已启动')
})
通常在访问服务器的时候,默认会有一个网站图表的请求,要求服务器提供网站图标。
简写:
require('http').createServer((req, res) => {
// 处理响应
}).listen(端口号)
假设我们写好了一套静态页面,但是需要让别人访问,就需要提供一个服务器,且别人来访问的时候还要能访问到对应的静态页面。这种服务器称之为静态资源服务器,目的只是为了提供访问静态资源。
const path = require('path')
let fs = require('fs')
require('http').createServer((req, res) => {
// 处理响应
// 通过请求路径获取到对应的文件路径
let filePath = path.join(__dirname, 'public', path.basename(req.url))
let ret = fs.existsSync(filePath) // 判断文件路径是否存在
// 判断文件路径是否是一个文件
fs.stat(filePath,(err,stats) => {
if(stats.isFile()){
// 读取文件并响应
res.end(fs.readFileSync(filePath))
}else{
// 如果不是文件就响应404
res.writeHead(404)
res.end() // 结束响应,避免客户端一直转
}
})
}).listen(端口号)
// 导入
const http = require('http');
const url = require('url');
// 创建实例&监听request事件&监听端口
http.createServer((req, res) => {
// 之前第3步中的回调函数
// 获取地址栏中 query数据
let { query } = url.parse(req.url, true);
console.log(query);
}).listen(8080)
const http = require('http');
const queryString = require('querystring');
http.createServer((req, res) => {
let str = ''
// data事件表示数据接收中
req.on('data', chunk => { // chunk表示接收到的一点一点的数据
str += chunk.toString()
});
// end事件表示数据传输结束了
req.on('end', () => {
let postData = queryString.parse(str) // 将接收到的字符串转为对象
console.log(postData);
});
}).listen(8080)
就是网上别人已经开发好的模块,我们可以直接拿来借鉴使用,但是需要下载,下载工具使用npm。
下载:
npm install/i 包名
npm i 包名 包名 ... # 下载多个模块
npm i 包名@版本号 # 最新版本可以使用 @latest
下载命令执行后,会产生node_modules文件夹,将下载好的包放在这个文件夹中。
这个文件夹的特点:文件比较琐碎,层级嵌套较深,依赖关系较多......
查看模块的所有版本:
npm view 模块 versions
查看所有安装好的依赖包:
npm list # 简写 npm ls
卸载:
npm uninstall/un 包名
下载/卸载参数
--save-dev 简写 -D 表示下载的这个包是一个开发依赖,将来上线后将不需要,只是在本地开发阶段需要
--save 简写 -S 表示下载的这个包是一个生产依赖,将来项目上线后还需要,本地开发和远程上线都需要,npm默认使用--save参数
--global 简写 -g 表示下载的这个包是一个命令,需要在计算机任何一个位置都能使用
初始化:
npm init # 手动输入整个包的信息
npm init -y # 自动生成整个包的信息 - 不能在中文文件夹下使用
# 初始化命令执行以后,会生成package.json文件,生成后在当前目录下安装的所有包,都会自动记录在这个文件中,方便查看、下载、卸载、分析等操作
npm install/i # 安装所有package.json中记录好的包,只安装生产依赖(之前用过-S),不安装开发依赖(之前安装用-D)
初始化的原因:
我们在开发的时候需要很多依赖包,等开发完成后,项目需要传到服务器环境下运行上线,但node_modules文件由于自身特点,不方便上传,可能在上传过程中造成无法上传文件或文件丢失等问题,所以,我们将项目中依赖的包记录在package.json文件中,在服务器环境中根据记录的包的信息,再次下载即可。
npm切换镜像源
npm config set registry 镜像源地址 # 切换命令
npm config get registry # 查看镜像源地址
npm --registry https://registry.npm.taobao.org install node-red-contrib-composer@latest # 临时切换使用
查看所有全局包:
npm list -g
清除缓存:
npm cache clear --force/-f
下载好的模块如果不知道怎么使用,上网查询npm 。所有使用npm下载好的模块,都在这个网站上能找到。
const http = require('http');
const cheerio = require('cheerio')
// http模块提供了get方法用来做爬虫
http.get(地址,res=>{
let str = ''
// 像接收post数据一样通过事件接收数据
res.on('data', chunk => {
str += chunk.toString()
})
res.on('end', () => {
console.log(str)
/*
响应回来的str是爬到的目标网页中的所有内容,对于爬回来的数据处理,有2种方式:
1.正则匹配
2.利用cheerio第三方模块去处理
*/
const $ = cheerio.load(str)
// $的时候可以像jquery中的$一样,直接能获取到爬回来的数据中的节点
})
})
const http = require('http')http-proxy-middleware
// 服务器中的代理,需要使用第三方模块
const proxy = require('http-proxy-middleware')
// 创建代理
let fn = proxy.createProxyMiddleware({
target: '', // 要代理的目标地址
changeOrigin: true, // 转换请求源
pathRewrite: {
'/daili':'' // 将原地址从目标地址中过滤掉
}
})
http.createServer((req, res) => {
let url = req.url
if(url === '/daili'){
// 调用代理函数
fn(req, res)
}
})
模块查找顺序:系统中>node_modules
启动一个web服务器。
下载安装:
npm i http-server -g
启动:
http-server
依赖一个json文件启动web服务器,且自带了对json文件操作的接口:
下载安装:
npm i json-server -g
使用:
json-server json文件
然后就启动了一个http服务器。且可以通过post、delete、put、get四种请求来对json文件中的数据做增删改查。
也就是说这个服务器内置json数据的操作接口,接口地址显示如下:
get http://localhost:端口号/json的键 - 获取所有数据
post http://localhost:端口号/json的键 请求主体中传送数据 - 新增一条数据
delete http://localhost:端口号/json的键/id - 删除指定id的数据
put http://localhost:端口号/json的键/id 请求主体中传送数据 - 修改指定id的数据
get http://localhost:端口号/json的键/id - 获取指定id对应的数据
yarn跟npm一样,是一个第三方包的管理工具,比起npm,yarn工具更加高效快捷。
通常在下载一些较为复杂的包的时候,多个包之间总会有一些依赖关系,npm下载的时候,使用续发形式下载,也就是同步下载,而yarn是并发式下载,也就是异步下载,效率更高。例如:我们需模块A,但是模块A需要依赖模块B,模块B又需要依赖模块C,npm下载的时候是按照顺序:C...>B...>A;yarn下载的时候是并发下载:A和B和C同时下载。
yarn不是一个自带工具,需要手动下载安装,下载地址安装 | Yarn 中文文档
检测安装:
yarn --version
初始化:
yarn init
yarn init -y
下载安装包:
yarn add 包
yarn add 包@版本号
卸载包:
yarn remove 包
安装全部依赖:
yarn
yarn install
这是一个全局工具,用法和node一样,但nodemon可以自动监视文件变化,当文件发生变化会自动重新执行命令。
下载安装:
npm i nodemon -g
使用:
nodemon 待执行的js文件
当文件发生改变后,会自动重新启动,无需重启。