草庐IT

vue - ES6模块化、promise、webpack打包(所在在学的朋友们先看这篇,看了不吃亏)

Heymar-10 2023-03-28 原文

首先我要说明一下,没错,还是没有进入vue,刘备请诸葛亮三次都可以了吧,我这也是第三次了,也绝对是最后一次了,我应经摸透了因为,最后的webpack打包加上一个git学了过后我就去vue了。

为什么要说先看这篇,其实跟我们今天的主题webpack没有太大关系,昨天学了一下webpack,其实内容没多少,webpack的内容无非就是参考文档去怎么做,然后最主要的js、html生成、css、字体图标、图片来打包包括开启一个webpack服务器。但是我们今天的主要内容,但是我要说的是比较重要的是,在学的朋友们,正在学包括后面在学的朋友们,作为一个程序员还在手写笔记吗?我也是昨天才知道手写笔记的就我一个,我都惊了,我那么大一本笔记本,又长又厚的,我都做了那么多了,居然现在才知道,属实太亏了,毕竟也是那个道理,如果后面工作不可能去翻书吧,优不优雅暂且不说,这耗费的时间就离谱虽然我自己做的笔记,我大概知道哪个知识点在哪一页。

那么既然不太推荐手写笔记了,那要用什么来做呢,程序员必备——Markdown!而他比较好的一款编辑器——Typora,昨天也花了一点时间了解了一下它有哪些功能哪些快捷键,确实这样做笔记方便查找,而且省时最主要的,我原来学内容可能内容没多少,但是也挺多的,满打满算都是一天的时间,反正现在有了这个,特别是代码部分,有时候我还要手写代码,这个直接一个截图的事情,你可以自己想想节省了多少时间。

至于我以前在笔记本上的,我的打算是,暴力一点,直接全 背 下 来。

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一样,看来这一步棋走对了。

2.

然后看到我们的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实例对象呢?

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

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第一个之前是同步输出,后面都为异步任务

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.

事件流,时间循环我自己口述一遍吧,之前也说过的,我们的任务分为同步任务和异步任务,同步任务会优先在主栈道上执行完,异步任务会根据宿主环境在那里执行,但是异步任务都是有回调函数的,所以执行了就会把函数放到异步任务的排列队伍,等到同步任务执行完,就会来按照顺序执行异步任务。

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

这个最大的难点我觉得在于当我们进入一个作用域后,会是一个全新的作用域,在这个里面再去重新看待里面的一些任务,就相当于你现在在这个作用域里面就是全局作用域

4.

进入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作为一个区分

