vue3学习笔记

文章目录

  • ES6模块化与异步编程高级用法
    • 1. ES6 模块化
      • 1.1 node.js 中如何实现模块化
      • 1.2 前端模块化规范的分类
      • 1.3 什么是 ES6 模块化规范
      • 1.4 在 node.js 中体验 ES6 模块化
      • 1.5 ES6 模块化的基本语法
        • 1. 默认导出
        • 2. 默认导入
        • 3. 默认导出的注意事项
        • 4. 默认导入的注意事项
        • 5. 按需导出
        • 6. 按需导入
        • 7. 按需导出与按需导入的注意事项
        • 8. 直接导入并执行模块中的代码
    • 2. Promise
      • 2.1 回调地狱
        • 1. 如何解决回调地狱的问题
        • 2. Promise 的基本概念
      • 2.2 基于回调函数按顺序读取文件内容
      • 2.3 基于 then-fs 读取文件内容
        • 1. then-fs 的基本使用
        • 2. .then() 方法的特性
        • 3. 基于 Promise 按顺序读取文件的内容
        • 4. 通过 .catch 捕获错误1
        • 5. 通过 .catch 捕获错误2
        • 6. Promise.all() 方法
        • 7. Promise.race() 方法
      • 2.4 基于 Promise 封装读文件的方法
        • 1. getFile 方法的基本定义
        • 2. 创建具体的异步操作
        • 3. 获取 .then 的两个实参
        • 4. 调用 resolve 和 reject 回调函数
    • 3. async/await
      • 3.1 什么是 async/await
      • 3.2 async/await 的基本使用
      • 3.3 async/await 的使用注意事项
    • 4. EventLoop
      • 4.1 JavaScript 是单线程的语言
      • 4.2 同步任务和异步任务
      • 4.3 同步任务和异步任务的执行过程
      • 4.4 EventLoop 的基本概念
      • 4.5 结合 EventLoop 分析输出的顺序
    • 5. 宏任务和微任务
      • 5.1 什么是宏任务和微任务
      • 5.2 宏任务和微任务的执行顺序
      • 5.3 去银行办业务的场景
      • 5.4 分析以下代码输出的顺序
      • 5.5 经典面试题
    • 6. API 接口案例
      • 6.1 案例需求
      • 6.2 主要的实现步骤
      • 6.3 搭建项目的基本结构
      • 6.4 创建基本的服务器
      • 6.5 创建 db 数据库操作模块
      • 6.6 创建 user_ctrl 模块
      • 6.7 创建 user_router 模块
      • 6.8 导入并挂载路由模块
      • 6.9 使用 try…catch 捕获异常
    • 7. 总结
  • 组件(上)
    • 1. 单页面应用程序
      • 1.1 单页面应用程序的优点
      • 1.2 单页面应用程序的缺点
      • 1.3 如何快速创建 vue 的 SPA 项目
    • 2. vite 的基本使用
      • 2.1 创建 vite 的项目
      • 2.2 梳理项目的结构
        • 1. 梳理项目的结构
      • 2.3 vite 项目的运行流程
        • 1. 在 App.vue 中编写模板结构
        • 2. 在 index.html 中预留 el 区域
        • 3. 在 main.js 中进行渲染
    • 3. 组件化开发思想
      • 3.1 什么是组件化开发
      • 3.2 组件化开发的好处
      • 3.3 vue 中的组件化开发
    • 4. vue 组件的构成
      • 4.1 vue 组件组成结构
      • 4.2 组件的 template 节点
        • 1. 在 template 中使用指令
        • 2. 在 template 中定义根节点
      • 4.3 组件的 script 节点
        • 1. script 中的 name 节点
        • 2. script 中的 data 节点
        • 3. 组件中的 data 必须是函数
        • 4. script 中的 methods 节点
      • 4.4 组件的 style 节点
        • 1. 让 style 中支持 less 语法
    • 5. 组件的基本使用
      • 5.1 组件的注册
        • 1. 注册组件的两种方式
        • 2. 全局注册组件
        • 3. 使用全局注册组件
        • 4. 局部注册组件
        • 5. 全局注册和局部注册的区别
        • 6. 组件注册时名称的大小写
        • 7. 通过 name 属性注册组件
      • 5.2 组件之间的样式冲突问题
        • 1. 如何解决组件样式冲突的问题
        • 2. style 节点的 scoped 属性
        • 3. /deep/ 样式穿透
      • 5.3 组件的 props
        • 1. 什么是组件的 props
        • 2. 在组件中声明 props
        • 3. 无法使用未声明的 props
        • 4. 动态绑定 props 的值
        • 5. props 的大小写命名
      • 5.4 Class 与 Style 绑定
        • 1. 动态绑定 HTML 的 class
        • 2. 以数组语法绑定 HTML 的 class
        • 3. 以对象语法绑定 HTML 的 class
        • 4. 以对象语法绑定内联的 style
    • 6. 总结
  • 组件(下)
    • 1. props 验证
      • 1.1 什么是 props 验证
      • 1.2 对象类型的 props 节点
      • 1.3 props 验证
        • 1. 基础的类型检查
        • 2. 多个可能的类型
        • 3. 必填项校验
        • 4. 属性默认值
        • 5. 自定义验证函数
    • 2. 计算属性
      • 2.1 什么是计算属性
      • 2.2 如何声明计算属性
      • 2.3 计算属性的使用注意点
      • 2.4 计算属性 vs 方法
    • 3. 自定义事件
      • 3.1 什么是自定义事件
      • 3.2 自定义事件的 3 个使用步骤
        • 1. 声明自定义事件
        • 2. 触发自定义事件
        • 3. 监听自定义事件
      • 3.3 自定义事件传参
    • 4. 组件上的 v-model
      • 4.1 为什么需要在组件上使用 v-model
      • 4.2 在组件上使用 v-model 的步骤
    • 5. 总结
  • 组件高级(上)
    • 1. watch 侦听器
      • 1.1 什么是 watch 侦听器
      • 1.2 watch 侦听器的基本语法
      • 1.3 使用 watch 检测用户名是否可用
      • 1.4 immediate 选项
      • 1.5 deep 选项
      • 1.6 监听对象单个属性的变化
      • 1.7 计算属性 vs 侦听器
    • 2. 组件的生命周期
      • 2.1 组件运行的过程
      • 2.2 如何监听组件的不同时刻
      • 2.3 如何监听组件的更新
      • 2.4 组件中主要的生命周期函数
      • 2.5 组件中全部的生命周期函数
      • 2.6 完整的生命周期图示
    • 3. 组件之间的数据共享
      • 3.1 组件之间的关系
      • 3.2 父子组件之间的数据共享
        • 1. 父组件向子组件共享数据
        • 2. 子组件向父组件共享数据
        • 3. 父子组件之间数据的双向同步
      • 3.3 兄弟组件之间的数据共享
        • 1. 安装 mitt 依赖包
        • 2. 创建公共的 EventBus 模块
        • 3. 在数据接收方自定义事件
        • 4. 在数据接发送方触发事件
      • 3.4 后代关系组件之间的数据共享
        • 1. 父节点通过 provide 共享数据
        • 2. 子孙节点通过 inject 接收数据
        • 3. 父节点对外共享响应式的数据
        • 4. 子孙节点使用响应式的数据
      • 3.5 vuex
      • 3.6 总结
    • 4. vue 3.x 中全局配置 axios
      • 4.1 为什么要全局配置 axios
      • 4.2 如何全局配置 axios
      • 5. 总结
  • 组件高级下
    • 1. ref 引用
      • 1.1 什么是 ref 引用
      • 1.2 使用 ref 引用 DOM 元素
      • 1.3 使用 ref 引用组件实例
      • 1.4 控制文本框和按钮的按需切换
      • 1.5 让文本框自动获得焦点
      • 1.6 this.$nextTick(cb) 方法
    • 2. 动态组件
      • 2.1 什么是动态组件
      • 2.2 如何实现动态组件渲染
      • 2.3 使用 keep-alive 保持状态
    • 3. 插槽
      • 3.1 什么是插槽
      • 3.2 体验插槽的基础用法
        • 1. 没有预留插槽的内容会被丢弃
        • 2. 后备内容
      • 3.3 具名插槽
      • 3.4 作用域插槽
        • 1. 解构作用域插槽的 Prop
        • 2. 声明作用域插槽
        • 3. 使用作用域插槽
    • 4. 自定义指令
      • 4.1 什么是自定义指令
      • 4.2 声明私有自定义指令的语法
      • 4.3 使用自定义指令
      • 4.4 声明全局自定义指令的语法
      • 4.5 updated 函数
      • 4.6 函数简写
      • 4.7 指令的参数值
    • 5. 总结
  • 路由
    • 1. 前端路由的概念与原理
      • 1.1 什么是路由
      • 1.2 回顾:后端路由
      • 1.3 SPA 与前端路由
      • 1.4 什么是前端路由
      • 1.5 前端路由的工作方式
      • 1.6 实现简易的前端路由
        • 1. 步骤1
        • 2. 步骤2
        • 3. 步骤3
        • 4. 步骤4
    • 2. vue-router 的基本使用
      • 2.1 什么是 vue-router
      • 2.2 vue-router 的版本
      • 2.3 vue-router 4.x 的基本使用步骤
        • 1. 在项目中安装 vue-router
        • 2. 定义路由组件
        • 3. 声明路由链接和占位符
        • 4. 创建路由模块
      • 2.4 从 vue-router 中按需导入两个方法
      • 2.5 导入需要使用路由控制的组件
      • 2.6 创建路由实例对象
      • 2.7 向外共享路由实例对象
      • 2.8 在 main.js 中导入并挂载路由模块
    • 3. vue-router 的高级用法
      • 3.1 路由重定向
      • 3.2 路由高亮
        • 1. 默认的高亮 class 类
        • 2. 自定义路由高亮的 class 类
      • 3.3 嵌套路由
        • 1. 声明子路由链接和子路由占位符
        • 2. 通过 children 属性声明子路由规则
      • 3.4 动态路由匹配
        • 1. 动态路由的概念
        • 2. $route.params 参数对象
        • 3. 使用 props 接收路由参数
      • 3.5 编程式导航
        • 1. vue-router 中的编程式导航 API
        • 2. $router.push
        • 2. $router.go
      • 3.6 命名路由
        • 1. 使用命名路由实现声明式导航
        • 2. 使用命名路由实现编程式导航
      • 3.7 导航守卫
        • 1. 如何声明全局导航守卫
        • 2. 守卫方法的 3 个形参
        • 3. next 函数的 3 种调用方式
        • 4. 结合 token 控制后台主页的访问权限
    • 4. 总结
  • VUE 基础 - 综合案例
    • 1. vue-cli
      • 1.1 什么是 vue-cli
      • 1.2 安装 vue-cli
        • 1. 解决 Windows PowerShell 不识别 vue 命令的问题
      • 1.3 创建项目
      • 1.4 基于 vue ui 创建 vue 项目
        • 1. 步骤1
        • 2. 步骤2
        • 4. 步骤3
        • 4. 步骤4
        • 5. 步骤5
        • 6. 步骤6
        • 7. 步骤7
        • 8. vue ui 的本质
        • 9. 项目创建完成后,自动进入项目仪表盘
      • 1.5 基于命令行创建 vue 项目
      • 1.6 梳理 vue2 项目的基本结构
      • 1.7 分析 main.js 中的主要代码
      • 1.8 在 vue2 的项目中使用路由
        • 1. 回顾:4.x 版本的路由如何创建路由模块
        • 2. 学习:3.x 版本的路由如何创建路由模块
    • 2. 组件库
      • 2.1 什么是 vue 组件库
      • 2.2 vue 组件库和 bootstrap 的区别
      • 2.3 最常用的 vue 组件库
      • 2.4 Element UI
        • 1. 在 vue2 的项目中安装 element-ui
        • 2. 引入 element-ui
        • 3. 完整引入
        • 4. 按需引入
      • 2.5 把组件的导入和注册封装为独立的模块
    • 3. axios 拦截器
      • 3.1 回顾:在 vue3 的项目中全局配置 axios
      • 3.2 在 vue2 的项目中全局配置 axios
      • 3.3 什么是拦截器
      • 3.4 配置请求拦截器
        • 1. 请求拦截器 – Token 认证
        • 2. 请求拦截器 – 展示 Loading 效果
      • 3.5 配置响应拦截器
        • 1. 响应拦截器 – 关闭 Loading 效果
    • 4. proxy 跨域代理
      • 4.1 回顾:接口的跨域问题
      • 4.2 通过代理解决接口的跨域问题
      • 4.3 在项目中配置 proxy 代理
    • 5. 总结
      • 3.2 在 vue2 的项目中全局配置 axios
      • 3.3 什么是拦截器
      • 3.4 配置请求拦截器
        • 1. 请求拦截器 – Token 认证
        • 2. 请求拦截器 – 展示 Loading 效果
      • 3.5 配置响应拦截器
        • 1. 响应拦截器 – 关闭 Loading 效果
    • 4. proxy 跨域代理
      • 4.1 回顾:接口的跨域问题
      • 4.2 通过代理解决接口的跨域问题
      • 4.3 在项目中配置 proxy 代理
    • 5. 总结


