* 对 node 的了解
*
* node 当时出现的 原因是什么
* 前端只有 JS 开发
* 后端: JAVA PHP....
*
* 所以 node 出现的原因就是为了 统一 全世界 的 编程语言
* 当时的目的就是为了所有的开发者能够用一个语言, 完成所有程序的编写
*
* 当时给程序起了个名字, 叫做 node, 后续因为 JS 统一了前端, 所以就想利用 js 也去书写后端
* 所以 node 是基于 js 完成的
*
* 所以node本质上是帮助我们JS扩展一些 完成后端的功能
*
*
* node 是如何运行的
* JS 原本只能运行在 浏览器中, 因为浏览器提供了运行JS的环境 其中最重要的是引擎
* 谷歌浏览器有一个引擎比较出名, 叫做 V8
*
* node 就是把 谷歌的 V8 引擎 拿出来, 去在电脑系统内运行, 然后给我们的 JS 提供了一个新的运行环境
* 也就是现在 JS 可以脱离浏览器, 运行到我们的 电脑系统中
*
*
*
* JS 运行到 node 环境和 运行到 浏览器环境 有什么区别?
*
* 1.1 原本 JS 是引入到 html 文件中, 然后将 html 文件运行到 浏览器中
* * 其中 html 提供了 DOM 的能力
* * 浏览器 提供了 BOM 的能力
* * 除了 DOM 和 BOM 之外 就剩下一个 标准 ES
* 1.2 但是现在 JS 不在引入到 html 文件中, 也不再运行到浏览器中, 而是运行到 电脑系统中
* * 所以我们就失去了 DOM 和 BOM 的能力
* * 所以 就剩下了 ES
* * 但是我们因为运行在电脑系统中, 所以我们也有了一些新的能力
* * 操作文件/目录: 创建, 编辑, 删除......
* * 操作数据库
*
* 2.1 原本如果我们有多个 JS 文件, 我们可以有多种方式将 JS 运行到一起
* * 将 多个 JS 文件 引入到同一个 html 文件中, 这些文件共享一个全局作用域
* * 利用 ES6 模块化语法, 将JS进行一个合理的导入导出, 然后使用
* 2.2 在 node 中, 我们也有可能会遇到有多个 JS 文件的情况
* * 因为我们 node 中, 不会出现 html 文件, 所以我们不能将多个 JS 文件引入到同一个 html 文件中
* * 利用 Commonjs 的模块化规范 进行一个 导入导出
*
* 因为 node 出现的时间是 08/09 此时 还没有 ES6
* 但是我们只要书写 node 就需要 模块化, 所以有了 Commonjs 的规范
*/
* 命令行
*
* windows: cmd/powershell
* mac: 终端
*
*
* 启动: cmd/powershell
* 1. window(左下角由四个小方块组成的一个按键/win) + r
* 2. 上一步完成后 会弹出一个弹窗 名字叫做 运行
* 3. 在运行内的输入框输入 cmd 或者 powershell
* 4. 然后按下 回车 C:\Users\41099
* 5. 此时会弹出一个弹窗 (cmd/powershell), 此时这个终端的 地址, 是我们系统的 基地址
*
*
* 上述的启动方式地址可能和我们项目的地址不同, 所以有一个新的启动方式
*
*
* 1. 打开项目的文件夹
* 2. 在文件夹上部 1/4 地址的输入框, 鼠标左键单击一次, 选中地址文本的时候直接输入 cmd/powershell
* 3. 然后 按下回车 C:\Users\41099\Desktop\飞秋共享\BK_2310_2\07_周\05_天\code>
*
*
* 1. 使用 win + r 直接启动一个 小黑窗 C:\Users\41099>
* 2. 找到你项目的文件夹所在的地址 复制地址
* 3. 找到小黑窗输入命令: cd 你的地址 C:\Users\41099\Desktop\飞秋共享\BK_2310_2\07_周\05_天\code>
*
*
* 1. 使用 vscode 打开你的项目
* 2. 找到你项目文件夹, 鼠标右键单击
* 3. 在弹出菜单中 找到 '在集成终端中打开
*
*
*
*
*
* 终端命令
* 1. 如果窗口文本太多, 需要清空:
* cmd: cls
* pw: clear
* 2. 查询 当前目录内的 内容
* cmd/pw: dir
* 3. 如果当前终端地址不对, 需要更改
* 3.1 去到下一个目录: cd 目录名
* 3.2 回到上一个目录: cd ..
*
*/
* 利用 node 运行 js
*
*
* 1. 随便打开一个终端, 方式无所谓, cmd/pw 无所谓, 终端路径无所谓
* 2. 在终端输入一个指令: node 然后敲回车
* 3. 此时我们会进入到 js 的编译程序中, 此时这个窗口类似于 浏览器的控制台
* 注意: 一定是 敲下 node 后才可以
*
* 但是上边的启动方式有一些小问题
* 1. 你在这个终端中书写的代码 不能保存
* 2. 如果代码只有一行, 那么书写没什么难度, 如果代码是多行, 那么书写起来很不方便
*
* 所以上述的方式只是能用, 但是不推荐
*
*
* 推荐的方式:
* 1. 在一个 JS 文件中书写我们要执行的代码
* 2. 鼠标右键单击这个文件, 选择 在 集成终端中打开
* 3. 输入一个命令 node 文件名
* 4. 敲回车
*/
// console.log('我是利用了 推荐的方式 书写的 JS, 并且最终会运行到 node 环境')
// console.log('我是利用了 推荐的方式 书写的 JS, 并且最终会运行到 node 环境', window)
// console.log('我是利用了 推荐的方式 书写的 JS, 并且最终会运行到 node 环境', document)
/**
* 在 node 中 导入的文件如果后缀是 .js 那么可以省略后缀
*
* 导入文件的时候会先将这个文件整体执行一遍
* 然后将 导出的内容, 拿到当前文件内
*/
const res = require('./04_node的模块化')
console.log('导入的数据: ', res)
* node 的模块化语法
*
* 模块化其实就是将 JS 内的部分数据或者方法 导出 或者 在另一个文件中导入一个文件内的数据或者方法
*
* 导出:
* 每一个 JS 文件, 只要运行到 node 环境中, 那么就回自导一个 变量 module
* 这个变量对应的值是一个对象, 对象中有很多属性
* 其中有一个属性叫做 exports, 这个属性的值 默认是一个空对象
* 这个属性的值是什么 当前文件就会导出什么
* 这个属性可以是一个字符串, 那么就导出一个字符串
* 这个属性可以是一个数组, 那么就导出一个数组
* 这个属性可以是一个函数, 那么就导出一个函数
* .....
*
*
* 每一个 JS 文件, 只要运行到 node 环境中, 那么就会自带一个变量 exports
* 这个变量的地址和 module.exports 内部的初始的对象地址完全相同
*
*
* 总结:
* 1. 给 module.exports 直接赋值 (任意类型无所谓)
* 2. 给 module.exports 这个对象内添加一些属性 (属性的值无所谓)
* 3. 给 exports 这个对象内添加一些属性 (属性的值无所谓)
*
*
* 导入:
* 在每一个 JS 文件中 天生自带一个 方法(函数) require()
*
* 调用这个函数的时候需要传入一个参数, 这个参数是你需要导入的文件地址
* require('./隔壁的XXX文件')
* 这个方法还有一个返回值, 返回值就是 你导入文件中 module.exports 这个属性的值
*
*
* 导入只有一个语法
* const 变量 = require('导入文件的地址')
*/
// console.log(module);
/*
Module {
....
exports: {},
....
}
*/
/**
* 在 node 中 每一个 文件 就是一个独立的模块
*
*
* 模块还有一些具体的划分
* 自定义模块: 自己写的每一个JS文件, 就是一个独立的自定义模块
* 内置模块: node 中提供好的模块, 这些模块可以帮助我们做很多事情
* 对文件的处理
* 对服务器的处理
* 对文件路径的处理
* 对url地址的处理
* .....
* 第三方模块: 别人写的模块就叫做第三方模块
* 用户A 写好了一个代码 有一些功能, 他将这个文件上传到了一个全世界开发者公用的仓库中, 给别人免费使用
* 用户B 发现了用户A 上传的这个代码, 以及他的功能, 正好是 用户B 所需要的
* 所以现在用户B除了自己重新写一遍之外, 还可以选择 去这个全世界开发者公用的仓库中 下载用户A 上传的代码
*
* 此时 用户A 写好的这个模块, 相对于 用户B 来说 就是 一个 第三方模块
*
*
* 不管是 自定义/内置/第三方模块
*
* 在使用前, 一定要 将模块导入到当前文件内
* 第三方模块在导入前 还需要下载到本地项目中
*/
const fs = require('fs')
console.log(fs)
fs 模块
fs.readFile('读取的文件地址', '配置文件的格式(可以不传)', '一个回调函数, 读取完毕后会执行')
console.log('读取开始')
fs.readFile('./index.txt', (error, data) => {
if (error) {
console.log('读取错误: ', error)
return
}
console.log('读取成功: ', data)
})
fs.readFile('./index.txt', 'utf-8', (error, data) => {
if (error) {
console.log('读取错误: ', error)
return
}
console.log('读取成功: ', data)
})
console.log('读取结束')
console.log('读取开始')
const str = fs.readFileSync('./index.txt')
console.log(str)
const str = fs.readFileSync('./index.txt', 'utf-8')
console.log(str)
console.log('读取结束')
fs.writeFile('./index.txt', '我才是最新加入的一个文本, 2345678iugfxzsertyhb', () => {
console.log('写入文件完毕')
})
fs.appendFile('./index.txt', '我是一个新加入的文本', () => {})
* path 模块
*
* 帮助我们完成文件地址相关的操作
* 拼接路径
* 解析路径
*/
const path = require("path");
// console.log(path);
// 1. 拼接路径: 相对路径
// const baseUrl = path.join('a1', 'b2', 'c3', 'd/e/f/qwe.html')
// console.log(baseUrl) // a1\b2\c3\d\e\f\qwe.html
// 2. 拼接路径: 绝对路径
// const baseUrl = path.resolve('a1', 'b2', 'c3', 'd/e/f/qwe.html')
// console.log(baseUrl) // C:\Users\41099\Desktop\飞秋共享\BK_2310_2\07_周\05_天\code\a1\b2\c3\d\e\f\qwe.html
// const baseUrl = path.resolve('D:', 'a1', 'b2', 'c3', 'd/e/f/qwe.html')
// console.log(baseUrl) // D:\a1\b2\c3\d\e\f\qwe.html
// 3. 解析路径
const res = path.parse('C:/Users/41099/Desktop/飞秋共享/BK_2310_2/07_周/05_天/code/index.html')
console.log(res)
/*
{
root: 'C:/',
dir: 'C:/Users/41099/Desktop/飞秋共享/BK_2310_2/07_周/05_天/code',
base: 'index.html',
ext: '.html',
name: 'index'
}
*/
url 模块
const url = require('url')
// const res = url.parse('http://localhost:8888/cart.html?goodsId=10086&userId=10010')
// console.log(res)
/*
Url {
protocol: 'http:',
slashes: true,
auth: null,
host: 'localhost:8888',
port: '8888',
hostname: 'localhost',
hash: null,
search: '?goodsId=10086&userId=10010',
query: 'goodsId=10086&userId=10010',
pathname: '/cart.html',
path: '/cart.html?goodsId=10086&userId=10010',
href: 'http://localhost:8888/cart.html?goodsId=10086&userId=10010'
}
*/
/**
* url.parse 默认不会帮我们解析 url 中的 参数
*
* 除非使用这个方法的时候 给第二个参数传递一个 布尔值 true
*/
const res = url.parse('http://localhost:8888/cart.html?goodsId=10086&userId=10010', true)
console.log(res)
/*
Url {
....
query: [Object: null prototype] { goodsId: '10086', userId: '10010' },
....
}
*/
/**
* 初始搭建服务器
*
* 就是一个提供服务的机器, 比如说提供一些数据
*/
const http = require("http");
const server = http.createServer(() => {
console.log('当有人请求我的时候, 就会触发')
})
server.listen(8080, () => {
console.log('服务器启动成功~端口号为: 8080')
})
* 请求补充
*
* 1. 什么算请求
* * 浏览器地址栏内输入了地址, 敲下回车
* * 目前以浏览器为请求主体向 服务器发送了一个请求
* * 那么将来反馈的数据会反馈给浏览器
* * script link 标签中 我们可以通过一些属性 引入一些远程的 css 或者 js 文件
* * 目前是以标签为请求主体 向服务器发送了一个请求
* * 那么将来反馈的数据会反馈给 标签
* * ajax 请求
* * 此时是以 ajax 为请求主体, 向服务器发送了一个请求
* * 那么将来反馈的数据会反馈给 ajax
*
* 2. 请求的完整地址
* 假设我们目前所在的页面地址: http://localhost:8080/a/b/c/index.html
*
*
* 假设我们的 地址 是 './a/b.html'
* 完整地址: http://localhost:8080/a/b/c/a/b.html
*
*
* 假设我们的 地址 是 '../a/b.html'
* 完整地址: http://localhost:8080/a/b/a/b.html
*
*
*
* 假设我们的 地址 是 '/qwe/asd.html'
* 完整地址: http://localhost:8080/qwe/asd.html
*/
/**
* 服务器添加静态页面
*/
const http = require('http')
const fs = require('fs')
console.log('有人访问我~', res.end)
res.end('<h1>今天是周五</h1>')
res.end('<h1>qwertyui</h1>')
})
const server = http.createServer((req, res) => {
fs.readFile('./client/views/index.html', 'utf-8', (err, data) => {
if (err) return console.log(err)
res.end(data)
})
})
server.listen(8080, () => console.log('服务器启动成功~'))
1. client
- 存储一些静态资源 (html/css/js/png/jpg/jpeg.....)
2. node_modules
- 存储第三方模块, 我们不管什么时候都不要去内部修改代码
3. controller
- 内部专门存储接口处理的函数
- 当前文件夹内按照接口的分类, 创建对应的文件
- 比如: cart.js -> 内部专门存储 购物车相关的接口处理函数
- 比如: user.js -> 内部专门存储 用户相关的接口处理函数
- 比如: goods.js -> 内部专门存储 商品相关的接口处理函数
- ......
4. router
- 内部专门存储路由相关的路由表
- 比如: cart.js -> 内部专门存储 购物车相关的路由表
- 比如: user.js -> 内部专门存储 用户相关的路由表
- 比如: goods.js -> 内部专门存储 商品相关的路由表
- 比如: index.js -> 内部专门存储 路由总表
- ......
5. middleware
- 内部专门存储 请求中间件
- 比如: cart.js -> 内部专门存储 购物车相关的请求中间件
- 比如: user.js -> 内部专门存储 用户相关的请求中间件
- 比如: goods.js -> 内部专门存储 商品相关的请求中间件
- ......