有关vue - ES6模块化、promise、webpack打包(所在在学的朋友们先看这篇,看了不吃亏)的更多相关文章

  1. ruby - 并发::Promise.all?不起作用 - 2

    在执行所有promise后,我正在尝试进行一些计算。但是proc从不调用:cbr_promise=Concurrent::Promise.execute{CbrRatesService.call}bitfinex_promise=Concurrent::Promise.execute{BitfinexService.call}proc=Proc.newdoputs10endConcurrent::Promise.all?([cbr_promise,bitfinex_promise]).then{proc}使用concurrent-ruby制作gem。例如,我是否应该创建一个每100毫秒

  2. chatGPT问答之 Webpack 5 多入口打包如何指定打包文件名规定的文件名 - 2

    前言chatGPT越来越令人惊奇,有一些答案在百度上搜半天却找不到你想要的,但与chatGPT的聊天中就可以非常快的得到你想要的结果,不得不说人工智能很好用下面就是我与chatGPT的聊天内容chatGPT问答之Webpack5多入口打包如何指定打包文件名规定的文件名问1:Webpack5多入口打包如何指定打包文件名为规定的文件名答1:在Webpack5中,可以使用output.filename选项来指定多入口打包后的文件名规则。output.filename可以是一个字符串,也可以是一个函数。如果output.filename是一个字符串,可以使用占位符来指定打包后的文件名规则,例如:mod

  3. javascript - JsDoc、ES6 和@param {Constructor} - 2

    我正在尝试使用JsDoc来记录es6类。无法相信您不能将类作为参数传递(类类型,而不是实例类型)。我一直在尝试一些事情,但无法让这个简单的代码正常工作,因此JsDoc不会向我抛出一些警告。除非我为我的每个类创建一个@typedef,然后手动将所有自己的和继承的成员添加到它,否则我无法让它工作。甚至不能做mixin!有没有人成功传递构造函数/类参数?让JsDoc处于静态上下文中,而不是实例上下文中?/***@classA*/classA{/***@static*/statichelloFromClassA(){}}/***@classB*@extendsA*/classBextendsA

  4. javascript - 你如何填充 Javascript ES6 `new.target` ? - 2

    一些ES6特性真的很容易polyfill:if(!Array.prototype.find){Array.prototype.find=...}你会如何polyfillnew.target?在不受支持的浏览器中使用时会触发语法错误。try/catch不起作用,因为它是一个语法错误。我不必使用new.target,我主要只是好奇。 最佳答案 正如Jaromanda评论的那样,您不能polyfill新语法,但您现在可以轻松解决一些new.target用例看看new.targetdocs你会看到一些可以用es5轻松编写的示例使用new.t

  5. javascript - 使用模块加载和类继承将 ES6 转换为 ES5 - 2

    我正在尝试找到将我的ECMAScript6代码转换为ES5的最佳/有效解决方案。我想使用模块加载器并利用继承。到目前为止,我最接近的是使用带有es2015预设和transform-es2015-modules-systemjs插件的Babel6。这是我的.babelrc文件:{"presets":["es2015"],"plugins":["transform-es2015-modules-systemjs"]}我的文件结构如下:-dist(transpiledfilesinthesamestructureasthesrcfolder)-src-classes-Point.js-Col

  6. javascript - Nodejs 与 promise 并行 - 2

    我有一个这样的字典:{go:['went','run'],love:['passion','like']}键的值是它的同义词。'getSynonymWords(word)'是一个异步函数,它返回一个promise,其中它的值是与传递的参数对应的同义词列表。我怎样才能像这样循环遍历对象以递归地获取另一个对象:{went:[],run:[],passion:[],like:[]}这是我的一段代码:functiongetRelatedWords(dict){returnnewPromise(function(resolve){varnewDict={};for(varkeyindict){i

  7. javascript - ES6 相当于 Node.js 需要函数调用 - 2

    这个问题在这里已经有了答案:PassoptionstoES6moduleimports(9个回答)关闭7年前。以下require函数调用的最短ES6等价物是什么?module.exports=function(app){...};require('./routes')(app);换句话说,在ES6模块中有一个等价的单行代码吗?

  8. javascript - ES6 异步生成器结果 - 2

    ES6有generatorsthatreturniterators:function*range(n){for(leti=0;i有一个关于返回Promises的异步函数的提议:asyncfunctionf(x){lety=awaitg(x);returny*y;}f(2).then(y=>{console.log(y);});那么如果我将两者结合起来会发生什么,就像这样:asyncfunction*ag(n){for(leti=0;i它返回什么?是Promise>?Iterator>?还有别的吗?我该如何食用它?我想应该有一个相应的for循环,什么将异步迭代其结果,例如:for(awa

  9. javascript - Angular $q.all 在第一个 promise 完成后被调用 - 2

    我正在尝试使用$q.all等待所有promise都已解决,但它是在第一个promise完成后调用的!我做错了什么?functionsendAudits(audits){varpromises=[];$scope.sendAudits={progress:0};angular.forEach(audits,function(audit,idAudit){promises.push(saveAudit(audit));});$q.all(promises).then(function(data){console.log(data);},function(errors){console.lo

  10. javascript - ES6 : import many files - 2

    我有一个导入大量AMD模块并在每个模块上调用初始化方法的脚本:define(['underscore','./mod0',...,'./modN'],function(_){_.each(_.toArray(arguments).slice(1),function(m){init(m);});});我需要切换到ES6导入语法,我想弄清楚是否可以从列表中导入模块,其方式类似于我的AMD代码。我想避免像这样的精神错乱:importmod0from'./mod0';...importmodNfrom'./modN';init(mod0);...init(modN);关于如何实现这一点有什么建

随机推荐