首先我要說明一下,沒錯,還是沒有進入vue,劉備請諸葛亮三次都可以了吧,我這也是第三次了,也絕對是最后一次了,我應(yīng)經(jīng)摸透了因為,最后的webpack打包加上一個git學(xué)了過后我就去vue了。
為什么要說先看這篇,其實跟我們今天的主題webpack沒有太大關(guān)系,昨天學(xué)了一下webpack,其實內(nèi)容沒多少,webpack的內(nèi)容無非就是參考文檔去怎么做,然后最主要的js、html生成、css、字體圖標、圖片來打包包括開啟一個webpack服務(wù)器。但是我們今天的主要內(nèi)容,但是我要說的是比較重要的是,在學(xué)的朋友們,正在學(xué)包括后面在學(xué)的朋友們,作為一個程序員還在手寫筆記嗎?我也是昨天才知道手寫筆記的就我一個,我都驚了,我那么大一本筆記本,又長又厚的,我都做了那么多了,居然現(xiàn)在才知道,屬實太虧了,畢竟也是那個道理,如果后面工作不可能去翻書吧,優(yōu)不優(yōu)雅暫且不說,這耗費的時間就離譜雖然我自己做的筆記,我大概知道哪個知識點在哪一頁。
那么既然不太推薦手寫筆記了,那要用什么來做呢,程序員必備——Markdown!而他比較好的一款編輯器——Typora,昨天也花了一點時間了解了一下它有哪些功能哪些快捷鍵,確實這樣做筆記方便查找,而且省時最主要的,我原來學(xué)內(nèi)容可能內(nèi)容沒多少,但是也挺多的,滿打滿算都是一天的時間,反正現(xiàn)在有了這個,特別是代碼部分,有時候我還要手寫代碼,這個直接一個截圖的事情,你可以自己想想節(jié)省了多少時間。
至于我以前在筆記本上的,我的打算是,暴力一點,直接全 背 下 來。
回到我們今天的主題上來,首先第一個內(nèi)容說一下vue的前提基礎(chǔ),首先es6的模塊化,首先知道commanjs吧,是我們node的規(guī)則,require、exports都是他的語法,但他不是標準推薦的,真正的正統(tǒng)標準是ES6模塊化,而且commanjs只支持后端,而es6支持前后端。
他的一個語法規(guī)則:
1.1
導(dǎo)入為import 暴露共享成員export 沒有了s
如果我們node.js要使用es6模塊化的話首先版本號是要大于14.15.1的,其次需要在package.json添加“type”:“module”
關(guān)于他的導(dǎo)入導(dǎo)出一共有兩大類,第一類是默認導(dǎo)入導(dǎo)出。
export default 和 import 自定義 from ‘路徑’ 注意路徑必須添加后綴js跟我們的commanjs不一樣
let x = 19
let y = 29
function show() {}
export default {
x,
show
}
import m1 from './默認導(dǎo)出.js'
console.log(m1);
然后按需導(dǎo)出 export const a = 1 就是誰要導(dǎo)出就在定義它的前面加一個export
按需導(dǎo)入 import {a} from ‘’ 這個要注意的是花括號里面的名字不再自定義必須和我們導(dǎo)出的一致,但是我們可以用as重命名
export let x = 10
export function show() {console.log('hello vue');}
import {x, show} from './按需導(dǎo)出.js'
console.log(x, show);
最后是我們的直接導(dǎo)入,直接導(dǎo)入其實也挺常用比如css,或者js直接就是一段代碼,可以直接導(dǎo)入進來不使用,他們自己有自己的用處
for(let i = 0; i < 5; i++) {
console.log(i);
}
import './直接導(dǎo)入代碼.js'
有一說一,這個代碼塊跟typora一樣,看來這一步棋走對了。
然后看到我們的promise這個構(gòu)造函數(shù)
2.1
先了解一下回調(diào)地獄的問題吧,什么叫做回調(diào)地獄,就是我們多層嵌套回調(diào)函數(shù),本身就是回調(diào)函數(shù),還一層一層嵌套,他執(zhí)行了才去執(zhí)行里面的,其實也就是我們的高階函數(shù),那么這個時候就有問題了,我們要改上面的代碼后面也要跟著改,而且大量冗余的代碼可讀性也差。
2.2
然后說回到我們的promise,沒錯它本身是個構(gòu)造函數(shù),然后他的prototype上面有一個.then的方法,所以他的實例是可以用的,這個.then是個什么方法,他就是用來預(yù)先指定成功或者失敗的回調(diào)函數(shù)的,成功是必選參數(shù),失敗是可選。
比如我們下面通過一個案例來說,基于回調(diào)來讀取內(nèi)容,一個文件夾下面三個txt,以前的做法不用多說了的通過fs讀完一個又在里面嵌套一個,這就是典型的回調(diào)地獄。
我們的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這個方法,如果我們在成功的回到函數(shù)里先輸出然后返回下一個promise實例對象呢?
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有一個捕獲錯誤的方法,防止前面因為什么東西發(fā)生錯誤,而導(dǎo)致整盤崩潰,當(dāng)然如果你大概知道是哪里可能有點問題也可以吧這個方法前移,那么這樣就會繼續(xù)執(zhí)行后面的
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') //這里不做失敗的回調(diào)函數(shù),當(dāng)我們成功后是不是又通過return反悔了一個thenfs創(chuàng)造的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') //這里不做失敗的回調(diào)函數(shù),當(dāng)我們成功后是不是又通過return反悔了一個thenfs創(chuàng)造的promise的實例對象
})
.then((r2) => {
console.log(r2);
return thenfs.readFile('./files/3.txt', 'utf-8')
})
.then((r3) => {
console.log(r3);
})

