avatar

目录
【前端25_后台】Node.js

Node.js

介绍

为什么要学Node.js

  • 废话,你学前端得知道这个,招聘信息里xx没写么(具有服务端开发经验,拥有基本的网站开发能力,服务端,前端,运维部署),愣着干嘛学啊?
  • 帮助打开服务端。
  • 更好配合服务端开发人员进行协同开发。

Node.js是什么

Node.js® 是一个基于 Chrome V8 引擎 的 JavaScript 运行时。

  • 不是一门语言,不是库,不是框架

  • 是一个JavaScript运行时的环境

  • 可以做服务端的语言,假如后台服务器是个黑盒子,那么Node就是帮你打开这个黑盒子的工具。当然,不仅仅是Node可以,以下的也可以

    • Java
    • PHP
    • Python
    • Ruby (GitHub网站)
    • .Net (C#)
    • Node.js (采用JavaScript,作为一个前端,不需要为了学后台而去学习新的语言了)
  • 凡是能用JavaScript来实现的,最终都能用JavaScript来实现。

  • https://nodejs.org/zh-cn/ 这个Node的中文网站

浏览器的JavaScript Node.js中的JavaScript
ECMAScript ECMAScript
BOM -
Dom -
- 提供服务器级别API
  • 开源生产库npm,他是世界上最大的开源库生态系统,你可以用它来安装各种包。
  • 构建在Chrome的V8引擎上
    • 我们写的代码就是字符串而已,然而浏览器引擎可以帮你去解析和执行,目前Chrome V8是公认最快的引擎
    • Node.js 的作者把V8引擎移植出来,开发了独立的运行环境。

Node.js能做什么

  • Web 服务器后台
  • 游戏/结果服务器
  • 命令行工具
    • npm(node)
    • git(c语言)
    • Hexo(node)

要学会的

  • B/S 编程模型
    • Browser-Server
    • Node 只是我们学习BS 编程模型的工具
  • 模块化编程
    • CSS @import('文件路径')
    • 在Node 中可以像@import()一样来引用加载 JavaScript
  • Node的常用API
  • 异步编程
    • 回调函数
  • Express 开发框架
  • EcmaSctipt6 语法

起步

安装Node

  • 确认Node 环境是否安装成功
    • 打开命令行,输入node -v,如果有版本号显示,就说明成功了。

Hello World

  1. 创建并编写JavaScript脚本文件
  2. 打开终端,定位脚本文件所在目录
  3. 输入node 文件名,执行脚本(注意不要把文件名字起成node.js)

NPM

  • node package manager 是包管理工具

安装命令

  • npm install 包名 [–save]

  • –save 会将安装的包记录到package.json的dependencies中

  • npm i 包名 -D //-d是–save-dev缩写

  • 将包安装记录到devDependencies中,执行 npm install 时,可以指定安装哪些包

  • package.json用于记录项目中用了那些包,方便管理

语义化版本

  • ^version:中版本

​ ^1.0.1 -> 1.x.x

  • ~version:小版本

​ ~1.0.1 -> 1.0.x

  • version:指定版本

命令行工具

npm常用命令

  • npm --version npm版本号

  • npm install --global npm升级npm

  • npm init 构建项目

1
2
3
4
5
6
7
8
9
package name:包的名字,默认为当前目录名称 (名字不能有大写)
version:版本,默认从 1.0.0 开始
description:自述文件的信息或空字符串 ""
entry point: 入口文件
test command: 可以为空,npm test 为测试模块的命令
git repository:git 仓库
keywords:关键词
author:作者
license: 许可证 ISC
  • npm init -y 跳过向导快速生成

  • npm install根据 package.json 自动下载所需的包,也可以简写成npm i

  • npm install 包名 --save

npm i -S

​ 根据包名下载,并保存依赖在项目中的 package.json文件中

  • npm uninstall 包名 --save

npm un -S

​ 根据包名删除,并且删除依赖项

  • npm help查看帮助

  • npm 命令 --help 查看命令帮助

npm镜像

自定义工具包

  • 你可以自己写一个工具,然后再你的项目中导入,你的工具不要放在node-module里,不然别人会以为你的是第三方包

API

核心模块

Node为JavaScript提供了很多服务器级别的 API ,这些 API 绝大多数都被包装到了一个具名的核心模块中了。例如文件操作的fs核心模块,http 服务构建的 http模块,path路径操作模块,os操作系统模块等。

读取文件

  • 浏览器中的JavaScript 是没有文件操作的能力的,但是Node中的JavaScript具有文件操作的能力

  • fs是 Filesystem 的简写,就是文件系统的意思
    在 Node 中如果想要进行文件操作,就必须引入 fs 这个核心模块
    在 fs 这个核心模块中,就提供了所有的文件操作相关的 API

javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 1. 加载使用 require 方法加载 fs 核心模块
var fs = require('fs')

// 2. 读取文件
/*
第一个参数:文件路径
第二个参数:回调函数(err,data)
如果成功读取文件:data=数据, err=null
失败:data=null,err=错误对象
相对路径必须加./
如果想要返回上层目录用 ../
*/
fs.readFile('./a.txt', function (error, data) {
console.log(error)
console.log(data)
//

// 文件中存储的其实都是二进制数据 0 1
// 这里为什么看到的不是 0 和 1 呢?原因时二进制转为 16 进制
// 我们可以通过toString()转化
console.log(data.toString())
})

写文件

  • fs.writeFile('文件路径', '写入内容', '回调函数')

  • 写文件的文件名中不能有特殊字符,比方说?,<,’>’之类的。

javascript
1
2
3
4
5
6
7
8
9
// 写文件
var fs = require('fs')
fs.writeFile('../data/nihao.md', '你好,我叫Node', function (error) {
if(error === null){
return
}else{
console.log('文件写入成功')
}
});

创建个简单的服务器

javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 非常轻松的构建一个 Web 服务器

// 1. 加载 http 核心模块
var http = require('http')

// 2. 创建服务
// 返回一个 Server 实例
var server = http.createServer()

// 3. 服务器能干吗
// 提供服务:对数据的服务
// 注册 request 请求事件
server.on('request', function (request, response) {
var url = request.url
response.write(url)
response.end()
// console.log('收到客户端的请求了')

// response 对象有一个方法:write 可以用来给客户端发送相应程序
// write 可以使用多次,但是最后一定要使用 end 来结束响应
})

// 凡是需要网路通信的都需要端口号
server.listen(3000, function () {
console.log('服务器启动成功了!')
})

设置编码

  • 我们需要告诉浏览器我是中文操作系统,你得给我翻译成中文,不然我看不懂啊
  • Content-Type 告诉对方我给你发送的数据类型是什么类型
  • text/plain https://tool.oschina.net/commons
  • https://tool.oschina.net/ 在这里可以对应查找一些有用的
javascript
1
2
3
4
5
6
7
8
9
server.on('request', function (req, res) {
// 服务器默认发送的数据,其实是 utf8 编码的内容
// 但是浏览器不知道你是 utf8 编码的内容
// 世界上所有的语言韩文日文等,都是 utf8
// 中文操作系统默认是 gbk
// 所以我们要告诉浏览器,我给你发送的内容是什么
res.setHeader('Content-Type', 'text/plain; charset=utf-8')
res.end('hello 世界')
})

读取目录

javascript
1
2
3
4
5
6
fs.readdir('D:\\study\\前端\\Node重学', function (err, files) {
if (err) {
return '目录不存在'
}
console.log(files)
})

回调地域

问题描述:代码
在这里插入图片描述

解决的方案可以这样

javascript
1
2
3
4
5
6
7
8
9
10
11
12
var fs = require('fs')
fs.readFile('./text1.txt',function(err, data){
setTimeout(()=>{
console.log(data.toString())
fs.readFile('./text2.txt',function(err, data){
console.log(data.toString());
fs.readFile('./text3.txt',function(err, data){
console.log(data.toString());
})
})
},2000)
})

但是这样一层层的嵌套,多了的话会出现如下情况,非常的不美观回调地域

如何解决呢,用promise

javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
var fs = require('fs')
// resolve 承诺成功,reject承诺失败

new Promise((resolve, reject) => {
setTimeout(() => {
fs.readFile('./text1.txt',function(err, data){
resolve(data)
})
}, 1000)
}).then(function(data){
console.log(data.toString())
return new Promise(function(resolve, reject){
fs.readFile('./text2.txt',function(err, data){
resolve(data)
})
})
}).then(function(data){
console.log(data.toString());
return new Promise(function(resolve, reject){
fs.readFile('./text3.txt',function(err, data){
resolve(data);
})
})
}).then(function(data){
console.log(data.toString());
})

模块化

简单的模块化

  • require这个方法专门用来引入模块

我有三个文件a.jsb.jsc.js

javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// a.js

// require 是一个方法
// 他的作用就是用来加载模块
// 在Node 中,模块有三种:
// 1.核心 2.用户自己编写的 3.
// 相对路径必须加./
console.log('开始执行a')
require('./b.js')
console.log('结束执行a')

//开始执行a
// b.js文件被执行
// 结束执行a
javascript
1
2
3
4
// b.js
console.log('b.js start')
require('./c.js')
console.log('b.js end')
javascript
1
2
// c.js
console.log('ccccc')
shell
1
2
3
4
5
# 开始执行a
# b.js start
# ccccc
# b.js end
# 结束执行a

模块作用域

  • 简单的说,外部访问不到内部,内部也访问不到外部,就在这个文件里面。
  • 同名的变量名字,在不同的模块里,也不会相互污染

模块间的通信

我现在又有两个a.js,b.js,分别是

javascript
1
2
3
4
5
6
7
8
9
10
// a.js

var app = require('./b.js')
// require 方法有两个最哦用
// 1.加载文件模块并执行里面的代码
// 2. 拿到被加载文件模块导出的接口对象

// 在每一个文件模块中都提供一个对象:expore
console.log('app:', app)
console.log('app:', app.foo)
javascript
1
2
3
4
5
// b.js
var foo = 'bbb'
exports.foo = foo
// 导出的是一个对象,不论是变量还是方法,都需要a文件里点出来使用
console.log('exports:', exports)

运行之后的结果是

shell
1
2
3
exports: {}
app: {}
# 他俩是等价的

如果你想引用的话,就要在b中把想要暴露的变量挂载到exports


Express 模块

  • 就是http原生的封装,为了便于开发

指定公开路径

javascript
1
2
3
4
5
app.use('/public',express.static('./public/'));
访问路径:http://localhost:8000/public/test.html

app.use(express.static('./public/'));
访问路径:http://localhost:8000/test.html

模板引擎

shell
1
2
npm install --save art-template
npm install --save express-art-template
  • 默认是在views这个文件夹名称下寻找页面
  • 使用的方法如下
javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var express = require('express');
var app = express();
//配置模板引擎 以.art结尾时使用模板引擎
app.engine('art', require('express-art-template'));
app.set('view options', {
debug: process.env.NODE_ENV !== 'production' // 配置生产模式
});

app.get('/', function (req, res) {
//express为response提供了一个方法:render,此方法默认不可以使用,配置了模板引擎才可以使用
//res.render('模板名',{模板数据})
//第一个参数, 默认去项目的views目录中查找,如果想修改默认路径:app.set("views",'路径')
res.render('index.art', {
user: {
name: 'aui',
tags: ['art', 'template', 'nodejs']
}
});
});

热启动

  • 改代码的时候就不需要在启动一次服务器了

  • 安装

shell
1
npm i --global nodemon

​ 使用

shell
1
nodemon  app.js

端口号

  • 所有联网的程序都需要进行网络通信
  • 计算机中只有一个物理网卡,同一个局域网中,网卡的地址必须唯一的。网卡是通过唯一的IP地址来进行定位的。
  • 每一个联网的应用对应一个端口号
  • IP地址用来定位计算机,端口号用来定位具体的联网应用程序
  • 获取访问我的另一条电脑的IP地址和端口号req.socket.remoteAddressreq.socket.remotePort
  • 端口号的范围从 0~65536 之间
  • 网站上线部署的时候默认是80端口,所以80的话尽量不要用

跨域以及同源策略

  • 只有当协议(http,https),域名,和端口号三者都一直的时候,才是同源
  • 同源安全是浏览器行为,请求到后台的话后台也会处理,但是返回到前台浏览器不允许展示
  • 如何解决跨域:第一种方法是后台设置响应头res.header('Access-Control-Allow-Origin', '*') ,其中的*可以写成同意跨域的IP地址,第二种方法是前台设置JsonP。

其他

  • GFM Markdown的语法标准
  • 代码风格
    • JavaScript Standard Style
    • 爱彼迎
  • 代码风格

    • 当你采用了无分号的代码风格的时候,只需要注意一下情况就不会有上面的问题
javascript
1
2
3
4
5
say()
//当一行代码是以( [ ` 开头的时候,则在前面补上一个分号用以鼊一些语法解析错误
;(function(){
console.log('hello')
})()
文章作者: Lovely Ruby
文章链接: https://wangzhongqing.xyz/p/c498e88b.html
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Ruby の いえ
打赏
  • 微信
    微信
  • 支付寶
    支付寶

评论