01-初识Node(必学) - 图1

课程介绍

  • HTML + CSS (做网页)
  • JS基础 (JS基础语法、变量、数据类型、函数、流程控制、运算符……)
  • WebAPIs(使得JavaScript有能力操作页面元素)
  • JS高级(了解原型、类、正则、各种方法)
  • Ajax(能够发送请求,和服务器有交互。远程操作服务器的数据(看接口文档,写对应的代码))
  • Git(难学,首次使用终端窗口,必须要用使用的)
  • 数据可视化(对Ajax知识的综合应用,echarts,增强编程能力)
  • 项目前置课(查漏补缺的课,散乱的知识点比较多,对项目做准备)

    • 第1天:初识Node(了解Node是什么?能够干什么?简单的用一下;)
    • 第2天:包管理器(npm)
    • 第3天:ES6,Promise、事件循环
    • 第4天:了解写接口
    • 第5天:ES模块化 + Webpack
    • 第6天:Webpack、总结、Vue开始

      终端软件(了解)

      介绍

      可以执行命令的窗口,叫做终端软件
      作为程序员,开发时,都会大量使用命令(计算机系统相关命令,Git相关命令、Node命令等等)
      所以,就必须了解终端软件的使用。并且,系统不同,终端软件也不同

      已经用过的终端软件

      安装Git之后,鼠标右键,打开 “Git Bash Here”,打开的这个黑窗口就是一个终端软件。
      在里面可以执行Git命令,(建议大家在这个窗口中,只写Git命令)

      系统内置终端软件

  • Windows

    • cmd
      • 在文件夹地址栏的位置,输入cmd,回车即可打开
    • powershell
      • 在文件夹空白处,按住Shift,鼠标右键,选择“在此处打开powershell窗口”
  • Mac
    • 终端(可以安装 超级右键Lite)+ oh my zsh
    • 可以选择安装 hyper 或者 iterm2 这样的终端软件。

      这些终端软件中,都可以执行我们学习过的Git命令。

vscode中的终端

vscode中的终端,使用的也是系统内置的终端。没什么新鲜的,只不过把界面集成到了vscode中而已。

  • 点击vscode菜单栏(最上面一栏)中的“终端”,即可新建一个终端窗口。
  • 或者在侧边栏的文件上,鼠标右键,新建终端
  • 或者按快捷键 Ctrl + ~ 打开关闭终端。

    喜欢就用,不喜欢就算了。

cd命令

作为前端开发者,最常用的系统命令就是 cd 命令

  • c 是 change 的意思,切换的意思
  • d 是 directory 的意思,目录的意思

