程序员书籍笔记 程序员书籍笔记
  • HTML
  • CSS
  • JavaScript
  • 前端知识
  • Vue
  • MarkDown
  • git
  • Node.js
  • Linux
  • 51单片机
  • 四级
  • 第一学期课程
  • 操作系统
  • 计算机网络
  • 数据结构
  • 计算机组成原理
  • HTML5
  • Electron
  • 日记便签
  • 前端导航
GitHub (opens new window)
  • HTML
  • CSS
  • JavaScript
  • 前端知识
  • Vue
  • MarkDown
  • git
  • Node.js
  • Linux
  • 51单片机
  • 四级
  • 第一学期课程
  • 操作系统
  • 计算机网络
  • 数据结构
  • 计算机组成原理
  • HTML5
  • Electron
  • 日记便签
  • 前端导航
GitHub (opens new window)
  • Vue

    • Vue基础
    • Vue前置知识
      • vue 前置知识
      • ES6模块化
        • 默认导出导入
        • 按需导出导入
        • 直接导入并执行
      • Promise
        • 基本概念
        • then-fs的案例
        • Promise.All()
        • Promise.race()
        • 封装自己功能的Promise
        • async 和 await
        • EventLoop
        • 宏任务和微任务
    • webpack
    • Vue基本使用
    • Vue基本使用+
    • Vue组件
    • Vue生命周期
    • Vue生命周期+
    • Vue插槽
    • Vue组件库
    • 网易云音乐案例
    • 案例
    • Vuex
    • Vue3.0
    • vue动画
    • 项目常用

    • 问题记录

    • vue模板
  • Nuxt

  • Echarts

  • Node

  • git

  • express

  • 微信小程序

  • Spring

  • 后端知识

  • Markdown

  • project

  • 自用文档查询

  • 框架和软件
  • Vue
yuadh
2022-02-03
目录

Vue前置知识

# vue 前置知识

  • 能够知道如何使用 ES6 的模块化语法
  • 能够知道如何使用 Promise 解决回调地狱的问题
  • 能够知道如何使用 async/await 简化 Promise的调用
  • 能够说出什么是EventLoop
  • 能够说出宏任务和微任务的执行顺序

# ES6模块化

Tip

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

但是,这些由社区提供的模块化标准,还是存在一定的差异与局限、并不是所有的浏览器与服务器通用的模块化标准,例如:AMD和CMD 适用于浏览器端,CommonJS适用于服务器端

因此大一统的 ES6 模块化规范诞生

node.js 可以使用 es6 中的模块化 :package.json 中添加 type:module 节点

默认情况下 node.js 使用的是 CommonJS 模块化规范

ES6 模块化中规范定义

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

基本语法

  1. 默认导出与默认导入
  2. 按需导出与按需导入
  3. 直接导入并执行模块中的代码

# 默认导出导入

语法:export default 默认导出成员

let n1 = 10;
let n2 = 20
function show(){}
export default{
    n1,
    show
}
1
2
3
4
5
6
7

注意:默认导出只允许导出一次

语法:inport 接收名称 from 模块标识符

import data from "./demo01.js"
console.log(data);
//{n1:10 , show:[Function:show]}
1
2
3

# 按需导出导入

导出:export 按需导出的成员

export let dat1 = 10;
export let dat2 = 20;
export function show(){}
1
2
3

导入:import {按需导入接收名称} from “模块化标识符”

import {dat1 as data} from "./URL"
console.log(data);
1
2

注意

  • 按需导入的成员名词必须和按需导出的名词一致
  • 按需导入时,可以使用 as 关键字进行重命名
  • 按需导入和默认导入可以同时存在,配合使用

# 直接导入并执行

如果只想单纯地执行某个模块中的代码,并不需要得到模块中共享的成员

此时,可以使用直接导入方法

for(let i=0;i<3;i++){
	console.log(i);
}
1
2
3
import "./URL"
// 0 1 2
1
2

# Promise

多层回调函数的相互嵌套,就形成了回调地狱

setTimeout(()=>{
    console.log('1');
    setTimeout(()=>{
         console.log('2');
        setTimeout(()=>{
            console.log('3');
        },3000)
    },2000)
},1000)
1
2
3
4
5
6
7
8
9
  • 代码耦合性强,难以维护
  • 大量冗余的代码互相嵌套,代码的可读性差

为了解决回调地狱的问题,ES6新增了 Promise 的概念

# 基本概念

  • Promise 是一个构造函数

    我们可以创建 Promise 的实例 const p = new Promise()

    new 出来的 Promise 实例对象,代表一个异步操作

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

    每一次得到的实例对象,都可以通过原型链的方式访问到 .then()方法

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

    p.then(成功的回调函数,失败的回调函数)

    p.then(result=>{},error=>{})
    
    1

    成功的回调函数是必选的,失败回调函数可选

# then-fs的案例

使用 node.js 中的 fs 文件操作模块 基于回调函数顺序读取文件内容