2.5
promise.all方法這是用來發(fā)起并行的異步操作的,什么意思,就是一個等待機制,多個異步操作,等待他們?nèi)客瓿刹艜?zhí)行then里面的函數(shù)
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))

注意輸出為一個數(shù)組,并且輸出順序使我們數(shù)組里面的執(zhí)行順序。
與之對應(yīng)的還有一個promise.race方法,他與all一起都是發(fā)起并行操作,但是他是一旦有人執(zhí)行完,就輸出,意思就是最快的那一個
2.6
來一個案例,封裝一個promise獲取文件的函數(shù),這個函數(shù)最主要的是要搞懂我們的回調(diào)與then之間這的關(guān)系,return 一個 new promise創(chuàng)造一個實例,而他只是形式上的promise實例對象,還需要往里面添加一個函數(shù),這個函數(shù)兩個參數(shù)就是用來接受then的兩個成功和失敗的函數(shù),所以這兩個參數(shù)是函數(shù),再在里面來讀取,fs的操作步驟,也有失敗和結(jié)果去把結(jié)果給到剛才對應(yīng)的兩個參數(shù)
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方法還是按順序執(zhí)行的函數(shù)是不是都是為了能讓我們的異步操作能按照順序執(zhí)行出來,下面是不僅執(zhí)行了異步操作而且還能按照順序執(zhí)行出來的簡化步驟用到await、async
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,函數(shù)就必須被async修飾。
不加await就是promise實例,加了就能返回值直接輸出。
在await第一個之前是同步輸出,后面都為異步任務(wù)
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
事件流,時間循環(huán)我自己口述一遍吧,之前也說過的,我們的任務(wù)分為同步任務(wù)和異步任務(wù),同步任務(wù)會優(yōu)先在主棧道上執(zhí)行完,異步任務(wù)會根據(jù)宿主環(huán)境在那里執(zhí)行,但是異步任務(wù)都是有回調(diào)函數(shù)的,所以執(zhí)行了就會把函數(shù)放到異步任務(wù)的排列隊伍,等到同步任務(wù)執(zhí)行完,就會來按照順序執(zhí)行異步任務(wù)。
3.1
js又把異步任務(wù)進一步劃分了宏任務(wù)和微任務(wù)。
宏任務(wù):比如ajax、計時器、文件操作等
微任務(wù):promise那幾個方法、prcess.nextTick等
在異步任務(wù)中會優(yōu)先執(zhí)行宏任務(wù)再去檢查這個宏任務(wù)里面的微任務(wù),然后再去執(zhí)行宏任務(wù)這樣一個循環(huán),來看一個經(jīng)典面試題,你看輸出的什么?
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
這個最大的難點我覺得在于當(dāng)我們進入一個作用域后,會是一個全新的作用域,在這個里面再去重新看待里面的一些任務(wù),就相當(dāng)于你現(xiàn)在在這個作用域里面就是全局作用域
4.
進入webpack。
webpack本質(zhì)上是一個第三方模塊包,他可以起到壓縮、翻譯、打包、降級的作用。
webpack環(huán)境準備:
yarn init 初始化
yarn add webpack
在package里面添加執(zhí)行命令“build” :“webpack”
反正webpack始終要記住一點他只支持js,其他的都需要去文檔上看怎么轉(zhuǎn)過來。
而且他的操作也比較規(guī)律化,先定義好文件,css要有css文件,字體圖標要有字體圖標文件,然后要跟我們的入口文件掛上鉤,像img圖片、字體圖標這些需要動態(tài)創(chuàng)建在入口文件里面,css直接導(dǎo)入,包括更改默認出入口,加載器、插件這些都是在webpack.config.js這個配置文件里面改。
另外的注意點就是我們的圖片處理只針對于img標簽,背景圖片會被css解析的,但是最好還是要做圖片處理,因為如果type為asset的話,會以8kb作為一個區(qū)分