所以 cd 命令的作用是切换终端中的路径

  • cd / 切换到根目录
  • cd .. 切换到上层目录 (重点
  • cd xxx 切换到 xxx 目录 (重点

    终端使用技巧

  • 按 ↑ 找到曾经执行过的命令。按 ↓ 相反。

  • 按 tab 键,可以自动补全命令。
  • clear命令用于清屏。(cmd中使用cls命令清屏

    浏览器中的JavaScript

    浏览器中的JavaScript的组成部分

  • 浏览器中的JS

    • ECMAScript(核心语法)ES3 —> ES5 —> ES6(2015) —> ES2016 —>ES2017 …..
      • 变量、常量
      • 数据类型
      • 函数
      • 流程控制(if、switch、for、while、for…in、continue、break)
      • 运算符
      • JS内置对象(Array、String、RegExp、Date、Math….)
    • WebAPI (浏览器提供的API
      • DOM(文档对象模型,document)
      • BOM(浏览器对象模型,location、history、….)
      • XMLHttpRequest
      • Canvas
      • URL
      • 为什么JavaScript 可以在浏览器中被执行

        image.png
        浏览器内核
  • 浏览器内核 包括 CSS解析引擎,包括 JS解析引擎

  • 目前,JS解析引擎基本上从内核中独立出来了
  • 所以,平时所说的浏览器内核一般和CSS有关系

不同的浏览器使用不同的 JavaScript 解析引擎:

  • Chrome 浏览器 => V8
  • Firefox 浏览器=> OdinMonkey(奥丁猴)
  • Safri 浏览器=> JSCore
  • IE 浏览器=> Chakra(查克拉)
  • etc…

其中,Chrome 浏览器的 V8 解析引擎性能最好!

浏览器中的 JavaScript 运行环境

  • 运行环境指的是代码正常运行所需的必要条件。
  • V8 引擎负责解析和执行 JavaScript 代码。
  • 内置 API 是由运行环境提供的特殊接口,只能在所属的运行环境中被调用。

目前为止,浏览器是我们已知的唯一一个JS的运行环境

Node.js简介

JavaScript 能否做后端开发

image.png

Node.js 的出现,使得JavaScript有了做后端开发的能力。

Node.js可以做什么

Node.js 作为一个 JavaScript 的运行环境,仅仅提供了基础的功能和 API。然而,基于 Node.js 提供的这些基础功能,很多强大 的工具和框架如雨后春笋,层出不穷,所以学会了 Node.js ,可以让前端程序员胜任更多的工作和岗位!

总之,Node.js 是大前端时代的“大宝剑”,有了 Node.js 这个超级 buff 的加持,前端程序员的行业竞争力会越来越强!

什么是 Node.js

Node.js® is a JavaScript runtime built on Chrome’s V8 JavaScript engine.
Node.js 一个基于 Chrome V8 引擎的 JavaScript 运行环境
通俗的理解:Node.js 为 JavaScript 代码的正常运行,提供的必要的环境。
Node.js 的官网地址: https://nodejs.org/zh-cn/

Node.js中的JavaScript运行环境

image.png
注意:

  • 浏览器是 JavaScript 的前端运行环境。(浏览器是客户端安装的软件)
  • Node.js 是 JavaScript 的后端运行环境。(正常情况下,Nodejs要安装到服务器上)
  • Node.js 中无法调用 DOM 和 BOM 等 浏览器内置 API。

image.png
总结起来:

  1. Node是JS的另一个运行环境。
  2. 在Node环境中,可以运行ECMAScript语法,但不能运行 WebAPI的语法

    Node.js环境安装

    下载安装

    如果希望通过 Node.js 来运行 Javascript 代码,则必须在计算机上安装 Node.js 环境才行。
    安装包可以从 Node.js 的官网首页直接下载,进入到 Node.js 的官网首页,点 击绿色的按钮,下载所需的版本后,双击直接安装即可。
    进入官网(中文),可以看到如下两个版本:
    image.png
  • LTS 为长期稳定版,对于追求稳定性的企业级项目来说,推荐安装 LTS 版本。
  • Current 为新特性尝鲜版,对于热衷于尝试新特性的用户来说,推荐安装 Current 版本的 Node.js。但是,Current 版本 中可能存在隐藏的 Bug 或安全性漏洞,因此不推荐在企业级项目中使用 Current 版本的 Node.js。

    建议使用 长期支持版

查看已安装的Node.js的版本号

打开终端(黑窗口,或者蓝窗口),在终端输入命令 node –v 后,按下回车键,即可查看已安装的 Node.js 的版本号。

如果你能够看到版本号,说明你已经安装成功了。

在Node.js环境中运行JavaScript

终端窗口运行(了解)

此种方式,类似于浏览器调试工具的“Console”面板,只适合运行少量的测试代码,所以了解即可。
操作步骤:

  • 打开任意终端,直接输入 node 命令并回车
  • 执行你的JS代码,按回车表示执行
  • 按两次“Ctrl+C”退出。

    使用node命令执行JS文件(掌握)

    此种方式,比较常用。可以运行写到 “xx.js” 里面的JS代码,可以运行JS文件中的代码。
    操作步骤:

  • 打开终端

  • 注意终端的路径,注意在此路径中,是否能找到你的js文件。
  • 输入 “node 要执行的js文件”回车表示运行
  • 执行文件的时候,需要保证 node xxx.js 这种格式
  • node只能运行JS代码(也就是不要 node xxx.html)

可能的问题

  • 如果终端中出现 >,按两次“Ctrl+C”退出
  • 不能使用node运行html、css等等代码
  • 不能在node环境中运行WebAPI的代码,比如document
  • JS文件名,不能叫做 node.js

    模块化介绍

    什么是模块化

    模块化,就是把一个大的文件拆分成若干小文件,而且还能把小文件通过特定的语法组合到一起的实现过程。
    比如手机、电脑….等等几乎所有,都是模块化的设计,拿电脑来说,可以把电脑拆分成显示器、键盘、硬盘、内存等一个一个的小模块,当然也能够组装到一起。

    优点

    模块化的优势:

  • 更利于维护(比如电脑屏幕坏了,只换屏幕就可以了;比如想升级显卡,只换显卡就行了);

  • 更好的复用性(比如有一块移动硬盘或U盘,大家都能用)

Node中,规定每个JS文件都是一个小模块。一个项目由许许多多的小模块(JS文件)组合而成。
Node中模块化的优势:

  • 更利于维护(比如,项目需要对登录模块升级,则不会影响其他模块)
  • 更好的复用性(比如有一个公共的函数,封装起来。其他所有JS文件都能使用这个函数)

    自定义模块

    我们创建的每个JS文件都是一个自定义模块,并且具有模块作用域,也就是在一个模块中创建的变量、常量、函数等等一切,都只能在当前模块中使用。

  • 共享(导出/暴露)内容给其他模块用,需要使用 module.exports 导出内容。

    • module 是Node中的一个全局对象,对象包含当前模块的详细信息。
    • module.exports 是模块的出口,通俗的说,就是导出内容用的,默认值是 {}
    • 比如,02-test.js 导出 age、name、fn 给其他模块用,可以 module.exports = {age, name, fn}
  • 其他模块,如果需要使用上述模块导出的内容,可以使用 require() 加载
    • let 结果 = require('模块路径')
    • 比如,let test = require('./02-test');
    • 加载自定义模块,必须加路径,即使是 ./ 也必须加。但是可以省略后缀。

示例:
functions.js — 导出内容

  1. // 这是我的函数库
  2. function aa() {
  3. console.log(111)
  4. }
  5. function bb() {
  6. console.log(222)
  7. }
  8. // aa、bb,默认只能在functions.js中使用
  9. // aa、bb,属于当前这个模块
  10. // 如果想把aa、bb给其他模块使用,则需要先”分享”
  11. // 【分享】,也叫做【导出】、或者【暴露】
  12. // 语法:module.exports = 导出的内容
  13. // module.exports = {} // 每个模块,默认导出空对象
  14. module.exports = { aa, bb }

index.js — 导入内容

  1. // 怎么在这里调用 functions.js 中的函数???
  2. // 想使用其他js文件中的函数,需要导入
  3. // 导入的语法,也是一行代码
  4. // 导入的语法:1. 必须带路径,即使是 ./ 也不能省略; 2. 可以省略后缀
  5. let obj = require('./functions')
  6. // console.log(obj)
  7. obj.aa()
  8. obj.bb()

一个模块导出什么,另一个模块加载后,就会得到什么。 就比如,我给你三个苹果,你只能得到三个苹果,不可能得到其他的。

模块的分类

  • 自定义模块
    • NodeJS中,创建的JS文件都是自定义模块。(也就是处处皆模块)
    • 需要自己通过 module.exports = 内容 导出
    • 需要自己通过 let 变量 = require('**./**文件名') 导入 (注意路径不能丢)
  • 内置模块(核心模块)
    • 安装Node之后,自带了很多内置模块。我们可以直接加载使用他们 。
    • 官方已经导出,我们只需要导入即可:let 变量 = require('**模块名**') (直接写模块名)
  • 第三方模块

    • 其他人编写的模块,发布到 npm 网站 上,我们可以下载使用。
    • 别人已经导出,我们只需要导入即可:let 变量 = require('**模块名**') (直接写模块名)

      内置模块

      内置模块是Node.js 平台自带的一套基本的 API(功能模块)。也叫做核心模块。
      下面介绍几个内置模块。
      注意,加载内置模块,不能写路径,这是和加载自定义模块不一样的。

      path模块

  • path 是 Node 本身提供的 API,专门用来处理路径。

  • http://nodejs.cn/api/path.html
  • 使用

    • 加载模块

      1. // 使用核心模块之前,首先加载核心模块
      2. let path = require('path');
      3. // 或者
      4. const path = require('path');
    • 调用path模块中的方法,来处理相应的问题,下面列举path模块中的几个方法
      | 方法 | 作用 | | —- | —- | | path.basename(path[, ext]) | 返回 path 的最后一部分(文件名) | | path.dirname(path) | 返回目录名 | | path.extname(path) | 返回路径中文件的扩展名(包含.) | | path.format(pathObject) | 将一个对象格式化为一个路径字符串 | | path.join([…paths]) | 拼接路径 | | path.parse(path) | 把路径字符串解析成对象的格式 | | path.resolve([…paths]) | 基于当前工作目录拼接路径 |

  1. // 我现在要使用官方提供的 path 模块
  2. // 用法一:先加载模块,得到对象; 然后再 ”对象.方法()”
  3. // let path = require('path') // 导入内置模块,直接写模块名
  4. // // console.log(path) // { resolve: ..., join: ...., basename: ...., extname: ....., ..... }
  5. // console.log(path.join('a', 'b', 'c', 'index.js')) // a/b/c/index.js
  6. // 用法二:先加载模块,得到对象; 直接把需要的方法解构出来;最后直接使用方法即可
  7. let { join } = require('path')
  8. // node官方提供的join方法,作用是拼接几部分路径
  9. // console.log(join('a', 'b', 'c')) // a/b/c
  10. // console.log(join('a', 'b', '../c', 'index.js')) // a/c/index.js
  11. // console.log(__dirname) // node中的一个全局变量,表示当前js文件的绝对路径(不包括文件名部分)
  12. // 拼接一下,得到db.js的绝对路径
  13. console.log(join(__dirname, 'index.js'))
  14. // D:/147-148-金燕龙/项目前置课-01/课堂代码/index.js

这里有用的代码,就一行:
join(__dirname, 'xxx')

fs模块

  • fs,即 file system,文件系统,该模块可以实现对 文件、文件夹的操作
  • http://nodejs.cn/api/fs.html
  • 使用

    • 加载模块

      1. // 引入模块,引入模块的时候,可以使用var、let,但是建议使用const,因为我们不希望它改变
      2. const fs = require('fs');
    • 调用fs模块的方法,下面列举fs模块中的常用方法
      | API | 作用 | 备注 | | —- | —- | —- | | fs.access(path, callback) | 判断路径是否存在 | | | fs.appendFile(file, data, callback) | 向文件中追加内容 | | | fs.copyFile(src, callback) | 复制文件 | | | fs.mkdir(path, callback) | 创建目录 | | | fs.readDir(path, callback) | 读取目录列表 | | | fs.rename(oldPath, newPath, callback) | 重命名文件/目录 | | | fs.rmdir(path, callback) | 删除目录 | 只能删除空目录 | | fs.stat(path, callback) | 获取文件/目录信息 | | | fs.unlink(path, callback) | 删除文件 | | | fs.watch(filename[, options][, listener]) | 监视文件/目录 | | | fs.watchFile(filename[, options], listener) | 监视文件 | | | ….. 一大堆 | | |

  1. // fs -- file system 文件系统
  2. // fs 模块处理的问题,都和文件、文件夹相关
  3. // 比如:获取某个文件里面的内容
  4. // 比如:把一些内容放到某个文件中
  5. // 比如:创建文件
  6. // 比如:创建文件夹
  7. // 比如:读取文件夹里面的全部文件
  8. // 比如:删除文件、文件夹
  9. // 比如:监视文件的变化
  10. // .......
  11. // 我们学习两个方法:
  12. // 1. readFile() ---- 异步读取文件(获取文件里面的内容)
  13. // 2. writeFile() --- 异步写入文件(把内容添加到文件里面)
  14. // 首先,加载fs模块,并把我们需要的 两个方法解构出来
  15. let { readFile, writeFile } = require('fs')
  16. // ------------------------------ readFile -----------------------------
  17. // 作用:读取文件(获取文件里面的内容)
  18. // 语法:
  19. /**
  20. * readFile('文件路径', '可选的utf-8', (err, data) => {
  21. * err表示错误信息(如果读取发生了错误【err=错误对象】;如果没有错误【err=null】)
  22. * data表示读取的结果
  23. * })
  24. */
  25. // readFile('05.txt', 'utf-8', (err, data) => {
  26. // // throw专门用于抛出错误,可以理解为输出错误;遇到throw语句还会终止代码的执行,有return的特点
  27. // if (err) throw err
  28. // console.log(data)
  29. // })
  30. // --------------------------- writeFile ------------------------------
  31. // 作用:写入文件(向文件中,添加内容)
  32. // 语法:
  33. /**
  34. * writeFile('文件', '字符串内容', err => {
  35. * 有错误发生【err=错误对象】; 没有错误【err=null】
  36. * })
  37. */
  38. // 特点:
  39. // 1. 如果文件不存在,会自动创建文件(但是不会递归创建)
  40. // 2. 如果文件存在,并且里面有内容;写入的新内容会把原来的内容覆盖
  41. writeFile('06.txt', '1234567890', err => {
  42. if (err) throw err
  43. console.log('写入成功')
  44. })

练习-对JSON数据进行处理

准备JSON数据

创建 books.json 文件,内容如下:

  1. [
  2. { "bookname": "史记", "author": "司马迁", "publisher": "北京出版社", "id": 3 },
  3. { "bookname": "遮天", "author": "辰东", "publisher": "仙侠出版社", "id": 5 },
  4. { "bookname": "西游记", "author": "吴承恩", "publisher": "北京出版社", "id": 6 },
  5. { "bookname": "JS权威指南", "author": "王宁", "publisher": "上海出版社", "id": 9 }
  6. ]

代码准备

创建json-parser.js ,里面封装并导出4个函数:

  1. // json-parser.js
  2. // 1. 准备工作(加载所需的模块,所需的方法,把 books.json 的绝对路径拼接好)
  3. const { join } = require('path')
  4. const { readFile, writeFile } = require('fs')
  5. // 得到books.json的绝对路径
  6. const filename = join(__dirname, 'books.json')
  7. // --------------------------- query() - 查询books.json里面的数据 ------------------------
  8. function query() {
  9. console.log(123)
  10. }
  11. // --------------------------- add() - 向 books.json中添加一本书 ------------------------
  12. function add() {}
  13. // --------------------------- del() - 从 books.json中删除一本书 ------------------------
  14. function del() {}
  15. // --------------------------- update() - 修改 books.json中的一本书 ------------------------
  16. function update() {}
  17. // 导出4个函数
  18. module.exports = { query, add, del, update }

创建一个 test.js ,导入上述四个函数,用于测试

  1. // 希望在test.js中,调用 json-parser.js 中封装的四个函数
  2. // let obj = require('./json-parser')
  3. // obj.query()
  4. let { query, add, del, update } = require('./json-parser')
  5. query()

query-读取数据

  1. // --------------------------- query() - 查询books.json里面的数据 ------------------------
  2. function query() {
  3. readFile(filename, 'utf-8', (err, data) => {
  4. if (err) throw err
  5. // 无论读取什么文件,得到的都是字符串(读取js文件、css文件、json文件等等,结果都是字符串)
  6. let arr = JSON.parse(data)
  7. console.log(arr)
  8. })
  9. }
  10. // 在test.js 中,调用query()

add-添加数据

  1. // --------------------------- add() - 向 books.json中添加一本书 ------------------------
  2. function add(obj) {
  3. // 准备新增的图书是 obj
  4. // 1. 先取出原来的图书,转成数组
  5. readFile(filename, 'utf-8', (err, data) => {
  6. if (err) throw err
  7. let arr = JSON.parse(data) // 把读取的结果转成数组
  8. // 2. 把新书加入到数组中(需要先计算新书的id)
  9. obj.id = arr[arr.length - 1].id + 1
  10. arr.push(obj)
  11. // console.log(arr)
  12. // 3. 把全部的图书,重新存入books.json
  13. writeFile(filename, JSON.stringify(arr), err => {
  14. if (err) throw err
  15. console.log('添加成功')
  16. })
  17. })
  18. }
  19. // 在test.js 中,调用函数add,并传递参数
  20. add({ bookname: '三国', author: '罗贯中', publisher: '北京出版社' })

del-删除数据

  1. // --------------------------- del() - 从 books.json中删除一本书 ------------------------
  2. function del(id) {
  3. // id = 9,要删除id=9的这本书
  4. // 1. 先读取books.json。转成数组
  5. readFile(filename, 'utf-8', (err, data) => {
  6. if (err) throw err
  7. let arr = JSON.parse(data)
  8. // console.log(arr)
  9. // 2. 根据id删除一本书(根据id条件,从数组中删除一个元素)
  10. let res = arr.filter(item => item.id != id)
  11. // 3. 把剩余的重新存起来
  12. writeFile(filename, JSON.stringify(res), err => {
  13. if (err) throw err
  14. console.log('删除成功')
  15. })
  16. })
  17. }
  18. // 在 test.js 中,调用函数,测试
  19. del(2)

update-修改数据

  1. // 调用函数,能够把数据修改了
  2. function update(obj) {
  3. // 思路:先把图书取出来 ==> 修改数组中的一条数据 ==> 把修改后的结果重新存起来
  4. readFile(filename, 'utf-8', (err, data) => {
  5. if (err) throw err
  6. let arr = JSON.parse(data)
  7. // console.log(arr)
  8. // 找到下标
  9. let i = arr.findIndex(item => item.id == obj.id)
  10. // 使用splice方法,从下标的位置,删除1条,然后把传入的新书加入
  11. arr.splice(i, 1, obj)
  12. writeFile(filename, JSON.stringify(arr), err => {
  13. if (err) throw err
  14. console.log('修改成功')
  15. })
  16. })
  17. }
  18. // 在test.js中,调用函数测试
  19. update({ id: 7, bookname: '朝花夕拾', author: '鲁迅', publisher: '商务出版社' })

小结

  • 练习任何一个方法之前,先把 books.json 数据处理好,要保证json数据是没问题的才行。
  • 练习某个方法的时候,把其他方法先注释了(把调用注释即可)
    • readFile() 和 writeFile() 是异步方法。
    • 多个异步任务,如果同时执行,不能保证顺序了
  • 涉及到的重点方法:push、filter、findIndex、splice、sort,去 MDN 查。

End