ES6模块化与异步编程高级用法

1. ES6 模块化

1.1 node.js 中如何实现模块化

node.js 遵循了 CommonJS 的模块化规范。其中:

  • 导入其它模块使用 require() 方法
  • 模块对外共享成员使用 module.exports 对象

模块化的好处:

大家都遵守同样的模块化规范写代码,降低了沟通的成本,极大方便了各个模块之间的相互调用,利人利己。

1.2 前端模块化规范的分类

在 ES6 模块化规范诞生之前,JavaScript 社区已经尝试并提出了 AMD、CMD、CommonJS 等模块化规范。

但是,这些由社区提出的模块化标准,还是存在一定的差异性与局限性、并不是浏览器与服务器通用的模块化标准,例如:

  • AMD 和 CMD 适用于浏览器端的 Javascript 模块化
  • CommonJS 适用于服务器端的 Javascript 模块化

太多的模块化规范给开发者增加了学习的难度与开发的成本。因此,大一统的 ES6 模块化规范诞生了!

1.3 什么是 ES6 模块化规范

ES6 模块化规范浏览器端服务器端通用的模块化开发规范。它的出现极大的降低了前端开发者的模块化学习成本,开发者不需再额外学习 AMD、CMD 或 CommonJS 等模块化规范。

ES6 模块化规范中定义:

  • 每个 js 文件都是一个独立的模块
  • 导入其它模块成员使用 import 关键字
  • 向外共享模块成员使用 export 关键字