fs.readFile('./URL','utf-8',(err1,r1)={
    if(err1){
        return err1.massage
    }
    console.log(r1);
	fs.readFile('./URL','utf-8',(err2,r2)={
    	if(err2){
        	return err2.massage
    	}
    	console.log(r2);
		fs.readFile('./URL','utf-8',(err3,r3)={
    		if(err3){
        		return err3.massage
    		}
    		console.log(r3);
		})
	})
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

此时就会产生地狱回调函数的问题

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

import thenFs from 'then-fs'
thenFs.readFile('./URL','utf-8').then(r1=>{console.log(r1)},err1=>{return err1.message});
import thenFs from 'then-fs'
thenFs.readFile('./URL','utf-8').then(r2=>{console.log(r2)},err2=>{return err2.message});
import thenFs from 'then-fs'
thenFs.readFile('./URL','utf-8').then(r3=>{console.log(r3)},err3=>{return err3.message});
1
2
3
4
5
6

但是以上无法保证文件的读取顺序

利用 Promise 链式调用,解决问题

thenFs.readFile('./URL1','utf-8').then((r1)=>{
    console.log(r1)
    return thenFs.readFile('./URL2','utf-8')
}).then((r2)=>{
    console.log(r2)
    return thenFs.readFile('./URL3','utf-8')
}).then((r3)=>{
     console.log(r3)
}).catch(err=>{
    console.log(err.message)
})
1
2
3
4
5
6
7
8
9
10
11

注意

.catch() 方法会捕获到链式调用之前的产生错误异常,不会继续执行后面的链式代码

如果不想影响到后面的链式代码执行,可以把 .catch() 方法提前

# Promise.All()

Promise.All()方法会发起并行的 Promise 异步操作,等所有的异步操作全部结束后才会执行下一步的 .then()操作

import thenFs from 'then-fs'
const promiseArr = [
    thenFs.readFile('./URL1','UTF-8'),
    thenFs.readFile('./URL2','UTF-8'),
    thenFs.readFile('./URL3','UTF-8'),
]
Promise.all(promiseArr).then(result=>{
    console.log(result)//1 2 3
})
1
2
3
4
5
6
7
8
9

# Promise.race()

Promise.race() 方法会发起并行的 异步操作,只有有任何一个异步操作完成,就立即执行下一步的 .then()操作

import thenFs from 'then-fs'
const promiseArr = [
    thenFs.readFile('./URL1','UTF-8'),
    thenFs.readFile('./URL2','UTF-8'),
    thenFs.readFile('./URL3','UTF-8'),
]
Promise.race(promiseArr).then(result=>{
    console.log(result)//1or2or3
})
1
2
3
4
5
6
7
8
9

# 封装自己功能的Promise

import fs from 'fs'
//自定义函数
function getFile(fpath){
    return new Promise(function(resolve,reject){
        fs.readFile(fpath,'utf-8',(err,dataStr)=>{
            if(err){
                return reject(err)
            }
            resolve(dataStr)
        })
    })
}
1
2
3
4
5
6
7
8
9
10
11
12

调用

getFile('./URL').then((r1)=>{console.log(r1)},(err)=>{console.log(err)});
1

注意

在构造 Promise 对象里 function函数的两个形参

在传递的时候第一个形参是 then() 方法的成功回调函数 ,第二个形参是失败回调函数

# async 和 await

async/await 是 ES8 引入的新语法,用来简化 promise 异步操作

import thenFs from ''
async getFile(){
	const r1 = await thenFs.readFile('url','utf8');
}
1
2
3
4
  • await 被使用的函数必须被 async 修饰
  • 在 async 函数中,第一个 await 之前的代码同步执行,之后的代码异步执行
console.log('a')
async function f(){
    console.log('b')
    const r1 = await thenFs.readFile('url','utf8');
    console.log(r1)
    console.log('c')
}
f()
console.log('d')
/////out  
//  a b d {r1} c
1
2
3
4
5
6
7
8
9
10
11

# EventLoop

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

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

同步任务和异步任务

同步任务:

  • 非耗时任务,在主线程上排队执行的任务
  • 只有前一个任务执行完毕,才能执行后一个任务

异步任务

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

  1. 同步任务由 js 主线程执行
  2. 异步任务委托给宿主环境执行
  3. 已完成的异步任务对应的回调函数,会被加入到任务队列中等待执行
  4. js 主线程的执行栈被清空后,会读取任务队列中的回调函数,次序执行
  5. 主线程不断重复第四步操作

整个运行机制称为 EventLoop

示例

console.log('a');
thenFs.readFile(('url','utf-8').then(s=>{
    console.log('B');   
}))
setTimeout(()=>{
    console.log('C');
},0)
console.log('D');
//out - ADCB
1
2
3
4
5
6
7
8
9

耗时短的回调和函数先进入任务队列

# 宏任务和微任务

js 把异步任务又做了进一步的划分,异步任务又分为

  • 宏任务(macrotask)
    • 异步 Ajax 请求
    • setTimeout、setInterval
    • 文件操作
    • 其它宏任务
  • 微任务(microtask)
    • Promise.then、.catch和.finally
    • process.nextTick
    • 其它微任务

交替执行(微-宏-微...)

示例

demo 1

setTimeout(function(){
    console.log('a');
})
new Promise(function(resolve){
    console.log('b');
    resolve()
}).then(function(){
    console.log('c')
})
console.log('d');
//out  - bdca
1
2
3
4
5
6
7
8
9
10
11

demo 2

console.log('1');
setTimeout(function(){//异步任务
    console.log('2')
    new Promise(function (resolve){//同步任务
        consolo.log('3')
        resolve()
    }).then(function(){//异步任务-微任务
        console.log('4')
    })
})
new Promise(function (resolve){//同步任务
    console.log('5')
    resolve()
}).then(function (){//异步任务-微任务
    console.log('6')
})
setTimeout (function(){//异步任务
    console.log('7')
    new Promise (function (resolve){//同步任务
        console.log('8')
        resolve()
    }).then(function(){//异步任务-微任务
        console.log('9')
    })
})
//out - 1 5 6 2 3 4 7 8 9
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
编辑 (opens new window)
上次更新: 2023/02/07, 14:51:48
Vue基础
webpack

← Vue基础 webpack→

Theme by Vdoing | Copyright © 2021-2023 yuadh
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
×