本文已参与「新人创作礼」活动,一起开启掘金创作之路。 1.
首先第一个内容说一下vue的前提基础,首先es6的模块化,首先知道commanjs吧,是我们node的规则,require、exports都是他的语法,但他不是标准推荐的,真正的正统标准是ES6模块化,而且commanjs只支持后端,而es6支持前后端。
他的一个语法规则:
1.1
导入为import 暴露共享成员export 没有了s
如果我们node.js要使用es6模块化的话首先版本号是要大于14.15.1的,其次需要在package.json添加“type”:“module”
关于他的导入导出一共有两大类,第一类是默认导入导出。
export default 和 import 自定义 from ‘路径’ 注意路径必须添加后缀js跟我们的commanjs不一样
let x = 19
let y = 29
function show() {}
export default {
x,
show
}
import m1 from './默认导出.js'
console.log(m1);
然后按需导出 export const a = 1 就是谁要导出就在定义它的前面加一个export
按需导入 import {a} from ‘’ 这个要注意的是花括号里面的名字不再自定义必须和我们导出的一致,但是我们可以用as重命名
export let x = 10
export function show() {console.log('hello vue');}
import {x, show} from './按需导出.js'
console.log(x, show);
最后是我们的直接导入,直接导入其实也挺常用比如css,或者js直接就是一段代码,可以直接导入进来不使用,他们自己有自己的用处
for(let i = 0; i < 5; i++) {
console.log(i);
}
import './直接导入代码.js'
有一说一,这个代码块跟typora一样,看来这一步棋走对了。
然后看到我们的promise这个构造函数
2.1
先了解一下回调地狱的问题吧,什么叫做回调地狱,就是我们多层嵌套回调函数,本身就是回调函数,还一层一层嵌套,他执行了才去执行里面的,其实也就是我们的高阶函数,那么这个时候就有问题了,我们要改上面的代码后面也要跟着改,而且大量冗余的代码可读性也差。
2.2
然后说回到我们的promise,没错它本身是个构造函数,然后他的prototype上面有一个.then的方法,所以他的实例是可以用的,这个.then是个什么方法,他就是用来预先指定成功或者失败的回调函数的,成功是必选参数,失败是可选。
比如我们下面通过一个案例来说,基于回调来读取内容,一个文件夹下面三个txt,以前的做法不用多说了的通过fs读完一个又在里面嵌套一个,这就是典型的回调地狱。
我们的fs模块不支持promise的方法所以我们需要下载一个包then-fs
import thenfs from 'then-fs'
thenfs.readFile('./files/1.txt', 'utf-8').then((r1) => console.log(r1))
thenfs.readFile('./files/2.txt', 'utf-8').then((r2) => console.log(r2))
thenfs.readFile('./files/3.txt', 'utf-8').then((r3) => console.log(r3))
可以看到通过promise的方法能够输出出来,但是有一个问题顺序不太对,这里是因为异步的原因,后面会说到
2.3
先来解决我们的顺序问题,怎么样可以让他们按照顺序来呢?
想通一件事情,我们的thenfs读取出来是一个promise的实例对象所以我们才能在后面用then这个方法,如果我们在成功的回到函数里先输出然后返回下一个promise实例对象呢?
Go
import thenfs from 'then-fs'
thenfs.readFile('./files/1.txt', 'utf8').then((r1) => {
console.log(r1);
return thenfs.readFile('./files/2.txt', 'utf8')
}).then((r2) => {
console.log(r2);
return thenfs.readFile('./files/3.txt', 'utf8')
}).then((r3) => console.log(r3))
2.4
捕获错误
我们promise有一个捕获错误的方法,防止前面因为什么东西发生错误,而导致整盘崩溃,当然如果你大概知道是哪里可能有点问题也可以吧这个方法前移,那么这样就会继续执行后面的
import thenfs from 'then-fs'
/* thenfs.readFile('./files/11.txt', 'utf-8').then((r1) => {
console.log(r1);
return thenfs.readFile('./files/2.txt', 'utf-8') //这里不做失败的回调函数,当我们成功后是不是又通过return反悔了一个thenfs创造的promise的实例对象
}).then((r2) => {
console.log(r2);
return thenfs.readFile('./files/3.txt', 'utf-8')
}).then((r3) => {
console.log(r3);
}).catch((err) => {
console.log(err.message);
}) */
thenfs.readFile('./files/11.txt', 'utf-8')
.catch((err) => {
console.log(err.message);
})
.then((r1) => {
console.log(r1);
return thenfs.readFile('./files/2.txt', 'utf-8') //这里不做失败的回调函数,当我们成功后是不是又通过return反悔了一个thenfs创造的promise的实例对象
})
.then((r2) => {
console.log(r2);
return thenfs.readFile('./files/3.txt', 'utf-8')
})
.then((r3) => {
console.log(r3);
})
2.5
promise.all方法这是用来发起并行的异步操作的,什么意思,就是一个等待机制,多个异步操作,等待他们全部完成才会去执行then里面的函数
import thenfs from 'then-fs'
let arr =[
thenfs.readFile('./files/1.txt', 'utf-8'),
thenfs.readFile('./files/2.txt', 'utf-8'),
thenfs.readFile('./files/3.txt', 'utf-8')
]
Promise.all(arr).then((r) => console.log(r))
注意输出为一个数组,并且输出顺序使我们数组里面的执行顺序。
与之对应的还有一个promise.race方法,他与all一起都是发起并行操作,但是他是一旦有人执行完,就输出,意思就是最快的那一个
2.6
来一个案例,封装一个promise获取文件的函数,这个函数最主要的是要搞懂我们的回调与then之间这的关系,return 一个 new promise创造一个实例,而他只是形式上的promise实例对象,还需要往里面添加一个函数,这个函数两个参数就是用来接受then的两个成功和失败的函数,所以这两个参数是函数,再在里面来读取,fs的操作步骤,也有失败和结果去把结果给到刚才对应的两个参数
import fs from 'fs'
function getTxt(Fpath,type) {
return new Promise(function(suc, wro) {
fs.readFile(Fpath, type, (err, result) => {
if(err) return wro(err.message)
suc(result)
})
})
}
getTxt('./files/1.txt', 'utf8').then((r1) => {
console.log(r1)
},(err) => {
console.log(err)
})
2.7
简化异步操作 。
刚才我们的不管是all方法还是按顺序执行的函数是不是都是为了能让我们的异步操作能按照顺序执行出来,下面是不仅执行了异步操作而且还能按照顺序执行出来的简化步骤用到await、async
Go
import thenfs from 'then-fs'
async function getFile() {
const r1 = await thenfs.readFile('../promise/files/1.txt', 'utf-8')
console.log(r1);
const r2 = await thenfs.readFile('../promise/files/2.txt', 'utf-8')
console.log(r2);
const r3 = await thenfs.readFile('../promise/files/3.txt', 'utf-8')
console.log(r3);
}
getFile()
function中用到await,函数就必须被async修饰。
不加await就是promise实例,加了就能返回值直接输出。
在await第一个之前是同步输出,后面都为异步任务
Go
import thenfs from 'then-fs'
console.log('A');
async function getFile() {
console.log('B')
const r1 = await thenfs.readFile('../promise/files/1.txt', 'utf-8')
const r2 = await thenfs.readFile('../promise/files/2.txt', 'utf-8')
const r3 = await thenfs.readFile('../promise/files/3.txt', 'utf-8')
console.log(r1,r2,r3);
console.log('D');
}
getFile()
console.log('C');
这个你认为输出出来是多少?
ABCr123最后D
事件流,时间循环我自己口述一遍吧,之前也说过的,我们的任务分为同步任务和异步任务,同步任务会优先在主栈道上执行完,异步任务会根据宿主环境在那里执行,但是异步任务都是有回调函数的,所以执行了就会把函数放到异步任务的排列队伍,等到同步任务执行完,就会来按照顺序执行异步任务。
3.1
js又把异步任务进一步划分了宏任务和微任务。
宏任务:比如ajax、计时器、文件操作等
微任务:promise那几个方法、prcess.nextTick等
在异步任务中会优先执行宏任务再去检查这个宏任务里面的微任务,然后再去执行宏任务这样一个循环,来看一个经典面试题,你看输出的什么?
console.log('1');
setTimeout(() => {
console.log('2');
new Promise (function(resolve) {
console.log('3');
resolve()
}).then(function() {
console.log('4');
})
});
new Promise(function(resolve) {
console.log('5');
resolve()
}).then(function() {
console.log('6');
})
setTimeout(() => {
console.log('7');
new Promise (function(resolve) {
console.log('8');
resolve()
}).then(function() {
console.log('9');
})
});
正确答案:156234789
这个最大的难点我觉得在于当我们进入一个作用域后,会是一个全新的作用域,在这个里面再去重新看待里面的一些任务,就相当于你现在在这个作用域里面就是全局作用域
进入webpack。
webpack本质上是一个第三方模块包,他可以起到压缩、翻译、打包、降级的作用。
webpack环境准备:
yarn init 初始化
yarn add webpack
在package里面添加执行命令“build” :“webpack”
反正webpack始终要记住一点他只支持js,其他的都需要去文档上看怎么转过来。
而且他的操作也比较规律化,先定义好文件,css要有css文件,字体图标要有字体图标文件,然后要跟我们的入口文件挂上钩,像img图片、字体图标这些需要动态创建在入口文件里面,css直接导入,包括更改默认出入口,加载器、插件这些都是在webpack.config.js这个配置文件里面改。
另外的注意点就是我们的图片处理只针对于img标签,背景图片会被css解析的,但是最好还是要做图片处理,因为如果type为asset的话,会以8kb作为一个区分