1.4 在 node.js 中体验 ES6 模块化

node.js 中默认仅支持 CommonJS 模块化规范,若想基于 node.js 体验与学习 ES6 的模块化语法,可以按照如下两个步骤进行配置:

​ ① 确保安装了 v14.15.1 或更高版本的 node.js

​ ② 在 package.json 的根节点中添加 “type”: “module” 节点

1.5 ES6 模块化的基本语法

ES6 的模块化主要包含如下 3 种用法:

​ ① 默认导出默认导入

​ ② 按需导出按需导入

​ ③ 直接导入执行模块中的代码

1. 默认导出

默认导出的语法: export default 默认导出的成员

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1D3419Gt-1650958972713)(D:\A_study\Vue\vue3_study_image\a1.png)]

2. 默认导入

默认导入的语法: import 接收名称 from '模块标识符'

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0oIJfr8I-1650958972714)(D:\A_study\Vue\vue3_study_image\a2.png)]

3. 默认导出的注意事项

每个模块中,只允许使用唯一的一次 export default,否则会报错!

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-t6vO6NM8-1650958972715)(D:\A_study\Vue\vue3_study_image\a3.png)]

4. 默认导入的注意事项

默认导入时的接收名称可以任意名称,只要是合法的成员名称即可:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Z1VDU6VA-1650958972715)(D:\A_study\Vue\vue3_study_image\a4.png)]

5. 按需导出

按需导出的语法: export 按需导出的成员

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-51gd3J15-1650958972716)(D:\A_study\Vue\vue3_study_image\a5.png)]

6. 按需导入

按需导入的语法: import { s1 } from '模块标识符'

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lSYoDKml-1650958972716)(D:\A_study\Vue\vue3_study_image\a6.png)]

7. 按需导出与按需导入的注意事项

​ ① 每个模块中可以使用多次按需导出

​ ② 按需导入的成员名称必须和按需导出的名称保持一致

​ ③ 按需导入时,可以使用 as 关键字进行重命名

​ ④ 按需导入可以和默认导入一起使用

8. 直接导入并执行模块中的代码

如果只想单纯地执行某个模块中的代码,并不需要得到模块中向外共享的成员。此时,可以直接导入并执行模块代码,示例代码如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-X6VXbEG7-1650958972717)(D:\A_study\Vue\vue3_study_image\a7.png)]

2. Promise

2.1 回调地狱

多层回调函数的相互嵌套,就形成了回调函数。示例代码如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qu9ND88m-1650958972717)(D:\A_study\Vue\vue3_study_image\a8.png)]

1. 如何解决回调地狱的问题

为了解决回调函数的问题,ES6(ECMAScript 2015)中新增了 Promise 的概念。

2. Promise 的基本概念

Promise 是一个构造函数

  • 我们可以创建 Promise 的实例 const p = new Promise()
  • new 出来的 Promise 实例对象,代表一个异步操作

② Promise.prototype 上包含一个 .then() 方法

  • 每一次 new Promise() 构造函数得到的实例对象,
  • 都可以通过原型链的方式访问到 .then() 方法,例如 p.then()

③ .then() 方法用来预先指定成功和失败的回调函数

  • p.then(成功的回调函数,失败的回调函数)
  • p.then(result => { }, error => { })
  • 调用 .then() 方法时,成功的回调函数是必选的、失败的回调函数是可选的

2.2 基于回调函数按顺序读取文件内容

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EBZF2uTy-1650958972718)(D:\A_study\Vue\vue3_study_image\a9.png)]

2.3 基于 then-fs 读取文件内容

由于 node.js 官方提供的 fs 模块仅支持以回调函数的方式读取文件,不支持 Promise 的调用方式。因此,需要先运行如下的命令,安装 then-fs 这个第三方包,从而支持我们基于 Promise 的方式读取文件的内容:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YZJXwKvj-1650958972718)(D:\A_study\Vue\vue3_study_image\a10.png)]

1. then-fs 的基本使用

调用 then-fs 提供的 readFile() 方法,可以异步地读取文件的内容,它的返回值是 Promise 的实例对象。因此可以调用 .then() 方法为每个 Promise 异步操作指定成功和失败之后的回调函数。示例代码如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QNdXVDWY-1650958972719)(D:\A_study\Vue\vue3_study_image\a11.png)]

注意:上述的代码无法保证文件的读取顺序,需要做进一步的改进!

import thenFs from 'then-fs'

thenFs.readFile('./files/1.txt','utf8').then((r1) => {console.log(r1)})
thenFs.readFile('./files/2.txt','utf8').then((r2) => {console.log(r2)})
thenFs.readFile('./files/3.txt','utf8').then((r3) => {console.log(r3)})

2. .then() 方法的特性

如果上一个 .then() 方法中返回了一个新的 Promise 实例对象,则可以通过下一个 .then() 继续进行处理。通过 .then() 方法的链式调用,就解决了回调地狱的问题

3. 基于 Promise 按顺序读取文件的内容

Promise 支持链式调用,从而来解决回调地狱的问题。示例代码如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cMQFuuCw-1650958972719)(D:\A_study\Vue\vue3_study_image\a12.png)]

4. 通过 .catch 捕获错误1

在 Promise 的链式操作中如果发生了错误,可以使用 Promise.prototype.catch 方法进行捕获和处理:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MAGemzv4-1650958972719)(D:\A_study\Vue\vue3_study_image\a13.png)]

5. 通过 .catch 捕获错误2

如果不希望前面的错误导致后续的 .then 无法正常执行,则可以将 .catch 的调用提前,示例代码如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZWGD8OkA-1650958972720)(D:\A_study\Vue\vue3_study_image\a14.png)]

6. Promise.all() 方法

Promise.all() 方法会发起并行的 Promise 异步操作,等所有的异步操作全部结束后才会执行下一步的.then 操作(等待机制)。示例代码如下

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1hyz87Iz-1650958972720)(D:\A_study\Vue\vue3_study_image\a15.png)]

注意:数组中 Promise 实例的顺序,就是最终结果的顺序

7. Promise.race() 方法

Promise.race() 方法会发起并行的 Promise 异步操作,只要任何一个异步操作完成,就立即执行下一步的 .then 操作(赛跑机制)。示例代码如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RbZwfRnK-1650958972720)(D:\A_study\Vue\vue3_study_image\a16.png)]

2.4 基于 Promise 封装读文件的方法

方法的封装要求:

​ ① 方法的名称要定义为 getFile

​ ② 方法接收一个形参 fpath,表示要读取的文件的路径

​ ③ 方法的返回值为 Promise 实例对象

1. getFile 方法的基本定义

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UMAg7w0f-1650958972721)(D:\A_study\Vue\vue3_study_image\a17.png)]

注意:第 5 行代码中的 new Promise() 只是创建了一个形式上的异步操作

2. 创建具体的异步操作

如果想要创建具体的异步操作,则需要在 new Promise() 构造函数期间,传递一个 function 函数,将具体的异步操作定义到 function 函数内部。示例代码如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cERhHMRe-1650958972721)(D:\A_study\Vue\vue3_study_image\a18.png)]

3. 获取 .then 的两个实参

通过 .then() 指定的成功和失败的回调函数,可以在 function 的形参中进行接收,示例代码如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9tFBObAN-1650958972722)(D:\A_study\Vue\vue3_study_image\a19.png)]

4. 调用 resolve 和 reject 回调函数

Promise 异步操作的结果,可以调用 resolve 或 reject 回调函数进行处理。示例代码如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kipoZHkW-1650958972722)(D:\A_study\Vue\vue3_study_image\a20.png)]

3. async/await

3.1 什么是 async/await

async/awaitES8(ECMAScript 2017)引入的新语法,用来简化 Promise 异步操作。在async/await 出现之前,开发者只能通过链式 .then() 的方式处理 Promise 异步操作。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-j2eC4cca-1650958972722)(D:\A_study\Vue\vue3_study_image\a21.png)]

  • .then 链式调用的优点:解决了回调地狱的问题
  • .then 链式调用的缺点:代码冗余、阅读性差、不易理解

3.2 async/await 的基本使用

使用 async/await 简化 Promise 异步操作的示例代码如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AyHw8cV6-1650958972723)(D:\A_study\Vue\vue3_study_image\a22.png)]

3.3 async/await 的使用注意事项

① 如果在 function 中使用了 await,则 function 必须被 async 修饰

② 在 async 方法中,第一个 await 之前的代码会同步执行,await 之后的代码会异步执行

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SozW4wVQ-1650958972723)(D:\A_study\Vue\vue3_study_image\a23.png)]

4. EventLoop

4.1 JavaScript 是单线程的语言

JavaScript 是一门单线程执行的编程语言。也就是说,同一时间只能做一件事情。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6dcC9kLm-1650958972723)(D:\A_study\Vue\vue3_study_image\a24.png)]

单线程执行任务队列的问题:

  • 如果前一个任务非常耗时,则后续的任务就不得不一直等待,从而导致程序假死的问题。

4.2 同步任务和异步任务

为了防止某个耗时任务导致程序假死的问题,JavaScript 把待执行的任务分为了两类:

同步任务(synchronous)

  • 又叫做非耗时任务,指的是在主线程上排队执行的那些任务
  • 只有前一个任务执行完毕,才能执行后一个任务

异步任务(asynchronous)

  • 又叫做耗时任务,异步任务由 JavaScript 委托给宿主环境进行执行
  • 当异步任务执行完成后,会通知 JavaScript 主线程执行异步任务的回调函数

4.3 同步任务和异步任务的执行过程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eOHWtB0b-1650958972724)(D:\A_study\Vue\vue3_study_image\a25.png)]

① 同步任务由 JavaScript 主线程次序执行

② 异步任务委托给宿主环境执行

③ 已完成的异步任务对应的回调函数,会被

​ 加入到任务队列中等待执行

④ JavaScript 主线程的执行栈被清空后,会

​ 读取任务队列中的回调函数,次序执行

⑤ JavaScript 主线程不断重复上面的第 4 步

4.4 EventLoop 的基本概念

JavaScript 主线程从“任务队列”中读取异步任务的回调函数,放到执行栈中依次执行。这个过程是循环不断的,所以整个的这种运行机制又称为 EventLoop(事件循环)。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1JbV8lNo-1650958972724)(D:\A_study\Vue\vue3_study_image\a26.png)]

4.5 结合 EventLoop 分析输出的顺序

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7XniGMec-1650958972724)(D:\A_study\Vue\vue3_study_image\a27.png)]

正确的输出结果:ADCB。其中:

  • A 和 D 属于同步任务。会根据代码的先后顺序依次被执行
  • C 和 B 属于异步任务。它们的回调函数会被加入到任务队列中,等待主线程空闲时再执行

5. 宏任务和微任务

5.1 什么是宏任务和微任务

JavaScript 把异步任务又做了进一步的划分,异步任务又分为两类,分别是:

① 宏任务(macrotask)

  • 异步 Ajax 请求、
  • setTimeout、setInterval、
  • 文件操作
  • 其它宏任务

② 微任务(microtask)

  • Promise.then、.catch 和 .finally
  • process.nextTick
  • 其它微任务

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9L1fTOUL-1650958972725)(D:\A_study\Vue\vue3_study_image\a28.png)]

5.2 宏任务和微任务的执行顺序

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-O4xzS6Rw-1650958972725)(D:\A_study\Vue\vue3_study_image\a29.png)]

每一个宏任务执行完之后,都会检查是否存在待执行的微任务,如果有,则执行完所有微任务之后,再继续执行下一个宏任务。

5.3 去银行办业务的场景

① 小云和小腾去银行办业务。首先,需要取号之后进行排队

  • 宏任务队列

② 假设当前银行网点只有一个柜员,小云在办理存款业务时,小腾只能等待

  • 单线程,宏任务按次序执行

③ 小云办完存款业务后,柜员询问他是否还想办理其它业务?

  • 当前宏任务执行完,检查是否有微任务

④ 小云告诉柜员:想要买理财产品、再办个信用卡、最后再兑换点马年纪念币?

  • 执行微任务,后续宏任务被推迟

⑤ 小云离开柜台后,柜员开始为小腾办理业务

  • 所有微任务执行完毕,开始执行下一个宏任务

5.4 分析以下代码输出的顺序

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3IJ5LMxa-1650958972726)(D:\A_study\Vue\vue3_study_image\a30.png)]

5.5 经典面试题

请分析以下代码输出的顺序(代码较长,截取成了左中右 3 个部分)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-z1TxoMFD-1650958972726)(D:\A_study\Vue\vue3_study_image\a31.png)]

6. API 接口案例

6.1 案例需求

基于 MySQL 数据库 + Express 对外提供用户列表的 API 接口服务。用到的技术点如下:

  • 第三方包 express 和 mysql2
  • ES6 模块化
  • Promise
  • async/await

6.2 主要的实现步骤

① 搭建项目的基本结构

② 创建基本的服务器

③ 创建 db 数据库操作模块

④ 创建 user_ctrl 业务模块

⑤ 创建 user_router 路由模块

6.3 搭建项目的基本结构

① 启用 ES6 模块化支持

  • 在 package.json 中声明 “type”: “module”

② 安装第三方依赖包

6.4 创建基本的服务器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mg6NPm0t-1650958972726)(D:\A_study\Vue\vue3_study_image\a32.png)]

6.5 创建 db 数据库操作模块

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RFXRw3HA-1650958972727)(D:\A_study\Vue\vue3_study_image\a33.png)]

6.6 创建 user_ctrl 模块

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZfEeJyao-1650958972727)(D:\A_study\Vue\vue3_study_image\a34.png)]

6.7 创建 user_router 模块

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Hu9EoYb0-1650958972728)(D:\A_study\Vue\vue3_study_image\a35.png)]

6.8 导入并挂载路由模块

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4gNdEz8A-1650958972728)(D:\A_study\Vue\vue3_study_image\a36.png)]

6.9 使用 try…catch 捕获异常

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-W1k7TGI9-1650958972729)(D:\A_study\Vue\vue3_study_image\a37.png)]

7. 总结

① 能够知道如何使用 ES6 的模块化语法

  • 默认导出与默认导入、按需导出与按需导入

② 能够知道如何使用 Promise 解决回调地狱问题

  • promise.then()、promise.catch()

③ 能够使用 async/await 简化 Promise 的调用

  • 方法中用到了 await,则方法需要被 async 修饰

④ 能够说出什么是 EventLoop

  • EventLoop 示意图

⑤ 能够说出宏任务和微任务的执行顺序

  • 在执行下一个宏任务之前,先检查是否有待执行的微任务

组件(上)

1. 单页面应用程序

1.1 单页面应用程序的优点

SPA 单页面应用程序最显著的 3 个优点如下:

① 良好的交互体验

  • 单页应用的内容的改变不需要重新加载整个页面
  • 获取数据也是通过 Ajax 异步获取
  • 没有页面之间的跳转,不会出现“白屏现象”

② 良好的前后端工作分离模式

  • 后端专注于提供 API 接口,更易实现 API 接口的复用
  • 前端专注于页面的渲染,更利于前端工程化的发展

③ 减轻服务器的压力

  • 服务器只提供数据,不负责页面的合成与逻辑的处理,吞吐能力会提高几倍

1.2 单页面应用程序的缺点

任何一种技术都有自己的局限性,对于 SPA 单页面应用程序来说,主要的缺点有如下两个:

① 首屏加载慢

  • 路由懒加载
  • 代码压缩
  • CDN 加速
  • 网络传输压缩

② 不利于 SEO

  • SSR 服务器端渲染

1.3 如何快速创建 vue 的 SPA 项目

vue 官方提供了两种快速创建工程化的 SPA 项目的方式:

① 基于 vite 创建 SPA 项目

② 基于 vue-cli 创建 SPA 项目

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HXbv4c0h-1650958972729)(D:\A_study\Vue\vue3_study_image\b1.png)]

2. vite 的基本使用

2.1 创建 vite 的项目

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tEL9JaBf-1650958972729)(D:\A_study\Vue\vue3_study_image\b37.png)]

按照顺序执行如下的命令,即可基于 vite 创建 vue 3.x 的工程化项目:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AA8q6AAg-1650958972730)(D:\A_study\Vue\vue3_study_image\b2.png)]

2.2 梳理项目的结构

使用 vite 创建的项目结构如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RkN6LmFz-1650958972730)(D:\A_study\Vue\vue3_study_image\b3.png)]

1. 梳理项目的结构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tXfdZe5q-1650958972731)(D:\A_study\Vue\vue3_study_image\b4.png)]

2.3 vite 项目的运行流程

在工程化的项目中,vue 要做的事情很单纯:通过 main.jsApp.vue 渲染到 index.html 的指定区域中。其中:

① App.vue 用来编写待渲染的模板结构

② index.html 中需要预留一个 el 区域

③ main.js 把 App.vue 渲染到了 index.html 所预留的区域中

1. 在 App.vue 中编写模板结构

清空 App.vue 的默认内容,并书写如下的模板结构:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MI27r6Z4-1650958972731)(D:\A_study\Vue\vue3_study_image\b5.png)]

2. 在 index.html 中预留 el 区域

打开 index.html 页面,确认预留了 el 区域:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MurCSYMR-1650958972731)(D:\A_study\Vue\vue3_study_image\b6.png)]

3. 在 main.js 中进行渲染

按照 vue 3.x 的标准用法,把 App.vue 中的模板内容渲染到 index.html 页面的 el 区域中:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5BGtlFGx-1650958972732)(D:\A_study\Vue\vue3_study_image\b7.png)]

3. 组件化开发思想

3.1 什么是组件化开发

组件化开发指的是:根据封装的思想,把页面上可重用的部分封装为组件,从而方便项目的开发和维护。

例如:http://www.ibootstrap.cn/ 所展示的效果,就契合了组件化开发的思想。用户可以通过拖拽组件的方式,快速生成一个页面的布局结构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZPBrMNFM-1650958972732)(D:\A_study\Vue\vue3_study_image\b8.png)]

3.2 组件化开发的好处

前端组件化开发的好处主要体现在以下两方面:

  • 提高了前端代码的复用性和灵活性
  • 提升了开发效率和后期的可维护性

3.3 vue 中的组件化开发

vue 是一个完全支持组件化开发的框架。vue 中规定组件的后缀名是 .vue。之前接触到的 App.vue 文件本质上就是一个 vue 的组件

4. vue 组件的构成

4.1 vue 组件组成结构

每个 .vue 组件都由 3 部分构成,分别是:

  • template -> 组件的模板结构
  • script -> 组件的 JavaScript 行为
  • style -> 组件的样式

其中,每个组件中必须包含 template 模板结构,而 script 行为和style 样式是可选的组成部分。

4.2 组件的 template 节点

vue 规定:每个组件对应的模板结构,需要定义到