- BabelJs 教程
- BabelJs - 首页
- BabelJs - 概述
- BabelJs - 环境搭建
- BabelJs - CLI
- BabelJs - ES6 代码执行
- BabelJs - 使用 Babel 6 进行项目设置
- BabelJs - 使用 Babel 7 进行项目设置
- 将 ES6 特性转换为 ES5
- 将 ES6 模块转换为 ES5
- 将 ES7 特性转换为 ES5
- 将 ES8 特性转换为 ES5
- BabelJs - Babel 插件
- BabelJs - Babel Polyfill
- BabelJs - Babel CLI
- BabelJs - Babel 预设
- 使用 Babel 和 Webpack
- 使用 Babel 和 JSX
- 使用 Babel 和 Flow
- 使用 BabelJS 和 Gulp
- BabelJs - 示例
- BabelJs 有用资源
- BabelJs - 快速指南
- BabelJs - 有用资源
- BabelJs - 讨论
BabelJS - 快速指南
BabelJS - 概述
BabelJS 是一个 JavaScript 转换器,它将新特性转换为旧标准。这样,这些特性就可以在旧版和新版浏览器上无缝运行。一位澳大利亚开发者 Sebastian McKenzie 启动了 BabelJS。
为什么选择 BabelJS?
JavaScript 是浏览器理解的语言。我们使用不同的浏览器来运行我们的应用程序 - Chrome、Firefox、Internet Explorer、Microsoft Edge、Opera、UC 浏览器等。ECMA Script 是 JavaScript 语言规范;ECMA Script 2015 ES6 是稳定的版本,在所有新旧浏览器中都能正常工作。
在 ES5 之后,我们有了 ES6、ES7 和 ES8。ES6 发布了许多新特性,并非所有浏览器都完全支持。ES7、ES8 和 ESNext(ECMA Script 的下一个版本)也是如此。目前尚不确定所有浏览器何时能够兼容所有发布的 ES 版本。
如果我们计划使用 ES6 或 ES7 或 ES8 特性来编写代码,由于缺乏对新更改的支持,它可能会在某些旧版浏览器中中断。因此,如果我们想在代码中使用 ECMA Script 的新特性,并希望它在所有可用的浏览器上运行,我们需要一个工具将我们的最终代码编译成 ES5。
Babel 做的就是这件事,它被称为转换器,可以将代码转换为我们想要的 ECMA Script 版本。它具有预设和插件等特性,可以配置我们需要转换代码的 ECMA 版本。使用 Babel,开发人员可以使用 JavaScript 中的新特性编写代码。用户可以使用 Babel 转换代码;这些代码随后可以在任何浏览器中使用,而不会出现任何问题。
下表列出了 ES6、ES7 和 ES8 中可用的特性 -
特性 | ECMA Script 版本 |
---|---|
Let + Const | ES6 |
箭头函数 | ES6 |
类 | ES6 |
Promise | ES6 |
生成器 | ES6 |
迭代器 | ES6 |
模块 | ES6 |
解构 | ES6 |
模板字面量 | ES6 |
增强对象 | ES6 |
默认、剩余和扩展属性 | ES6 |
Async - Await | ES7 |
指数运算符 | ES7 |
Array.prototype.includes() | ES7 |
字符串填充 | ES8 |
BabelJS 管理以下两个部分 -
- 转换
- 填充
什么是 Babel-转换器?
Babel-转换器将现代 JavaScript 的语法转换为旧版浏览器可以轻松理解的形式。例如,箭头函数、const、let 类将转换为函数、var 等。这里语法,即箭头函数被转换为普通函数,在两种情况下功能相同。
什么是 Babel-填充?
JavaScript 中添加了一些新特性,例如 Promise、Map 和 includes。这些特性可以用于数组;同样,当使用 Babel 进行转换时,不会被转换。如果新特性是方法或对象,我们需要将 Babel-填充与转换一起使用才能使其在旧版浏览器上工作。
以下是 JavaScript 中可用的 ECMA Script 特性列表,可以进行转换和填充 -
- 类
- 装饰器
- Const
- 模块
- 解构
- 默认参数
- 计算属性名
- 对象剩余/扩展
- 异步函数
- 箭头函数
- 剩余参数
- 扩展
- 模板字面量
可以填充的 ECMA Script 特性 -
- Promise
- Map
- Set
- Symbol
- Weakmap
- Weakset
- includess
- Array.from、Array.of、Array#find、Array.buffer、Array#findIndex
- Object.assign、Object.entries、Object.values
BabelJS 的特性
在本节中,我们将了解 BabelJS 的不同特性。以下是 BabelJS 最重要的核心特性 -
Babel-插件
插件和预设是 Babel 转换代码的配置细节。Babel 支持许多插件,如果我们知道代码将在哪个环境中执行,则可以单独使用这些插件。
Babel-预设
Babel 预设是一组插件,即 babel-转换器的配置细节,指示 Babel 以特定模式进行转换。我们需要使用预设,其中包含我们希望代码转换为的环境。例如,es2015 预设会将代码转换为 es5。
Babel-填充
有些特性(例如方法和对象)无法转换。在这种情况下,我们可以使用 babel-填充来促进在任何浏览器中使用这些特性。让我们以 Promise 为例;为了使该特性在旧版浏览器中工作,我们需要使用填充。
Babel-填充
Babel-cli 带有一系列命令,可以使用这些命令轻松地在命令行上编译代码。它还具有插件和预设等特性,可以与命令一起使用,从而可以轻松地一次性转换代码。
使用 BabelJS 的优势
在本节中,我们将了解与使用 BabelJS 相关的不同优势 -
BabelJS 为添加到 JavaScript 的所有新特性提供向后兼容性,并且可以在任何浏览器中使用。
BabelJS 能够转换以获取 JavaScript 的下一个即将发布的版本 - ES6、ES7、ESNext 等。
BabelJS 可以与 gulp、webpack、flow、react、typescript 等一起使用,使其功能非常强大,并且可以用于大型项目,从而使开发人员的生活更轻松。
BabelJS 还与 react JSX 语法一起使用,并且可以编译成 JSX 形式。
BabelJS 支持插件、填充、babel-cli,这使得它易于处理大型项目。
使用 BabelJS 的缺点
在本节中,我们将了解使用 BabelJS 的不同缺点 -
BabelJS 代码在转换时会更改语法,这使得发布到生产环境后难以理解代码。
与原始代码相比,转换后的代码大小更大。
并非所有 ES6/7/8 或即将发布的新特性都可以转换,我们必须使用填充才能使其在旧版浏览器上工作。
这是 babeljs 的官方网站 https://babel.node.org.cn/。
BabelJS - 环境搭建
在本节中,我们将学习如何为 BabelJS 设置环境。
要使用 BabelJS,我们需要以下设置 -
- NodeJS
- Npm
- Babel-CLI
- Babel-Preset
- 用于编写代码的 IDE
NodeJS
要检查系统中是否安装了 nodejs,请在终端中键入node –v。这将帮助您查看当前安装在系统上的 nodejs 版本。
如果它没有打印任何内容,请在您的系统上安装 nodejs。要安装 nodejs,请访问 nodejs 的主页 https://node.org.cn/en/download/ 并根据您的操作系统安装软件包。
以下屏幕截图显示了 nodejs 的下载页面 -
根据您的操作系统,安装所需的软件包。安装 nodejs 后,npm 也会随之安装。要检查 npm 是否已安装,请在终端中键入npm –v。它应该显示 npm 的版本。
BabelJS - CLI
Babel 带有一个内置的命令行界面,可用于编译代码。
创建一个您将在其中工作的目录。在这里,我们创建了一个名为babelproject的目录。让我们利用 nodejs 创建项目详细信息。
我们使用npm init创建项目,如下所示 -
这是我们创建的项目结构。
现在要使用 Babel,我们需要安装 Babel cli、Babel 预设、Babel 核心,如下所示 -
babel-cli
执行以下命令以安装 babel-cli -
npm install --save-dev babel-cli
babel-preset
执行以下命令以安装 babel-preset -
npm install --save-dev babel-preset-env
babel-core
执行以下命令以安装 babel-core -
npm install --save-dev babel-core
安装后,以下是 package.json 中可用的详细信息 -
我们已将 babel 插件安装到项目的本地。这样做是为了我们可以根据项目需求以及 babeljs 的不同版本在项目中以不同的方式使用 babel。Package.json 提供了所用 babeljs 的版本详细信息。
为了在项目中使用 babel,我们需要在 package.json 中指定如下 -
Babel 主要用于编译 JavaScript 代码,这将具有向后兼容性。现在,我们将用 ES6 -> ES5 或 ES7 -> ES5 以及 ES7->ES6 等编写代码。
为了在执行时向 Babel 提供相同的说明,我们需要在根文件夹中创建一个名为 .babelrc 的文件。它包含一个具有预设详细信息的 json 对象,如下所示 -
我们将创建 JavaScript 文件 index.js 并使用 Babel 将其编译为 es2015。在此之前,我们需要安装 es2015 预设,如下所示 -
在 index.js 中,我们使用箭头函数创建了一个函数,这是 es6 中添加的新特性。使用 Babel,我们将代码编译为 es5。
要执行到 es2015,使用以下命令 -
npx babel index.js
输出
它显示了上面所示的 es5 中的 index.js 代码。
我们可以通过执行如下命令将输出存储到文件中:
npx babel index.js --out-file index_es5.js
输出
这是我们创建的文件,index_es5.js:
BabelJS - ES6 代码执行
BabelJS 是一个 JavaScript 编译器,它将添加到 JavaScript 中的新特性转换为 ES5 或 React,具体取决于给定的预设或插件。ES5 是 JavaScript 最古老的形式之一,并且可以无缝运行在新旧浏览器上。在本教程的大多数示例中,我们都将代码编译成了 ES5。
我们已经看到了 ES6、ES7 和 ES8 中添加了许多特性,例如箭头函数、类、Promise、生成器、异步函数等。当在旧浏览器中使用任何新添加的特性时,它都会抛出错误。BabelJS 有助于编译代码,使其向后兼容旧版浏览器。我们已经看到 ES5 在旧版浏览器上运行良好,没有任何问题。因此,考虑到项目环境的详细信息,如果需要在旧版浏览器上运行,我们可以在项目中使用任何新特性,并使用 babeljs 将代码编译成 ES5,然后在任何浏览器中使用它而不会出现任何问题。
让我们考虑以下示例来理解这一点。
示例
<!DOCTYPE html> <html> <head> <title>BabelJs Testing</title> </head> <body> <script type="text/javascript" src="index.js"></script> </body> </html>
index.js 文件
var _foo = () => { return "Hello World" }; alert(_foo());
输出
当我们在 Chrome 浏览器中运行以上 html 时,我们得到以下输出:
当 HTML 在 Firefox 中运行时,它会生成以下输出:
当相同的 HTML 在 Internet Explorer 中运行时,它会生成以下语法错误:
我们使用了 ES6 箭头函数;如上所示,它并不适用于所有浏览器。为了使其正常工作,我们使用 BabelJS 将代码编译为 ES5,并在所有浏览器中使用它。
将使用 babeljs 将 js 文件编译为 es5,并在浏览器中再次检查。
在 html 文件中,我们将使用 index_new.js,如下所示:
<!DOCTYPE html> <html> <head> <title>BabelJs Testing</title> </head> <body> <script type="text/javascript" src="index_new.js"></script> </body> </html>
index_new.js
"use strict"; var _foo = function _foo() { return "Hello World"; }; alert(_foo());
Chrome 输出
Firefox 浏览器输出
IE 浏览器输出
BabelJS - 使用 Babel 6 进行项目设置
在本章中,我们将了解如何在项目中使用 babeljs。我们将使用 nodejs 创建一个项目,并使用 http 本地服务器来测试我们的项目。
创建项目设置
在本节中,我们将学习如何创建项目设置。
创建一个新目录并运行以下命令创建项目:
npm init
输出
执行后,上述命令会生成以下输出:
以下是创建的 package.json:
我们将安装开始使用 babeljs 所需的软件包。我们将执行以下命令来安装babel-cli、babel-core、babel-preset-es2015。
npm install babel-cli babel-core babel-preset-es2015 --save-dev
输出
执行后,上述命令会生成以下输出:
Package.json 更新如下:
我们需要 http 服务器来测试 js 文件。执行以下命令安装 http 服务器:
npm install lite-server --save-dev
我们在 package.json 中添加了以下详细信息:
在脚本中,Babel 负责将 src 文件夹中的 scripts.js 转换为 dev 文件夹中的 scripts.bundle.js。我们在 package.json 中添加了编译所需代码的完整命令。此外,添加了build,它将启动lite-server 来测试更改。
src/scripts.js 中的 JavaScript 如下所示:
class Student { constructor(fname, lname, age, address) { this.fname = fname; this.lname = lname; this.age = age; this.address = address; } get fullname() { return this.fname +"-"+this.lname; } }
我们在 index.html 中调用了转换后的脚本,如下所示:
<html> lt;head></head> <body> <script type="text/javascript" src="dev/scripts.bundle.js?a=11"></script> <h1 id="displayname"></h1> <script type="text/javascript"> var a = new Student("Siya", "Kapoor", "15", "Mumbai"); var studentdet = a.fullname; document.getElementById("displayname").innerHTML = studentdet; </script> </body> </html>
我们需要运行以下命令,它将调用 babel 并编译代码。该命令将从 package.json 调用 Babel:
npm run babel
scripts.bundle.js 是在 dev 文件夹中创建的新 js 文件:
dev/scripts.bundle.js 的输出如下:
"use strict"; var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var Student = function () { function Student(fname, lname, age, address) { _classCallCheck(this, Student); this.fname = fname; this.lname = lname; this.age = age; this.address = address; } _createClass(Student, [{ key: "fullname", get: function get() { return this.fname + "-" + this.lname; } }]); return Student; }();
现在让我们运行以下命令来启动服务器:
npm run build
当命令运行时,它将在浏览器中打开 url:
输出
上述命令生成以下输出:
BabelJS - 使用 Babel 7 进行项目设置
Babel 的最新版本 7 发布了对现有软件包的更改。安装部分与 Babel 6 相同。Babel 7 中唯一的区别是所有软件包都需要使用@babel/安装,例如 @babel/core、@babel/preset-env、@babel/cli、@babel/polyfill 等。
这是一个使用 babel 7 创建的项目设置。
命令
执行以下命令启动项目设置:
npm init
安装以下软件包
npm install --save-dev @babel/core npm install --save-dev @babel/cli npm install --save-dev @babel/preset-env
以下是创建的 package.json:
现在将在根文件夹中创建一个.babelrc文件:
创建一个文件夹src/并在其中添加文件main.js,并将您的代码写入转换为 es5。
src/main.js
let add = (a,b) => { return a+b; }
转换命令
npx babel src/main.js --out-file main_es5.js
main_es5.js
"use strict"; var add = function add(a, b) { return a + b; };
Babel 7 的工作原理与 Babel 6 相同。唯一的区别是使用 @babel 安装软件包。
Babel 7 中有一些预设已弃用。列表如下:
- ES20xx 预设
- babel-preset-env
- babel-preset-latest
- Babel 中的阶段预设
此外,软件包中的年份也被删除 - @babel/plugin-transform-es2015-classes现在为@babel/plugin-transform-classes
我们将再举一个使用 typescript 并使用 typescript 预设和 babel 7 将其转换为 Es2015 JavaScript 的示例。
要使用 typescript,我们需要安装 typescript 软件包,如下所示:
npm install --save-dev @babel/preset-typescript
在src/文件夹中创建test.ts文件,并以 typescript 形式编写代码:
test.ts
let getName = (person: string) => { return "Hello, " + person; } getName("Siya");
.babelrc
命令
npx babel src/test.ts --out-file test.js
test.js
"use strict"; var getName = function getName(person) { return "Hello, " + person; }; getName("Siya");
BabelJS - 将 ES6 特性转换为 ES5
在本章中,我们将了解添加到 ES6 中的特性。我们还将学习如何使用 BabelJS 将这些特性编译为 ES5。
以下是我们将在本章中讨论的各种 ES6 特性:
- Let + Const
- 箭头函数
- 类
- Promise
- 生成器
- 解构
- 迭代器
- 模板字面量
- 增强对象
- 默认、剩余和扩展属性
Let + Const
Let 在 JavaScript 中声明一个块作用域局部变量。请考虑以下示例以了解 let 的用法。
示例
let a = 1; if (a == 1) { let a = 2; console.log(a); } console.log(a);
输出
2 1
第一个控制台打印 2 的原因是a使用let再次声明,并且仅在if块中可用。使用 let 声明的任何变量仅在其声明的块内可用。我们使用 let 声明了两次变量 a,但它不会覆盖 a 的值。
这是 var 和 let 关键字之间的区别。当您使用 var 声明变量时,该变量将在函数的作用域内可用,或者如果声明为全局变量。
如果使用 let 声明变量,则该变量在块作用域内可用。如果在 if 语句内声明,则它仅在 if 块内可用。这同样适用于 switch、for 循环等。
现在我们将看到使用 babeljs 将代码转换为 ES5。
让我们运行以下命令来转换代码:
npx babel let.js --out-file let_es5.js
从 es6 到 es5 的 let 关键字的输出如下:
使用 ES6 的 Let
let a = 1; if (a == 1) { let a = 2; console.log(a); } console.log(a);
使用 babel 转换为 ES5
"use strict"; var a = 1; if (a == 1) { var _a = 2; console.log(_a); } console.log(a);
如果您查看 ES5 代码,let 关键字将替换为var关键字。此外,if 块内的变量被重命名为_a,以获得与使用let关键字声明时相同的效果。
Const
在本节中,我们将学习 ES6 和 ES5 中 const 关键字的工作原理。Const 关键字也存在于作用域内;如果在外部,它将抛出错误。一旦赋值,声明的 const 变量的值就不能更改。让我们考虑以下示例以了解 const 关键字的使用方法。
示例
let a =1; if (a == 1) { const age = 10; } console.log(age);
输出
Uncaught ReferenceError: age is not defined at:5:13
以上输出抛出错误,因为 const age 在 if 块内定义,并且在 if 块内可用。
我们将了解使用 BabelJS 转换为 ES5。
ES6
let a =1; if (a == 1) { const age = 10; } console.log(age);
命令
npx babel const.js --out-file const_es5.js
使用 BabelJS 转换为 ES6
"use strict"; var a = 1; if (a == 1) { var _age = 10; } console.log(age);
对于 ES5,const 关键字将替换为 var 关键字,如上所示。
箭头函数
与变量表达式相比,箭头函数具有更短的语法。它也称为胖箭头函数或 lambda 函数。该函数没有自己的 this 属性。在此函数中,省略了关键字 function。
示例
var add = (x,y) => { return x+y; } var k = add(3,6); console.log(k);
输出
9
使用 BabelJS,我们将以上代码转换为 ES5。
ES6 - 箭头函数
var add = (x,y) => { return x+y; } var k = add(3,6); console.log(k);
命令
npx babel arrowfunction.js --out-file arrowfunction_es5.js
BabelJS - ES5
使用 Babel,箭头函数将转换为变量表达式函数,如下所示。
"use strict"; var add = function add(x, y) { return x + y; }; var k = add(3, 6); console.log(k);
类
ES6 带来了新的类特性。类类似于 ES5 中可用的基于原型的继承。class 关键字用于定义类。类就像特殊的函数,并且具有类似于函数表达式的相似之处。它有一个构造函数,在类内部调用。
示例
class Person { constructor(fname, lname, age, address) { this.fname = fname; this.lname = lname; this.age = age; this.address = address; } get fullname() { return this.fname +"-"+this.lname; } } var a = new Person("Siya", "Kapoor", "15", "Mumbai"); var persondet = a.fullname;
输出
Siya-Kapoor
ES6 - 类
class Person { constructor(fname, lname, age, address) { this.fname = fname; this.lname = lname; this.age = age; this.address = address; } get fullname() { return this.fname +"-"+this.lname; } } var a = new Person("Siya", "Kapoor", "15", "Mumbai"); var persondet = a.fullname;
命令
npx babel class.js --out-file class_es5.js
BabelJS - ES5
使用 babeljs 添加了额外的代码以使类的功能与 ES5 中相同。BabelJs 确保功能与在 ES6 中一样。
"use strict"; var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var Person = function () { function Person(fname, lname, age, address) { _classCallCheck(this, Person); this.fname = fname; this.lname = lname; this.age = age; this.address = address; } _createClass(Person, [{ key: "fullname", get: function get() { return this.fname + "-" + this.lname; } }]); return Person; }(); var a = new Person("Siya", "Kapoor", "15", "Mumbai"); var persondet = a.fullname;
Promise
JavaScript Promise 用于管理代码中的异步请求。
它使生活更轻松并使代码保持简洁,因为您管理来自具有依赖关系的异步请求的多个回调。Promise 提供了一种更好的处理回调函数的方法。Promise 是 ES6 的一部分。默认情况下,当您创建一个 Promise 时,Promise 的状态为 pending。
Promise 有三种状态:
- pending(初始状态)
- resolved(成功完成)
- rejected(失败)
new Promise()用于构造一个 Promise。Promise 构造函数有一个参数,它是一个回调函数。回调函数有两个参数 - resolve 和 reject;
这两个都是内部函数。您编写的异步代码,即 Ajax 调用、图像加载、定时函数将进入回调函数。
如果回调函数中执行的任务成功,则调用 resolve 函数;否则,将使用错误详细信息调用 reject 函数。
以下代码行显示了 Promise 结构调用:
var _promise = new Promise (function(resolve, reject) { var success = true; if (success) { resolve("success"); } else { reject("failure"); } }); _promise.then(function(value) { //once function resolve gets called it comes over here with the value passed in resolve console.log(value); //success }).catch(function(value) { //once function reject gets called it comes over here with the value passed in reject console.log(value); // failure. });
ES6 Promise 示例
let timingpromise = new Promise((resolve, reject) => { setTimeout(function() { resolve("Promise is resolved!"); }, 1000); }); timingpromise.then((msg) => { console.log(msg); });
输出
Promise is resolved!
ES6 - Promise
let timingpromise = new Promise((resolve, reject) => { setTimeout(function() { resolve("Promise is resolved!"); }, 1000); }); timingpromise.then((msg) => { console.log(msg); });
命令
npx babel promise.js --out-file promise_es5.js
BabelJS - ES5
"use strict"; var timingpromise = new Promise(function (resolve, reject) { setTimeout(function () { resolve("Promise is resolved!"); }, 1000); }); timingpromise.then(function (msg) { console.log(msg); });
对于 Promise,在转换时代码不会发生变化。我们需要使用 babel-polyfill 才能使其在旧版浏览器上运行。babel-polyfills 的详细信息在 babel - poyfill 章节中进行了说明。
生成器
生成器函数类似于普通的function。该函数具有特殊的语法 function*,在函数中使用 *,以及yield关键字在函数内部使用。这旨在在需要时暂停或启动函数。普通的函数一旦执行开始,就不能在中间停止。它要么执行完整函数,要么在遇到 return 语句时停止。生成器在这里的行为有所不同,您可以使用 yield 关键字停止函数,并在需要时通过再次调用生成器来启动它。
示例
function* generatorfunction(a) { yield a; yield a +1 ; } let g = generatorfunction(8); console.log(g.next()); console.log(g.next());
输出
{value: 8, done: false} {value: 9, done: false}
ES6 - 生成器
function* generatorfunction(a) { yield a; yield a +1 ; } let g = generatorfunction(8); console.log(g.next()); console.log(g.next());
命令
npx babel generator.js --out-file generator_es5.js
BabelJS - ES5
"use strict"; var _marked = /*#__PURE__*/regeneratorRuntime.mark(generatorfunction); function generatorfunction(a) { return regeneratorRuntime.wrap(function generatorfunction$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: _context.next = 2; return a; case 2: _context.next = 4; return a + 1; case 4: case "end": return _context.stop(); } } }, _marked, this); } var g = generatorfunction(8); console.log(g.next()); console.log(g.next());
迭代器
JavaScript 中的迭代器返回一个 JavaScript 对象,该对象具有值。该对象还有一个名为 done 的标志,它具有 true/false 值。如果它不是迭代器的末尾,则返回 false。让我们考虑一个示例,并查看迭代器在数组上的工作原理。
示例
let numbers = [4, 7, 3, 10]; let a = numbers[Symbol.iterator](); console.log(a.next()); console.log(a.next()); console.log(a.next()); console.log(a.next()); console.log(a.next());
在以上示例中,我们使用了数字数组,并使用Symbol.iterator作为索引在数组上调用了一个函数。
使用数组上的 next() 获得的输出如下:
{value: 4, done: false} {value: 7, done: false} {value: 3, done: false} {value: 10, done: false} {value: undefined, done: true}
输出给出一个具有 value 和 done 作为属性的对象。每次next()方法调用都会从数组中获取下一个值,并且 done 为 false。只有当数组中的元素完成时,done 的值才会为 true。我们可以将其用于迭代数组。还有更多可用的选项,例如for-of循环,其用法如下:
示例
let numbers = [4, 7, 3, 10]; for (let n of numbers) { console.log(n); }
输出
4 7 3 10
当for-of 循环使用键时,它会提供数组值的详细信息,如上所示。我们将检查这两种组合,并查看 babeljs 如何将其转换为 es5。
示例
let numbers = [4, 7, 3, 10]; let a = numbers[Symbol.iterator](); console.log(a.next()); console.log(a.next()); console.log(a.next()); console.log(a.next()); console.log(a.next()); let _array = [4, 7, 3, 10]; for (let n of _array) { console.log(n); }
命令
npx babel iterator.js --out-file iterator_es5.js
输出
"use strict"; var numbers = [4, 7, 3, 10]; var a = numbers[Symbol.iterator](); console.log(a.next()); console.log(a.next()); console.log(a.next()); console.log(a.next()); console.log(a.next()); var _array = [4, 7, 3, 10]; var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = _array[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var n = _step.value; console.log(n); } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } }
在 es5 中添加了for-of循环的更改。但是 iterator.next 保持不变。我们需要使用babel-polyfill才能使其在旧版浏览器中运行。Babel-polyfill 与 babel 一起安装,并且可以从 node_modules 中使用,如下所示:
示例
<html> <head> <script type="text/javascript" src="node_modules/babel-polyfill/dist/polyfill.min.js"></script> <script type="text/javascript" src="iterator_es5.js"></script> </head> <body> <h1>Iterators</h1> </body> </html>
输出
解构
解构属性的行为类似于 JavaScript 表达式,它从数组、对象中解包值。
以下示例将解释解构语法的使用方法。
示例
let x, y, rem; [x, y] = [10, 20]; console.log(x); console.log(y); [x, y, ...rem] = [10, 20, 30, 40, 50]; console.log(rem); let z = 0; ({ x, y } = (z) ? { x: 10, y: 20 } : { x: 1, y: 2 }); console.log(x); console.log(y);
输出
10 20 [30, 40, 50] 1 2
以上代码行展示了如何将数组右侧的值分配给左侧的变量。带有...rem的变量获取数组中所有剩余的值。
我们还可以使用条件运算符,如下所示,将左侧对象中的值分配给变量。
({ x, y } = (z) ? { x: 10, y: 20 } : { x: 1, y: 2 }); console.log(x); // 1 console.log(y); // 2
让我们使用 babeljs 将其转换为 ES5。
命令
npx babel destructm.js --out-file destruct_es5.js
destruct_es5.js
"use strict"; var x = void 0, y = void 0, rem = void 0; x = 10; y = 20; console.log(x); console.log(y); x = 10; y = 20; rem = [30, 40, 50]; console.log(rem); var z = 0; var _ref = z ? { x: 10, y: 20 } : { x: 1, y: 2 }; x = _ref.x; y = _ref.y; console.log(x); console.log(y);
模板字面量
模板字面量是一种字符串字面量,允许在其中使用表达式。它使用反引号(``)而不是单引号或双引号。当我们说字符串内的表达式时,这意味着我们可以在字符串内使用变量、调用函数等。
示例
let a = 5; let b = 10; console.log(`Using Template literal : Value is ${a + b}.`); console.log("Using normal way : Value is " + (a + b));
输出
Using Template literal : Value is 15. Using normal way : Value is 15
ES6 - 模板字面量
let a = 5; let b = 10; console.log(`Using Template literal : Value is ${a + b}.`); console.log("Using normal way : Value is " + (a + b));
命令
npx babel templateliteral.js --out-file templateliteral_es5.js
BabelJS - ES5
"use strict"; var a = 5; var b = 10; console.log("Using Template literal : Value is " + (a + b) + "."); console.log("Using normal way : Value is " + (a + b));
增强对象字面量
在 es6 中,添加到对象字面量的新特性非常棒且实用。我们将逐步了解 ES5 和 ES6 中对象字面量的几个示例。
示例
ES5 var red = 1, green = 2, blue = 3; var rgbes5 = { red: red, green: green, blue: blue }; console.log(rgbes5); // {red: 1, green: 2, blue: 3} ES6 let rgbes6 = { red, green, blue }; console.log(rgbes6); // {red: 1, green: 2, blue: 3}
如果查看以上代码,ES5 和 ES6 中的对象有所不同。在 ES6 中,如果变量名与键相同,则不必指定键值。
让我们看看使用 babel 编译到 ES5 的结果。
ES6-增强对象字面量
const red = 1, green = 2, blue = 3; let rgbes5 = { red: red, green: green, blue: blue }; console.log(rgbes5); let rgbes6 = { red, green, blue }; console.log(rgbes6); let brand = "carbrand"; const cars = { [brand]: "BMW" } console.log(cars.carbrand); //"BMW"
命令
npx babel enhancedobjliteral.js --out-file enhancedobjliteral_es5.js
BabelJS - ES5
"use strict"; function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } var red = 1, green = 2, blue = 3; var rgbes5 = { red: red, green: green, blue: blue }; console.log(rgbes5); var rgbes6 = { red: red, green: green, blue: blue }; console.log(rgbes6); var brand = "carbrand"; var cars = _defineProperty({}, brand, "BMW"); console.log(cars.carbrand); //"BMW"
默认、剩余和扩展属性
在本节中,我们将讨论默认、剩余和扩展属性。
默认
使用 ES6,我们可以对函数参数使用默认参数,如下所示。
示例
let add = (a, b = 3) => { return a + b; } console.log(add(10, 20)); // 30 console.log(add(10)); // 13
让我们使用 babel 将以上代码转换为 ES5。
命令
npx babel default.js --out-file default_es5.js
BabelJS - ES5
"use strict"; var add = function add(a) { var b = arguments.length > 1 >> arguments[1] !== undefined ? arguments[1] : 3; return a + b; }; console.log(add(10, 20)); console.log(add(10));
剩余
剩余参数以三个点(...)开头,如下面的示例所示。
示例
let add = (...args) => { let sum = 0; args.forEach(function (n) { sum += n; }); return sum; }; console.log(add(1, 2)); // 3 console.log(add(1, 2, 5, 6, 6, 7)); //27
在以上函数中,我们向 add 函数传递了 n 个参数。如果在 ES5 中添加所有这些参数,则必须依赖 arguments 对象来获取参数的详细信息。使用 ES6,rest 可以帮助使用三个点定义参数,如上所示,我们可以遍历它并获得数字的总和。
注意 - 使用三个点(即剩余参数)时,不能使用其他参数。
示例
let add = (...args, value) => { //syntax error let sum = 0; args.forEach(function (n) { sum += n; }); return sum; };
以上代码将导致语法错误。
编译到 es5 的结果如下。
命令
npx babel rest.js --out-file rest_es5.js
Babel -ES5
"use strict"; var add = function add() { for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } var sum = 0; args.forEach(function (n) { sum += n; }); return sum; }; console.log(add(1, 2)); console.log(add(1, 2, 5, 6, 6, 7));
扩展
扩展属性也像剩余参数一样使用三个点。以下是一个工作示例,展示了如何使用扩展属性。
示例
let add = (a, b, c) => { return a + b + c; } let arr = [11, 23, 3]; console.log(add(...arr)); //37
现在让我们看看以上代码是如何使用 babel 转换的。
命令
npx babel spread.js --out-file spread_es5.js
Babel-ES5
"use strict"; var add = function add(a, b, c) { return a + b + c; }; var arr = [11, 23, 3]; console.log(add.apply(undefined, arr));
代理
代理是一个对象,您可以在其中定义属性查找、赋值、枚举、函数、调用等操作的自定义行为。
语法
var a = new Proxy(target, handler);
目标 和 处理程序 都是对象。
目标 是一个对象,也可以是另一个代理元素。
处理程序 将是一个对象,其属性为函数,这些函数将在被调用时提供行为。
让我们尝试通过一个示例来理解这些特性。
示例
let handler = { get: function (target, name) { return name in target ? target[name] : "invalid key"; } }; let o = { name: 'Siya Kapoor', addr: 'Mumbai' } let a = new Proxy(o, handler); console.log(a.name); console.log(a.addr); console.log(a.age);
我们在以上示例中定义了目标和处理程序,并将其与代理一起使用。代理返回带有键值对的对象。
输出
Siya Kapoor Mumbai invalid key
现在让我们看看如何使用 babel 将以上代码转换为 ES5。
命令
npx babel proxy.js --out-file proxy_es5.js
Babel-ES5
'use strict'; var handler = { get: function get(target, name) { return name in target ? target[name] : "invalid key"; } }; var o = { name: 'Siya Kapoor', addr: 'Mumbai' }; var a = new Proxy(o, handler); console.log(a.name); console.log(a.addr); console.log(a.age);
BabelJS - 将 ES6 模块转换为 ES5
在本章中,我们将了解如何使用 Babel 将 ES6 模块转换为 ES5。
模块
考虑这样一种情况:需要重用 JavaScript 代码的部分内容。ES6 通过模块的概念来解决这个问题。
模块只不过是写在文件中的 JavaScript 代码块。除非模块文件导出它们,否则模块中的函数或变量不可用于使用。
简单来说,模块可以帮助您在模块中编写代码,并仅公开代码中其他部分应访问的部分。
让我们考虑一个示例,以了解如何使用模块以及如何导出它以便在代码中使用它。
示例
add.js
var add = (x,y) => { return x+y; } module.exports=add;
multiply.js
var multiply = (x,y) => { return x*y; }; module.exports = multiply;
main.js
import add from './add'; import multiply from './multiply' let a = add(10,20); let b = multiply(40,10); console.log("%c"+a,"font-size:30px;color:green;"); console.log("%c"+b,"font-size:30px;color:green;");
我有三个文件:add.js 用于添加两个给定数字,multiply.js 用于将两个给定数字相乘,以及 main.js,它调用 add 和 multiply 并输出控制台。
为了在 main.js 中使用 add.js 和 multiply.js,我们必须首先导出它们,如下所示。
module.exports = add; module.exports = multiply;
要在 main.js 中使用它们,我们需要导入它们,如下所示。
import add from './add'; import multiply from './multiply'
我们需要模块打包器来构建文件,以便我们可以在浏览器中执行它们。
我们可以这样做:
- 使用 Webpack
- 使用 Gulp
ES6 模块和 Webpack
在本节中,我们将了解 ES6 模块是什么。我们还将学习如何使用 webpack。
在开始之前,我们需要安装以下包。
npm install --save-dev webpack npm install --save-dev webpack-dev-server npm install --save-dev babel-core npm install --save-dev babel-loader npm install --save-dev babel-preset-env
Package.json
我们在脚本中添加了 pack 和 publish 任务,以便使用 npm 运行它们。以下是 webpack.config.js 文件,它将构建最终文件。
webpack.config.js
var path = require('path'); module.exports = { entry: { app: './src/main.js' }, output: { path: path.resolve(__dirname, 'dev'), filename: 'main_bundle.js' }, mode:'development', module: { rules: [ { test: /\.js$/, include: path.resolve(__dirname, 'src'), loader: 'babel-loader', query: { presets: ['env'] } } ] } };
运行命令 npm run pack 来构建文件。最终文件将存储在 dev/ 文件夹中。
命令
npm run pack
创建了 dev/main_bundle.js 通用文件。此文件将 add.js、multiply.js 和 main.js 组合在一起,并将其存储在 dev/main_bundle.js 中。
/******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ /******/ // Check if module is in cache /******/ if(installedModules[moduleId]) { /******/ return installedModules[moduleId].exports; /******/ } /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ i: moduleId, /******/ l: false, /******/ exports: {} /******/ }; /******/ /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ /******/ // Flag the module as loaded /******/ module.l = true; /******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ /******/ /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; /******/ /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; /******/ /******/ // define getter function for harmony exports /******/ __webpack_require__.d = function(exports, name, getter) { /******/ if(!__webpack_require__.o(exports, name)) { /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); /******/ } /******/ }; /******/ /******/ // define __esModule on exports /******/ __webpack_require__.r = function(exports) { /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); /******/ } /******/ Object.defineProperty(exports, '__esModule', { value: true }); /******/ }; /******/ /******/ // create a fake namespace object /******/ // mode & 1: value is a module id, require it /******/ // mode & 2: merge all properties of value into the ns /******/ // mode & 4: return value when already ns object /******/ // mode & 8|1: behave like require /******/ __webpack_require__.t = function(value, mode) { /******/ if(mode & 1) value = __webpack_require__(value); /******/ if(mode & 8) return value; /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; /******/ var ns = Object.create(null); /******/ __webpack_require__.r(ns); /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); /******/ return ns; /******/ }; /******/ /******/ // getDefaultExport function for compatibility with non-harmony modules /******/ __webpack_require__.n = function(module) { /******/ var getter = module && module.__esModule ? /******/ function getDefault() { return module['default']; } : /******/ function getModuleExports() { return module; }; /******/ __webpack_require__.d(getter, 'a', getter); /******/ return getter; /******/ }; /******/ /******/ // Object.prototype.hasOwnProperty.call /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; /******/ /******/ // __webpack_public_path__ /******/ __webpack_require__.p = ""; /******/ /******/ /******/ // Load entry module and return exports /******/ return __webpack_require__(__webpack_require__.s = "./src/main.js"); /******/ }) /************************************************************************/ /******/ ({ /***/ "./src/add.js": /*!********************!*\ !*** ./src/add.js ***! \********************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; eval( "\n\nvar add = function add(x, y) {\n return x + y;\n}; \n\nmodule.exports = add; \n\n//# sourceURL = webpack:///./src/add.js?" ); /***/ }), /***/ "./src/main.js": /*!*********************!*\ !*** ./src/main.js ***! \*********************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; eval( "\n\nvar _add = __webpack_require__(/*! ./add */ \"./src/add.js\"); \n\nvar _add2 = _interopRequireDefault(_add); \n\nvar _multiply = __webpack_require__(/*! ./multiply */ \"./src/multiply.js\"); \n\nvar _multiply2 = _interopRequireDefault(_multiply); \n\nfunction _interopRequireDefault(obj) { return obj >> obj.__esModule ? obj : { default: obj }; } \n\nvar a = (0, _add2.default)(10, 20); \nvar b = (0, _multiply2.default)(40, 10); \n\nconsole.log(\"%c\" + a, \"font-size:30px;color:green;\"); \nconsole.log(\"%c\" + b, \"font-size:30px;color:green;\"); \n\n//# sourceURL = webpack:///./src/main.js?" ); /***/ }), /***/ "./src/multiply.js": /*!*************************!*\ !*** ./src/multiply.js ***! \*************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; eval( "\n\nvar multiply = function multiply(x, y) {\n return x * y;\n}; \n\nmodule.exports = multiply; \n\n//# sourceURL = webpack:///./src/multiply.js?" ); /***/ }) /******/ });
命令
以下是在浏览器中测试输出的命令。
npm run publish
在您的项目中添加 index.html。它调用 dev/main_bundle.js。
<html> <head></head> <body> <script type="text/javascript" src="dev/main_bundle.js"></script> </body> </html>
输出
ES6 模块和 Gulp
要使用 Gulp 将模块捆绑到一个文件中,我们将使用 browserify 和 babelify。首先,我们将创建项目设置并安装所需的包。
命令
npm init
在开始项目设置之前,我们需要安装以下包。
npm install --save-dev gulp npm install --save-dev babelify npm install --save-dev browserify npm install --save-dev babel-preset-env npm install --save-dev babel-core npm install --save-dev gulp-connect npm install --save-dev vinyl-buffer npm install --save-dev vinyl-source-stream
安装后的 package.json
现在让我们创建 gulpfile.js,它将帮助运行将模块捆绑在一起的任务。我们将使用上面与 webpack 一起使用的相同文件。
示例
add.js
var add = (x,y) => { return x+y; } module.exports=add;
multiply.js
var multiply = (x,y) => { return x*y; }; module.exports = multiply;
main.js
import add from './add'; import multiply from './multiply' let a = add(10,20); let b = multiply(40,10); console.log("%c"+a,"font-size:30px;color:green;"); console.log("%c"+b,"font-size:30px;color:green;");
此处创建了 gulpfile.js。用户将使用 browserify 并使用 transform 转换为 babelify。babel-preset-env 用于将代码转换为 es5。
Gulpfile.js
const gulp = require('gulp'); const babelify = require('babelify'); const browserify = require('browserify'); const connect = require("gulp-connect"); const source = require('vinyl-source-stream'); const buffer = require('vinyl-buffer'); gulp.task('build', () => { browserify('src/main.js') .transform('babelify', { presets: ['env'] }) .bundle() .pipe(source('main.js')) .pipe(buffer()) .pipe(gulp.dest('dev/')); }); gulp.task('default', ['es6'],() => { gulp.watch('src/app.js',['es6']) }); gulp.task('watch', () => { gulp.watch('./*.js', ['build']); }); gulp.task("connect", function () { connect.server({ root: ".", livereload: true }); }); gulp.task('start', ['build', 'watch', 'connect']);
我们使用 browserify 和 babelify 来处理模块导出和导入,并将它们组合到一个文件中,如下所示。
gulp.task('build', () => { browserify('src/main.js') .transform('babelify', { presets: ['env'] }) .bundle() .pipe(source('main.js')) .pipe(buffer()) .pipe(gulp.dest('dev/')); });
我们在 transform 中调用了带有 presets env 的 babelify。
将包含 main.js 的 src 文件夹提供给 browserify 并保存在 dev 文件夹中。
我们需要运行命令 gulp start 来编译文件。
命令
npm start
以下是 dev/ 文件夹中创建的最终文件。
(function() { function r(e,n,t) { function o(i,f) { if(!n[i]) { if(!e[i]) { var c = "function"==typeof require&&require; if(!f&&c)return c(i,!0);if(u)return u(i,!0); var a = new Error("Cannot find module '"+i+"'"); throw a.code = "MODULE_NOT_FOUND",a } var p = n[i] = {exports:{}}; e[i][0].call( p.exports,function(r) { var n = e[i][1][r]; return o(n||r) } ,p,p.exports,r,e,n,t) } return n[i].exports } for(var u="function"==typeof require>>require,i = 0;i<t.length;i++)o(t[i]);return o } return r })() ({1:[function(require,module,exports) { "use strict"; var add = function add(x, y) { return x + y; }; module.exports = add; },{}],2:[function(require,module,exports) { 'use strict'; var _add = require('./add'); var _add2 = _interopRequireDefault(_add); var _multiply = require('./multiply'); var _multiply2 = _interopRequireDefault(_multiply); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var a = (0, _add2.default)(10, 20); var b = (0, _multiply2.default)(40, 10); console.log("%c" + a, "font-size:30px;color:green;"); console.log("%c" + b, "font-size:30px;color:green;"); }, {"./add":1,"./multiply":3}],3:[function(require,module,exports) { "use strict"; var multiply = function multiply(x, y) { return x * y; }; module.exports = multiply; },{}]},{},[2]);
我们将它用于 index.html,并在浏览器中运行它以获取输出。
<html> <head></head> <body> <h1>Modules using Gulp</h1> <script type="text/javascript" src="dev/main.js"></script> </body> </html>
输出
BabelJS - 将 ES7 特性转换为 ES5
在本章中,我们将学习如何将 ES7 特性转换为 ES5。
ECMA Script 7 添加了以下新特性。
- 异步-等待
- 指数运算符
- Array.prototype.includes()
我们将使用 babeljs 将它们编译为 ES5。根据您的项目需求,还可以将代码编译为任何 ecma 版本,例如 ES7 到 ES6 或 ES7 到 ES5。由于 ES5 版本最稳定并且在所有现代和旧版浏览器上都能正常工作,因此我们将代码编译为 ES5。
异步-等待
Async 是一个异步函数,它返回一个隐式 Promise。Promise 要么被 fulfilled 要么被 rejected。异步函数与普通标准函数相同。该函数可以具有 await 表达式,该表达式会暂停执行,直到它返回一个 Promise,一旦获得 Promise,执行就会继续。只有当函数为异步函数时,await 才能工作。
以下是一个关于异步和等待的工作示例。
示例
let timer = () => { return new Promise(resolve => { setTimeout(() => { resolve("Promise resolved after 5 seconds"); }, 5000); }); }; let out = async () => { let msg = await timer(); console.log(msg); console.log("hello after await"); }; out();
输出
Promise resolved after 5 seconds hello after await
在调用 timer 函数之前添加了 await 表达式。timer 函数将在 5 秒后返回 Promise。因此,await 将暂停执行,直到 timer 函数上的 Promise 被 fulfilled 或 rejected,然后继续执行。
现在让我们使用 babel 将以上代码转换为 ES5。
ES7 - 异步-等待
let timer = () => { return new Promise(resolve => { setTimeout(() => { resolve("Promise resolved after 5 seconds"); }, 5000); }); }; let out = async () => { let msg = await timer(); console.log(msg); console.log("hello after await"); }; out();
命令
npx babel asyncawait.js --out-file asyncawait_es5.js
BabelJS - ES5
"use strict"; var timer = function timer() { return new Promise(function (resolve) { setTimeout(function () { resolve("Promise resolved after 5 seconds"); }, 5000); }); }; var out = async function out() { var msg = await timer(); console.log(msg); console.log("hello after await"); }; out();
Babeljs 不会编译对象或方法;因此,此处使用的 Promise 不会被转换,并将按原样显示。为了在旧版浏览器上支持 Promise,我们需要添加代码,这些代码将支持 Promise。现在,让我们安装 babel-polyfill,如下所示。
npm install --save babel-polyfill
它应该被保存为依赖项,而不是开发依赖项。
要在浏览器中运行代码,我们将使用 node_modules\babel-polyfill\dist\polyfill.min.js 中的 polyfill 文件,并使用 script 标签调用它,如下所示。
<!DOCTYPE html> <html> <head> <title>BabelJs Testing</title> </head> <body> <script src="node_modules\babel-polyfill\dist\polyfill.min.js" type="text/javascript"></script> <script type="text/javascript" src="aynscawait_es5.js"></script> </body> </html>
当您运行以上测试页面时,您将在控制台中看到以下输出。
指数运算符
** 是 ES7 中用于幂运算的运算符。以下示例展示了 ES7 中其工作原理,以及使用 babeljs 转换的代码。
示例
let sqr = 9 ** 2; console.log(sqr);
输出
81
ES6 - 幂运算
let sqr = 9 ** 2; console.log(sqr);
要转换幂运算符,我们需要安装一个插件,如下所示。
命令
npm install --save-dev babel-plugin-transform-exponentiation-operator
将插件详细信息添加到 .babelrc 文件中,如下所示。
{ "presets":[ "es2015" ], "plugins": ["transform-exponentiation-operator"] }
命令
npx babel exponeniation.js --out-file exponeniation_es5.js
BabelJS - ES5
"use strict"; var sqr = Math.pow(9, 2); console.log(sqr);
Array.prototype.includes()
如果传递给它的元素存在于数组中,则此特性返回 true,否则返回 false。
示例
let arr1 = [10, 6, 3, 9, 17]; console.log(arr1.includes(9)); let names = ['Siya', 'Tom', 'Jerry', 'Bean', 'Ben']; console.log(names.includes('Tom')); console.log(names.includes('Be'));
输出
true true false
我们必须再次使用 babel-polyfill,因为 includes 是数组上的方法,它不会被转换。我们需要额外的步骤来包含 polyfill 以使其在旧版浏览器中工作。
ES6 - array.includes
let arr1 = [10, 6, 3, 9, 17]; console.log(arr1.includes(9)); let names = ['Siya', 'Tom', 'Jerry', 'Bean', 'Ben']; console.log(names.includes('Tom')); console.log(names.includes('Be'));
命令
npx babel array_include.js --out-file array_include_es5.js
Babel-ES5
'use strict'; var arr1 = [10, 6, 3, 9, 17]; console.log(arr1.includes(9)); var names = ['Siya', 'Tom', 'Jerry', 'Bean', 'Ben']; console.log(names.includes('Tom')); console.log(names.includes('Be'));
要在旧版浏览器中测试它,我们需要使用 polyfill,如下所示。
<!DOCTYPE html> <html> <head> <title>BabelJs Testing</title> </head> <body> <script src="node_modules\babel-polyfill\dist\polyfill.min.js" type="text/javascript"></script> <script type="text/javascript" src="array_include_es5.js"></script> </body> </html>
输出
BabelJS - 将 ES8 特性转换为 ES5
字符串填充是添加到 javascript 中的新 ES8 特性。我们将研究一个简单的示例,该示例将使用 babel 将字符串填充转换为 ES5。
字符串填充
字符串填充根据指定的长度从左侧添加另一个字符串。字符串填充的语法如下所示。
语法
str.padStart(length, string); str.padEnd(length, string);
示例
const str = 'abc'; console.log(str.padStart(8, '_')); console.log(str.padEnd(8, '_'));
输出
_____abc abc_____
ES8 - 字符串填充
const str = 'abc'; console.log(str.padStart(8, '_')); console.log(str.padEnd(8, '_'));
命令
npx babel strpad.js --out-file strpad_es5.js
Babel - ES5
'use strict'; var str = 'abc'; console.log(str.padStart(8, '_')); console.log(str.padEnd(8, '_'));
js 必须与 babel-polyfill 一起使用,如下所示。
test.html
<!DOCTYPE html> <html> <head> <title>BabelJs Testing</title> </head> <body> <script src="node_modules\babel-polyfill\dist\polyfill.min.js" type="text/javascript"></script> <script type="text/javascript" src="strpad_es5.js"></script> </body> </html>
BabelJS - Babel 插件
BabelJS 是一个 JavaScript 编译器,它根据可用的预设和插件更改给定代码的语法。Babel 编译流程涉及以下三个部分。
- 解析
- 转换
- 打印
传递给 Babel 的代码会原样返回,只是语法发生了改变。我们已经看到过将预设添加到 .babelrc 文件中,以将代码从 es6 编译到 es5 或反之亦然。预设只不过是一组插件。如果在编译期间未提供预设或插件的详细信息,Babel 不会进行任何更改。
现在让我们讨论以下插件 -
- transform-class-properties
- Transform-exponentiation-operator
- For-of
- 对象 rest 和扩展
- async/await
现在,我们将创建一个项目设置并使用一些插件进行操作,这将使我们对 Babel 中插件的需求有更清晰的了解。
命令
npm init
我们必须为 Babel 安装所需的包 - Babel CLI、Babel Core、Babel 预设等。
Babel 6 的包
npm install babel-cli babel-core babel-preset-es2015 --save-dev
Babel 7 的包
npm install @babel/cli @babel/core @babel/preset-env --save-dev
在你的项目中创建一个 js 文件并编写你的 js 代码。
类 - Transform-class-properties
为此,请观察以下给出的代码 -
示例
main.js
class Person { constructor(fname, lname, age, address) { this.fname = fname; this.lname = lname; this.age = age; this.address = address; } get fullname() { return this.fname + "-" + this.lname; } } var a = new Person("Siya", "Kapoor", "15", "Mumbai"); var persondet = a.fullname;
目前,我们还没有向 Babel 提供任何预设或插件的详细信息。如果我们碰巧使用以下命令转换代码 -
npx babel main.js --out-file main_out.js
main_out.js
class Person { constructor(fname, lname, age, address) { this.fname = fname; this.lname = lname; this.age = age; this.address = address; } get fullname() { return this.fname + "-" + this.lname; } } var a = new Person("Siya", "Kapoor", "15", "Mumbai"); var persondet = a.fullname;
我们将获得与代码相同的输出。现在让我们将预设添加到 .babelrc 文件中。
注意 - 在项目根目录下创建 .babelrc 文件。
.babelrc for babel 6
.babelrc for babel 7
{ "presets":["@babel/env"] }
我们已经安装了预设;现在让我们再次运行命令 -
npx babel main.js --out-file main_out.js
main_out.js
"use strict"; var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var Person = function () { function Person(fname, lname, age, address) { _classCallCheck(this, Person); this.fname = fname; this.lname = lname; this.age = age; this.address = address; } _createClass(Person, [{ key: "fullname", get: function get() { return this.fname + "-" + this.lname; } }]); return Person; }(); var a = new Person("Siya", "Kapoor", "15", "Mumbai"); var persondet = a.fullname;
在 ES6 中,类语法如下
class Person { constructor(fname, lname, age, address) { this.fname = fname; this.lname = lname; this.age = age; this.address = address; } get fullname() { return this.fname + "-" + this.lname; } }
存在构造函数,并且类的所有属性都在其中定义。如果我们需要在类外部定义类属性,则无法这样做。
示例
class Person { name = "Siya Kapoor"; fullname = () => { return this.name; } } var a = new Person(); var persondet = a.fullname(); console.log("%c"+persondet, "font-size:25px;color:red;");
如果我们碰巧编译上述代码,它将在 Babel 中抛出一个错误。这导致代码无法编译。
为了使其按我们想要的方式工作,我们可以使用名为 babel-plugin-transform-class-properties 的 Babel 插件。为了使其工作,我们需要先安装它,如下所示 -
Babel 6 的包
npm install --save-dev babel-plugin-transform-class-properties
Babel 7 的包
npm install --save-dev @babel/plugin-proposal-class-properties
将插件添加到 .babelrc 文件中以供 Babel 6 使用 -
.babelrc for babel 7
{ "plugins": ["@babel/plugin-proposal-class-properties"] }
现在,我们将再次运行命令。
命令
npx babel main.js --out-file main_out.js
main.js
class Person { name = "Siya Kapoor"; fullname = () => { return this.name; } } var a = new Person(); var persondet = a.fullname(); console.log("%c"+persondet, "font-size:25px;color:red;");
编译到 main_out.js
class Person { constructor() { this.name = "Siya Kapoor"; this.fullname = () => { return this.name; }; } } var a = new Person(); var persondet = a.fullname(); console.log("%c"+persondet, "font-size:25px;color:red;");
输出
以下是我们在浏览器中使用时获得的输出 -
指数运算符 - transform-exponentiation-operator
** 是 ES7 中用于指数运算的运算符。以下示例显示了 ES7 中相同运算符的工作原理。它还展示了如何使用 BabelJS 转换代码。
示例
let sqr = 9 ** 2; console.log("%c"+sqr, "font-size:25px;color:red;");
要转换指数运算符,我们需要安装以下插件 -
Babel 6 的包
npm install --save-dev babel-plugin-transform-exponentiation-operator
Babel 7 的包
npm install --save-dev @babel/plugin-transform-exponentiation-operator
将插件详细信息添加到 .babelrc 文件中,如下所示,以供 Babel 6 使用 -
{ "plugins": ["transform-exponentiation-operator"] }
.babelrc for babel 7
{ "plugins": ["@babel/plugin-transform-exponentiation-operator"] }
命令
npx babel exponeniation.js --out-file exponeniation_out.js
exponeniation_out.js
let sqr = Math.pow(9, 2); console.log("%c" + sqr, "font-size:25px;color:red;");
输出
For-of
Babel 6 和 7 中插件所需的包如下 -
Babel 6
npm install --save-dev babel-plugin-transform-es2015-for-of
Babel 7
npm install --save-dev @babel/plugin-transform-for-of
.babelrc for babel 6
{ "plugins": ["transform-es2015-for-of"] }
.babelrc for babel 7
{ "plugins": ["@babel/plugin-transform-for-of"] }
forof.js
let foo = ["PHP", "C++", "Mysql", "JAVA"]; for (var i of foo) { console.log(i); }
命令
npx babel forof.js --out-file forof_es5.js
Forof_es5.js
let foo = ["PHP", "C++", "Mysql", "JAVA"]; var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = foo[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var i = _step.value; console.log(i); } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } }
输出
对象 rest 和扩展
Babel 6 和 7 中插件所需的包如下 -
Babel 6
npm install --save-dev babel-plugin-transform-object-rest-spread
Babel 7
npm install --save-dev @babel/plugin-proposal-object-rest-spread
.babelrc for babel 6
{ "plugins": ["transform-object-rest-spread"] }
.babelrc for babel 7
{ "plugins": ["@babel/plugin-proposal-object-rest-spread"] }
o.js
let { x1, y1, ...z1 } = { x1: 11, y1: 12, a: 23, b: 24 }; console.log(x1); console.log(y1); console.log(z1); let n = { x1, y1, ...z1}; console.log(n);
命令
npx babel o.js --out-file o_es5.js
o_es5.js
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } let _x1$y1$a$b = { x1: 11, y1: 12, a: 23, b: 24 }, { x1, y1 } = _x1$y1$a$b, z1 = _objectWithoutProperties(_x1$y1$a$b, ["x1", "y1"]); console.log(x1); console.log(y1); console.log(z1); let n = _extends({ x1, y1 }, z1); console.log(n);
输出
async/await
我们需要为 Babel 6 安装以下包 -
npm install --save-dev babel-plugin-transform-async-to-generator
Babel 7 的包
npm install --save-dev @babel/plugin-transform-async-to-generator
.babelrc for babel 6
{ "plugins": ["transform-async-to-generator"] }
.babelrc for babel 7
{ "plugins": ["@babel/plugin-transform-async-to-generator"] }
async.js
let timer = () => { return new Promise(resolve => { setTimeout(() => { resolve("Promise resolved after 5 seconds"); }, 5000); }); }; let out = async () => { let msg = await timer(); console.log(msg); console.log("hello after await"); }; out();
命令
npx babel async.js --out-file async_es5.js
async_es5.js
function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } let timer = () => { return new Promise(resolve => { setTimeout(() => { resolve("Promise resolved after 5 seconds"); }, 5000); }); }; let out = (() => { var _ref = _asyncToGenerator(function* () { let msg = yield timer(); console.log(msg); console.log("hello after await"); }); return function out() { return _ref.apply(this, arguments); }; })(); out();
我们必须为此使用 polyfill,因为它在不支持 Promise 的浏览器中不起作用。
输出
BabelJS - Babel Polyfill
Babel Polyfill 为 Web 浏览器添加了对尚不可用功能的支持。Babel 将代码从最新的 Ecma 版本编译到我们想要的版本。它根据预设更改语法,但无法对使用的对象或方法执行任何操作。我们必须为这些功能使用 polyfill 以实现向后兼容性。
可以进行 polyfill 的功能
以下是当在旧版浏览器中使用时需要 polyfill 支持的功能列表 -
- Promise
- Map
- Set
- Symbol
- Weakmap
- Weakset
- Array.from、Array.includes、Array.of、Array#find、Array.buffer、Array#findIndex
- Object.assign、Object.entries、Object.values
我们将创建项目设置,并查看 Babel Polyfill 的工作原理。
命令
npm init
我们现在将安装 Babel 所需的包。
Babel 6 的包
npm install babel-cli babel-core babel-preset-es2015 --save-dev
Babel 7 的包
npm install @babel/cli @babel/core @babel/preset-env --save-dev
这是最终的 package.json -
我们还将 es2015 添加到预设中,因为我们希望将代码编译到 es5。
.babelrc for babel 6
.babelrc for babel 7
{ "presets":["@babel/env"] }
我们将安装 lite-serve,以便我们可以在浏览器中测试代码 -
npm install --save-dev lite-server
让我们将 Babel 命令添加到 package.json 中以编译我们的代码 -
我们还添加了 build 命令,该命令调用 lite-server。
Babel-polyfill 与 babel-core 包一起安装。babel-polyfill 将在 node_modules 中可用,如下所示 -
我们将进一步研究 Promise 并与之一起使用 babel-polyfill。
ES6 - Promise
let timingpromise = new Promise((resolve, reject) => { setTimeout(function() { resolve("Promise is resolved!"); }, 1000); }); timingpromise.then((msg) => { console.log("%c"+msg, "font-size:25px;color:red;"); });
命令
npx babel promise.js --out-file promise_es5.js
BabelJS - ES5
"use strict"; var timingpromise = new Promise(function (resolve, reject) { setTimeout(function () { resolve("Promise is resolved!"); }, 1000); }); timingpromise.then(function (msg) { console.log("%c"+msg, "font-size:25px;color:red;"); });
编译不需要更改任何内容。Promise 的代码已原样转换。但是,即使我们将代码编译到 es5,不支持 Promise 的浏览器也会抛出错误。
要解决此问题,我们需要在最终的 es5 编译代码中添加 polyfill。要在浏览器中运行代码,我们将从 node_modules 中获取 babel-polyfill 文件并将其添加到我们要使用 Promise 的 .html 文件中,如下所示 -
index.html
<html> <head> </head> <body> <h1>Babel Polyfill Testing</h1> <script type="text/javascript" src="node_modules/babel-polyfill/dist/polyfill.min.js"></script> <script type="text/javascript" src="promise_es5.js"></script> </body> </html>
输出
在 index.html 文件中,我们使用了来自 node_modules 的 polyfill.min.js 文件,然后是 promise_es5.js -
<script type="text/javascript" src="node_modules/babel-polyfill/dist/polyfill.min.js"></script> <script type="text/javascript" src="promise_es5.js"></script>
注意 - polyfill 文件必须在主 JavaScript 调用之前开始使用。
字符串填充
字符串填充根据指定的长度从左侧添加另一个字符串。字符串填充的语法如下所示。
语法
str.padStart(length, string); str.padEnd(length, string);
示例
const str = 'abc'; console.log(str.padStart(8, '_')); console.log(str.padEnd(8, '_'));
输出
_____abc abc_____
Babel - ES5
npx babel strpad.js --out-file strpad_es5.js
命令
'use strict'; var str = 'abc'; console.log(str.padStart(8, '_')); console.log(str.padEnd(8, '_'));
js 必须与 babel-polyfill 一起使用,如下所示。
test.html
<!DOCTYPE html> <html> <head> <title>BabelJs Testing </title> </head> <body> <script src="node_modules/babel-polyfill/dist/polyfill.min.js" type="text/javascript"></script> <script type="text/javascript" src="strpad_es5.js"></script> </body> </html>
Map、Set、WeakSet、WeakMap
在本节中,我们将学习Map、Set、WeakSet、WeakMap。
Map 是一个具有键/值对的对象。
Set 也是一个对象,但具有唯一值。
WeakMap 和 WeakSet 也是具有键/值对的对象。
Map、Set、WeakMap 和 WeakSet 是添加到 ES6 中的新功能。要将其转换为在旧版浏览器中使用,我们需要使用 polyfill。我们将使用一个示例并使用 polyfill 编译代码。
示例
let m = new Map(); //map example m.set("0","A"); m.set("1","B"); console.log(m); let set = new Set(); //set example set.add('A'); set.add('B'); set.add('A'); set.add('B'); console.log(set); let ws = new WeakSet(); //weakset example let x = {}; let y = {}; ws.add(x); console.log(ws.has(x)); console.log(ws.has(y)); let wm = new WeakMap(); //weakmap example let a = {}; wm.set(a, "hello"); console.log(wm.get(a));
输出
Map(2) {"0" => "A", "1" => "B"} Set(2) {"A", "B"} true false hello
命令
npx babel set.js --out-file set_es5.js
Babel-ES5
"use strict"; var m = new Map(); //map example m.set("0", "A"); m.set("1", "B"); console.log(m); var set = new Set(); //set example set.add('A'); set.add('B'); set.add('A'); set.add('B'); console.log(set); var ws = new WeakSet(); //weakset example var x = {}; var y = {}; ws.add(x); console.log(ws.has(x)); console.log(ws.has(y)); var wm = new WeakMap(); //weakmap example var a = {}; wm.set(a, "hello"); console.log(wm.get(a));
js 必须与 babel-polyfill 一起使用,如下所示。
test.html
<!DOCTYPE html> <html> <head> <title>BabelJs Testing</title> </head> <body> <script src="node_modules/babel-polyfill/dist/polyfill.min.js" type="text/javascript"></script> <script type="text/javascript" src="set_es5.js"></script> </body> </html>
输出
数组方法
可以在数组上使用许多属性和方法;例如,array.from、array.includes 等。
让我们考虑使用以下示例来更好地理解这一点。
示例
arraymethods.js
var arrNum = [1, 2, 3]; console.log(arrNum.includes(2)); console.log(Array.from([3, 4, 5], x => x + x));
输出
true [6, 8, 10]
命令
npx babel arraymethods.js --out-file arraymethods_es5.js
Babel-es5
"use strict"; var arrNum = [1, 2, 3]; console.log(arrNum.includes(2)); console.log(Array.from([3, 4, 5], function (x) { return x + x; }));
数组上使用的方法按原样打印。为了使其在旧版浏览器上工作,我们需要在开头添加 polyfill 文件,如下所示 -
index.html
<html> <head></head> <body> <h1>Babel Polyfill Testing</h1> <script type="text/javascript" src="node_modules/babel-polyfill/dist/polyfill.min.js"></script> <script type="text/javascript" src="arraymethods_es5.js"></script> </body> </html>
输出
BabelJS - Babel CLI
BabelJS 带有一个内置的命令行界面,其中可以使用易于使用的命令轻松地将 JavaScript 代码编译到相应的 ECMA Script。我们将在本章中讨论这些命令的使用。
首先,我们将为我们的项目安装 babel-cli。我们将使用 babeljs 编译代码。
为你的项目创建一个文件夹以使用 babel-cli。
命令
npm init
显示
为上述项目创建的 Package.json -
让我们运行命令来安装 babel-cli。
Babel 6 的包
npm install --save-dev babel-cli
Babel 7 的包
npm install --save-dev @babel/cli
显示
我们已经安装了 babel-cli,这是更新后的 package.json -
此外,我们需要安装 babel-preset 和 babel-core。现在让我们看看安装命令。
Babel 6 的包
npm install --save-dev babel-preset-env npm install --save-dev babel-core
Babel 7 的包
npm install --save-dev @babel/core npm install --save-dev @babel/preset-env
这是上述命令的更新后的 package.json -
由于我们需要编译我们将要编写的 JavaScript 代码以具有向后兼容性,因此我们将将其编译为 ECMA Script 5。为此,我们需要指示 Babel 查找预设,即将在其中进行编译的 es 版本。我们需要在创建的项目根目录中创建一个 .babelrc> 文件,如下所示。
它包含一个具有以下预设详细信息的 json 对象 -
{ "presets": ["env"] }
对于 Babel 7,.babelrc 如下所示 -
{ "presets":["@babel/env"] }
我们已将 Babel 本地安装到项目中。为了在我们的项目中使用 Babel,我们需要在 package.json 中指定它,如下所示 -
编译 JS 文件
现在我们准备编译我们的 JavaScript 文件了。在你的项目中创建一个名为 src 的文件夹;在这个文件夹中,创建一个名为 main.js 的文件并编写如下所示的 es6 javascript 代码 -
命令
npx babel src/main.js
输出
在上述情况下,来自 main.js 的代码在终端中以 es5 版本显示。来自 es6 的箭头函数转换为 es5,如上所示。我们将存储在不同的文件中,而不是在终端中显示编译后的代码,如下所示。
我们在项目中创建了一个名为 out 的文件夹,我们希望将编译后的文件存储在其中。以下命令将编译并将输出存储在我们想要的位置。
命令
npx babel src/main.js --out-file out/main_out.js
输出
命令中的 --out-file 选项帮助我们将输出存储在我们选择的文件夹位置。
如果我们希望每次更改主要文件时都更新文件,请将 --watch 或 -w 选项添加到命令中,如下所示。
命令
npx babel src/main.js --watch --out-file out/main_out.js
输出
你可以对主要文件进行更改;此更改将反映在编译后的文件中。
在上述情况下,我们更改了日志消息,并且 --watch 选项持续检查是否有任何更改,并在编译后的文件中添加了相同的更改。
编译后的文件
在我们之前的章节中,我们学习了如何编译单个文件。现在,我们将编译一个目录并将编译后的文件存储在另一个目录中。
在 src 文件夹中,我们将创建另一个 js 文件,名为 main1.js。目前,src 文件夹中有 2 个 javascript 文件 main.js 和 main1.js。
以下是文件中的代码 -
main.js
var arrowfunction = () => { console.log("Added changes to the log message"); }
main1.js
var handler = () => { console.log("Added one more file"); }
以下命令将编译来自 src 文件夹的代码并将其存储到 out/ 文件夹中。我们已从 out/ 文件夹中删除所有文件并将其清空。我们将运行该命令并检查 out/ 文件夹中的输出。
命令
npx babel src --out-dir out
我们在 out 文件夹中得到了 2 个文件 - main.js 和 main1.js
main.js
"use strict"; var arrowfunction = function arrowfunction() { console.log("Added changes to the log message"); };
main1.js
"use strict"; var handler = function handler() { console.log("Added one more file"); };
接下来,我们将执行以下命令以使用 babeljs 将这两个文件编译成一个文件。
命令
npx babel src --out-file out/all.js
输出
"use strict"; var arrowfunction = function arrowfunction() { console.log("Added changes to the log message"); }; "use strict"; var handler = function handler() { console.log("Added one more file"); };
如果我们希望忽略某些文件不被编译,我们可以使用 --ignore 选项,如下所示。
命令
npx babel src --out-file out/all.js --ignore src/main1.js
输出
all.js
"use strict"; var arrowfunction = function arrowfunction() { console.log("Added changes to the log message"); };
我们可以使用插件选项在文件编译期间使用。要使用插件,我们需要安装它,如下所示。
命令
npm install --save-dev babel-plugin-transform-exponentiation-operator
expo.js
let sqr = 9 ** 2; console.log(sqr);
命令
npx babel expo.js --out-file expo_compiled.js --plugins=babel-plugin-transform-exponentiation-operator
输出
"use strict"; var sqr = Math.pow(9, 2); console.log(sqr);
我们也可以在命令中使用预设,如下所示。
命令
npx babel src/main.js --out-file main_es5.js --presets=es2015
为了测试上述情况,我们已从 .babelrc 中删除了预设选项。
main.js
var arrowfunction = () => { console.log("Added changes to the log message"); }
main_es5.js
"use strict"; var arrowfunction = function arrowfunction() { console.log("Added changes to the log message"); };
我们也可以从命令行忽略 .babelrc,如下所示 -
npx babel --no-babelrc src/main.js --out-file main_es5.js --presets=es2015
为了测试上述情况,我们已将预设添加回 .babelrc,并且由于我们在命令中添加了 --no-babelrc,因此它将被忽略。main_es5.js 文件的详细信息如下 -
main_es5.js
"use strict"; var arrowfunction = function arrowfunction() { console.log("Added changes to the log message"); };
BabelJS - Babel 预设
Babel 预设是 Babel 转换器的配置详细信息,告诉它以指定的模式进行转换。以下是一些我们将在本章中讨论的最流行的预设 -
- ES2015
- Env
- React
我们需要使用包含我们希望代码转换到的环境的预设。例如,es2015 预设会将代码转换为 es5。值为 env 的预设也会转换为 es5。它还具有其他功能,即选项。如果您希望该功能在最新版本的浏览器上受支持,则 Babel 仅在这些浏览器不支持该功能时才会转换代码。使用 react 预设,Babel 会将代码转换为 React 代码。
要使用预设,我们需要在项目根文件夹中创建一个 .babelrc 文件。为了展示其工作原理,我们将创建一个如下所示的项目结构。
命令
npm init
我们必须按照如下方式安装所需的 Babel 预设,以及 Babel CLI、Babel Core 等。
Babel 6 包
npm install babel-cli babel-core babel-preset-es2015 --save-dev
Babel 7 包
npm install @babel/cli @babel/core @babel/preset-env --save-dev
注意 - babel-preset-es2015 从 Babel 7 开始已弃用。
es2015 或 @babel/env
在项目的根目录中创建 .babelrc 文件 (Babel 6) -
在 .babelrc 中,预设为 es2015。这表示我们希望 Babel 编译器将代码转换为 es2015。
对于 Babel 7,我们需要按如下方式使用预设 -
{ "presets":["@babel/env"] }
以下是安装后的 package.json -
由于我们已在本地安装了 Babel,因此我们在 package.json 的 scripts 部分添加了 Babel 命令。
让我们做一个简单的示例来检查使用 es2015 预设进行转译。
示例
main.js
let arrow = () => { return "this is es6 arrow function"; }
转译为 es5,如下所示。
命令
npx babel main.js --out-file main_es5.js
main_es5.js
"use strict"; var arrow = function arrow() { return "this is es6 arrow function"; };
Env
使用 Env 预设,您可以指定您希望最终代码转译到的环境。
我们将使用上面创建的相同的项目结构,并将预设从 es2015 更改为 env,如下所示。
此外,我们需要安装 babel-preset-env。我们将执行以下命令来安装它。
命令
npm install babel-preset-env --save-dev
我们将再次编译 main.js 并查看输出。
main.js
let arrow = () => { return "this is es6 arrow function"; }
命令
npx babel main.js --out-file main_env.js
main_env.js
"use strict"; var arrow = function arrow() { return "this is es6 arrow function"; };
我们看到转译后的代码是 es5。如果我们知道代码将执行的环境,我们可以使用此预设来指定它。例如,如果我们将浏览器指定为 Chrome 和 Firefox 的最后 1 个版本,如下所示。
命令
npx babel main.js --out-file main_env.js
main_env.js
"use strict"; let arrow = () => { return "this is es6 arrow function"; };
我们现在获得的箭头函数语法保持不变。它没有被转译成 ES5 语法。这是因为我们希望代码支持的环境已经支持箭头函数。
Babel 使用 babel-preset-env 处理基于环境的代码编译。我们还可以根据 Node.js 环境来指定编译目标,如下所示
代码的最终编译结果如下所示。
命令
npx babel main.js --out-file main_env.js
main_env.js
"use strict"; let arrow = () => { return "this is es6 arrow function"; };
Babel 根据当前 Node.js 版本编译代码。
React 预设
当我们使用 React.js 时,可以使用 React 预设。我们将做一个简单的示例,并使用 React 预设查看输出。
要使用预设,我们需要安装 babel-preset-react (Babel 6),如下所示 -
npm install --save-dev babel-preset-react
对于 Babel 7,如下所示 -
npm install --save-dev @babel/preset-react
对于 Babel 6,.babelrc 的更改如下 -
对于 Babel 7
{ "presets": ["@babel/preset-react"] }
main.js
<h1>Hello, world!</h1>
命令
npx babel main.js --out-file main_env.js
main_env.js
React.createElement( "h1", null, "Hello, world!" );
使用预设:react,main.js 中的代码被转换为 React.js 语法。
BabelJS - 使用 Babel 和 Webpack
Webpack 是一个模块打包器,它将所有模块及其依赖项(js、样式、图像等)打包成静态资源 .js、.css、.jpg、.png 等。Webpack 带有预设,有助于将代码编译成所需的格式。例如,React 预设有助于将最终输出转换为 React 格式,es2015 或 env 预设有助于将代码编译为 ES5 或 6 或 7 等。我们在项目设置中使用了 Babel 6。如果您想切换到 Babel 7,请使用 @babel/babel-package-name 安装 Babel 的所需包。
这里,我们将讨论使用 Babel 和 Webpack 的项目设置。创建一个名为 的文件夹,并在 Visual Studio IDE 中打开它。
要创建项目设置,请运行 npm init babel webpack,如下所示 -
以下是 npm init 创建后的 package.json -
现在,我们将安装使用 Babel 和 Webpack 所需的包。
npm install --save-dev webpack npm install --save-dev webpack-dev-server npm install --save-dev babel-core npm install --save-dev babel-loader npm install --save-dev babel-preset-env
以下是安装后的 Package.json -
现在,我们将创建一个 webpack.config.js 文件,其中包含打包 js 文件的所有详细信息。这些文件将使用 Babel 编译成 es5。
要使用服务器运行 Webpack,我们使用 webpack-server。以下是添加到其中的详细信息 -
我们添加了 publish 命令,它将启动 webpack-dev-server 并更新最终文件存储的路径。现在我们将用于更新最终文件的路径是 /dev 文件夹。
要使用 Webpack,我们需要运行以下命令 -
npm run publish
首先我们需要创建 webpack.config.js 文件。这些文件将包含 Webpack 工作的配置详细信息。
文件中的详细信息如下 -
var path = require('path'); module.exports = { entry: { app: './src/main.js' }, output: { path: path.resolve(__dirname, 'dev'), filename: 'main_bundle.js' }, mode:'development', module: { rules: [ { test: /\.js$/, include: path.resolve(__dirname, 'src'), loader: 'babel-loader', query: { presets: ['env'] } } ] } };
文件的结构如上所示。它以 path 开头,提供当前路径的详细信息。
var path = require('path'); //gives the current path
接下来是 module.exports 对象,它具有 entry、output 和 module 属性。entry 是起点。在这里,我们需要提供要编译的主要 js 文件。
entry: { app: './src/main.js' },
path.resolve(_dirname, ‘src/main.js’) -- 将在目录中查找 src 文件夹,并在该文件夹中查找 main.js。
输出
output: { path: path.resolve(__dirname, 'dev'), filename: 'main_bundle.js' },
Output 是一个包含 path 和 filename 属性的对象。Path 将保存编译文件所在的文件夹,filename 将告诉您在 .html 文件中使用的最终文件名。
module
module: { rules: [ { test: /\.js$/, include: path.resolve(__dirname, 'src'), loader: 'babel-loader', query: { presets: ['env'] } } ] }
Module 是一个包含规则详细信息的对象。它具有以下属性 -
- test
- include
- loader
- query
Test 将保存所有以 .js 结尾的 js 文件的详细信息。它具有模式,将在给定的入口点中查找结尾处的 .js。
Include 指示要查看的文件使用的文件夹。
Loader 使用 babel-loader 来编译代码。
Query 具有 presets 属性,它是一个数组,其值为 env - es5 或 es6 或 es7。
创建 src 文件夹和 main.js 文件;在其中编写您的 ES6 代码。稍后,运行命令以查看它如何使用 Webpack 和 Babel 编译为 es5。
src/main.js
let add = (a,b) => { return a+b; }; let c = add(10, 20); console.log(c);
运行以下命令 -
npm run pack
编译后的文件如下所示 -
dev/main_bundle.js
!function(e) { var t = {}; function r(n) { if(t[n])return t[n].exports;var o = t[n] = {i:n,l:!1,exports:{}}; return e[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports } r.m = e,r.c = t,r.d = function(e,t,n) { r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n}) }, r.r = function(e) { "undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0}) }, r.t = function(e,t) { if(1&t&&(e = r(e)),8&t)return e; if(4&t&&"object"==typeof e&&e&&e.__esModule)return e; var n = Object.create(null); if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)r.d(n,o,function(t) {return e[t]}.bind(null,o)); return n }, r.n = function(e) { var t = e&&e.__esModule?function() {return e.default}:function() {return e}; return r.d(t,"a",t),t }, r.o = function(e,t) {return Object.prototype.hasOwnProperty.call(e,t)}, r.p = "",r(r.s = 0) }([function(e,t,r) {"use strict";var n = function(e,t) {return e+t}(10,20);console.log(n)}]); !function(e) { var t = {}; function r(n) { if(t[n])return t[n].exports; var o = t[n] = {i:n,l:!1,exports:{}}; return e[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports } r.m = e,r.c = t,r.d = function(e,t,n) { r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n}) }, r.r = function(e) { "undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0}) }, r.t = function(e,t) { if(1&t&&(e=r(e)), 8&t)return e; if(4&t&&"object"==typeof e&&e&&e.__esModule)return e; var n = Object.create(null); if( r.r(n), Object.defineProperty(n,"default",{enumerable:!0,value:e}), 2&t&&"string"!=typeof e ) for(var o in e)r.d(n,o,function(t) {return e[t]}.bind(null,o)); return n }, r.n = function(e) { var t = e&&e.__esModule?function() {return e.default}:function() {return e}; return r.d(t,"a",t),t }, r.o = function(e,t) { return Object.prototype.hasOwnProperty.call(e,t) }, r.p = "",r(r.s = 0) }([function(e,t,r) { "use strict"; var n = function(e,t) {return e+t}(10,20); console.log(n) }]);
代码如上所示编译。Webpack 添加了一些内部所需的代码,并且 main.js 中的代码位于末尾。我们已经像上面那样控制台输出了值。
在 .html 文件中添加最终的 js 文件,如下所示 -
<html> <head></head> <body> <script type="text/javascript" src="dev/main_bundle.js"></script> </body> </html>
运行以下命令 -
npm run publish
要检查输出,我们可以在以下地址打开文件 -
https://127.0.0.1:8080/
我们得到如上所示的控制台值。现在让我们尝试使用 Webpack 和 Babel 将代码编译成单个文件。
我们将使用 Webpack 将多个 js 文件捆绑到一个文件中。Babel 将用于将 es6 代码编译为 es5。
现在,我们在 src/ 文件夹中有 2 个 js 文件 - main.js 和 Person.js,如下所示 -
person.js
export class Person { constructor(fname, lname, age, address) { this.fname = fname; this.lname = lname; this.age = age; this.address = address; } get fullname() { return this.fname +"-"+this.lname; } }
我们使用了 export 来使用 Person 类的详细信息。
main.js
import {Person} from './person' var a = new Person("Siya", "Kapoor", "15", "Mumbai"); var persondet = a.fullname; console.log(persondet);
在 main.js 中,我们从文件路径导入了 Person。
注意 - 我们不必包含 person.js,只需文件名即可。我们创建了一个 Person 类的对象,并如上所示控制台输出了详细信息。
Webpack 将合并 person.js 和 main.js,并在 dev/main_bundle.js 中更新为一个文件。运行命令 npm run publish 以在浏览器中检查输出 -
BabelJS - 使用 Babel 和 JSX
在本章中,我们将了解使用 JSX 和 Babel 的方法。在深入了解细节之前,让我们先了解什么是 JSX。
什么是 JSX?
JSX 是一种 JavaScript 代码,其中包含 XML 语法。JSX 标签具有标签名称、属性和子元素,使其看起来像 XML。
React 使用 JSX 进行模板化,而不是普通的 JavaScript。这不是必须的,但是,以下是一些随之而来的优点。
它更快,因为它在将代码编译为 JavaScript 时执行优化。
它也是类型安全的,大多数错误可以在编译时被捕获。
如果您熟悉 HTML,它使编写模板变得更容易和更快。
我们在项目设置中使用了 Babel 6。如果您想切换到 Babel 7,请使用 @babel/babel-package-name 安装 Babel 的所需包。
我们将创建项目设置并使用 Webpack 将 JSX 与 React 编译成正常的 JavaScript,使用 Babel。
要启动项目设置,请运行以下命令以安装 Babel、React 和 Webpack。
命令
npm init
现在,我们将安装使用 Babel、Webpack 和 JSX 所需的包 -
npm install --save-dev webpack npm install --save-dev webpack-cli npm install --save-dev webpack-dev-server npm install --save-dev babel-core npm install --save-dev babel-loader npm install --save-dev babel-preset-es2015 npm install --save-dev babel-preset-react npm install --save-dev react npm install --save-dev react-dom
以下是安装后的 package.json -
现在将创建一个 webpack.config.js 文件,其中包含打包 js 文件的所有详细信息,并使用 Babel 将其编译成 es5。
要使用服务器运行 Webpack,有一个名为 webpack-server 的工具。我们添加了一个名为 publish 的命令;此命令将启动 webpack-dev-server 并更新最终文件存储的路径。现在我们将用于更新最终文件的路径是 /dev 文件夹。
要使用 Webpack,我们需要运行以下命令 -
npm run publish
我们将创建 webpack.config.js 文件,其中包含 Webpack 工作的配置详细信息。
文件中的详细信息如下 -
var path = require('path'); module.exports = { entry: { app: './src/main.js' }, output: { path: path.resolve(__dirname, 'dev'), filename: 'main_bundle.js' }, mode:'development', module: { rules: [ { test:/\.(js|jsx)$/, include: path.resolve(__dirname, 'src'), loader: 'babel-loader', query: { presets: ['es2015','react'] } } ] } };
文件的结构如上所示。它以 path 开头,提供当前路径的详细信息。
var path = require('path'); //gives the current path
接下来是 module.exports 对象,它具有 entry、output 和 module 属性。
Entry 是起点。在这里,我们需要提供要编译的主要 js 文件。
entry: { app: './src/main.js' },
path.resolve(_dirname, ‘src/main.js’) -- 将在目录中查找 src 文件夹,并在该文件夹中查找 main.js。
输出
output: { path: path.resolve(__dirname, 'dev'), filename: 'main_bundle.js' },
Output 是一个包含 path 和 filename 属性的对象。Path 将保存编译文件所在的文件夹,filename 将告诉您在 .html 文件中使用的最终文件名。
module
module: { rules: [ { test:/\.(js|jsx)$/, include: path.resolve(__dirname, 'src'), loader: 'babel-loader', query: { presets: ['es2015','react'] } } ] }
模块是一个包含规则细节的对象,它具有属性,例如 test、include、loader 和 query。
Test 将保存所有以 .js 和 .jsx 结尾的 js 文件的详细信息。它具有一个模式,将在给定的入口点中查找结尾处的 .js 和 .jsx。
Include 指示用于查找文件的文件夹。
Loader 使用 babel-loader 来编译代码。
Query 具有属性 presets,它是一个数组,其值为 env – es5 或 es6 或 es7。我们使用了 es2015 和 react 作为预设。
创建文件夹 src/。在其中添加 main.js 和 App.jsx。
App.jsx
import React from 'react'; class App extends React.Component { render() { var style = { color: 'red', fontSize: 50 }; return ( <div style={style}> Hello World!!! </div> ); } } export default App;
main.js
import React from 'react'; import ReactDOM from 'react-dom'; import App from './App.jsx'; ReactDOM.render(, document.getElementById('app'));
运行以下命令来打包 .js 文件并使用预设 es2015 和 react 进行转换。
命令
npm run pack
将 dev 文件夹中的 main_bundle.js 添加到 index.html 中 -
<!DOCTYPE html> <html lang = "en"> <head> <meta charset = "UTF-8"> <title>React App</title> </head> <body> <div id = "app"></div> <script src = "dev/main_bundle.js"></script> </body> </html>
命令
npm run publish
输出
BabelJS - 使用 Babel 和 Flow
Flow 是 JavaScript 的静态类型检查器。要使用 Flow 和 Babel,我们将首先创建一个项目设置。我们在项目设置中使用了 Babel 6。如果您想切换到 Babel 7,请使用 @babel/babel-package-name 安装 Babel 的必需包。
命令
npm init
安装 Flow 和 Babel 的必需包 -
npm install --save-dev babel-core babel-cli babel-preset-flow flow-bin babel-plugin-transform-flow-strip-types
这是安装后的最终 package.json。还添加了 Babel 和 Flow 命令,以便在命令行中执行代码。
在项目设置内创建 .babelrc,并添加如下所示的预设
创建一个 main.js 文件,并使用 Flow 编写您的 JavaScript 代码 -
main.js
/* @flow */ function concat(a: string, b: string) { return a + b; } let a = concat("A", "B"); console.log(a);
使用 Babel 命令编译代码,使用预设:将 Flow 转换为普通 JavaScript
npx babel main.js --out-file main_flow.js
main_flow.js
function concat(a, b) { return a + b; } let a = concat("A", "B"); console.log(a);
我们还可以使用名为 babel-plugin-transform-flow-strip-types 的插件来代替预设,如下所示 -
在 .babelrc 中,添加如下所示的插件 -
main.js
/* @flow */ function concat(a: string, b: string) { return a + b; } let a = concat("A", "B"); console.log(a);
命令
npx babel main.js --out-file main_flow.js
main_flow.js
function concat(a, b) { return a + b; } let a = concat("A", "B"); console.log(a);
BabelJS - 使用 BabelJS 和 Gulp
在本章中,我们将使用 Babel 和 Gulp 创建项目设置。Gulp 是一个使用 Node.js 作为平台的任务运行器。Gulp 将运行将 JavaScript 文件从 es6 转换为 es5 的任务,完成后将启动服务器以测试更改。我们在项目设置中使用了 Babel 6。如果您想切换到 Babel 7,请使用 @babel/babel-package-name 安装 Babel 的必需包。
我们将首先使用 npm 命令创建项目,并安装所需的包以开始。
命令
npm init
我们创建了一个名为 gulpbabel 的文件夹。接下来,我们将安装 Gulp 和其他必需的依赖项。
命令
npm install gulp --save-dev npm install gulp-babel --save-dev npm install gulp-connect --save-dev npm install babel-preset-env --save-dev npm install babel-core --save-dev
我们将如下所示将预设环境详细信息添加到 .babelrc 文件中
gulpfile.js
var gulp =require('gulp'); var babel =require('gulp-babel'); var connect = require("gulp-connect"); gulp.task('build', () => { gulp.src('src/./*.js') .pipe(babel()) .pipe(gulp.dest('./dev')) }); gulp.task('watch', () => { gulp.watch('./*.js', ['build']); }); gulp.task("connect", function () { connect.server({ root: ".", livereload: true }); }); gulp.task('start', ['build', 'watch', 'connect']);
我们在 Gulp 中创建了三个任务:[‘build’,’watch’,’connect’]。src 文件夹中所有可用的 js 文件将使用 Babel 转换为 es5,如下所示 -
gulp.task('build', () => { gulp.src('src/./*.js') .pipe(babel()) .pipe(gulp.dest('./dev')) });
最终更改存储在 dev 文件夹中。Babel 使用 .babelrc 中的预设详细信息。如果您想更改为其他预设,可以在 .babelrc 文件中更改详细信息。
现在,我们将使用 es6 javascript 在 src 文件夹中创建一个 .js 文件,并运行 gulp start 命令来执行更改。
src/main.js
class Person { constructor(fname, lname, age, address) { this.fname = fname; this.lname = lname; this.age = age; this.address = address; } get fullname() { return this.fname +"-"+this.lname; } }
命令:gulp start
dev/main.js
这是使用 Babel 转换的 -
"use strict"; var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i <props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var Person = function () { function Person(fname, lname, age, address) { _classCallCheck(this, Person); this.fname = fname; this.lname = lname; this.age = age; this.address = address; } _createClass(Person, [{ key: "fullname", get: function get() { return this.fname + "-" + this.lname; } }]); return Person; }();
Index.html
这是使用 转换后的 dev/main.js 完成的 -
<html> <head></head> <body> <script type="text/javascript" src="dev/main.js"></script> <h1 id="displayname"></h1> <script type="text/javascript"> var a = new Student("Siya", "Kapoor", "15", "Mumbai"); var studentdet = a.fullname; document.getElementById("displayname").innerHTML = studentdet; </script> </body> </html>
输出
BabelJS - 示例
我们将使用 ES6 功能并创建一个简单的项目。Babeljs 将用于将代码编译为 ES5。该项目将包含一组图像,这些图像将在固定时间间隔后自动滑动。我们将使用 ES6 类来处理它。我们在项目设置中使用了 Babel 6。如果您想切换到 Babel 7,请使用 @babel/babel-package-name 安装 Babel 的必需包。
自动滑动图像
我们将使用 Gulp 来构建项目。首先,我们将创建如下所示的项目设置
命令
npm init
我们创建了一个名为 babelexample 的文件夹。接下来,我们将安装 Gulp 和其他必需的依赖项。
命令
npm install gulp --save-dev npm install gulp-babel --save-dev npm install gulp-connect --save-dev npm install babel-preset-env --save-dev
以下是安装后的 Package.json -
我们将如下所示将预设环境详细信息添加到 .babelrc 文件中 -
由于我们需要 Gulp 任务来构建最终文件,因此我们将创建包含所需任务的 gulpfile.js
gulpfile.js
var gulp = require('gulp'); var babel = require('gulp-babel'); var connect = require("gulp-connect"); gulp.task('build', () => { gulp.src('src/./*.js') .pipe(babel()) .pipe(gulp.dest('./dev')) }); gulp.task('watch', () => { gulp.watch('./*.js', ['build']); }); gulp.task("connect", function () { connect.server({ root: ".", livereload: true }); }); gulp.task('start', ['build', 'watch', 'connect']);
我们在 Gulp 中创建了三个任务,[‘build’,’watch’,’connect’]。src 文件夹中所有可用的 js 文件将使用 Babel 转换为 es5,如下所示
gulp.task('build', () => { gulp.src('src/./*.js') .pipe(babel()) .pipe(gulp.dest('./dev')) });
最终更改存储在 dev 文件夹中。Babel 使用 .babelrc 中的预设详细信息。如果您想更改为其他预设,可以在 .babelrc 文件中更改详细信息。
现在,我们将使用 es6 JavaScript 在 src 文件夹中创建一个 .js 文件,并运行 gulp start 命令来执行更改。
项目结构如下所示 -
src/slidingimage.js
class SlidingImage { constructor(width, height, imgcounter, timer) { this.counter = 0; this.imagecontainerwidth = width; this.imagecontainerheight = height; this.slidercounter = imgcounter; this.slidetimer = timer; this.startindex = 1; this.css = this.applycss(); this.maincontainer = this.createContainter(); this.childcontainer = this.imagecontainer(); this.autoslide(); } createContainter() { let maindiv = document.createElement('div'); maindiv.id = "maincontainer"; maindiv.class = "maincontainer"; document.body.appendChild(maindiv); return maindiv; } applycss() { let slidercss = ".maincontainer{ position : relative; margin :auto;}.left, .right { cursor: pointer; position: absolute;" + "top: 50%; width: auto; padding: 16px; margin-top: -22px; color: white; font-weight: bold; " + "font-size: 18px; transition: 0.6s ease; border-radius: 0 3px 3px 0; }.right { right: 0; border-radius: 3px 0 0 3px;}" + ".left:hover, .right:hover { background-color: rgba(0,0,0,0.8);}"; let style = document.createElement('style'); style.id = "slidercss"; style.type = "text/css"; document.getElementsByTagName("head")[0].appendChild(style); let styleall = style; if (styleall.styleSheet) { styleall.styleSheet.cssText = slidercss; } else { let text = document.createTextNode(slidercss); style.appendChild(text); } } imagecontainer() { let childdiv = []; let imgcont = []; for (let a = 1; a >= this.slidercounter; a++) { childdiv[a] = document.createElement('div'); childdiv[a].id = "childdiv" + a; childdiv[a].style.width = this.imagecontainerwidth + "px"; childdiv[a].style.height = this.imagecontainerheight + "px"; if (a > 1) { childdiv[a].style.display = "none"; } imgcont[a] = document.createElement('img'); imgcont[a].src = "src/img/img" + a + ".jpg"; imgcont[a].style.width = "100%"; imgcont[a].style.height = "100%"; childdiv[a].appendChild(imgcont[a]); this.maincontainer.appendChild(childdiv[a]); } } autoslide() { console.log(this.startindex); let previousimg = this.startindex; this.startindex++; if (this.startindex > 5) { this.startindex = 1; } setTimeout(() => { document.getElementById("childdiv" + this.startindex).style.display = ""; document.getElementById("childdiv" + previousimg).style.display = "none"; this.autoslide(); }, this.slidetimer); } } let a = new SlidingImage(300, 250, 5, 5000);
我们将创建 src/ 中的 img/ 文件夹,因为我们需要显示图像;这些图像需要每 5 秒旋转一次。dev/ 文件夹将存储编译后的代码。运行 gulp start 以构建最终文件。
最终项目结构如下所示 -
在 slidingimage.js 中,我们创建了一个名为 SlidingImage 的类,该类具有诸如 createcontainer、imagecontainer 和 autoslide 等方法,这些方法创建主容器并将图像添加到其中。autoslide 方法有助于在指定的时间间隔后更改图像。
let a = new SlidingImage(300, 250, 5, 5000);
在此阶段,将调用该类。我们将传递 宽度、高度、图像数量和旋转图像的秒数。
命令
gulp start
dev/slidingimage.js
"use strict"; var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var SlidingImage = function () { function SlidingImage(width, height, imgcounter, timer) { _classCallCheck(this, SlidingImage); this.counter = 0; this.imagecontainerwidth = width; this.imagecontainerheight = height; this.slidercounter = imgcounter; this.slidetimer = timer; this.startindex = 1; this.css = this.applycss(); this.maincontainer = this.createContainter(); this.childcontainer = this.imagecontainer(); this.autoslide(); } _createClass(SlidingImage, [{ key: "createContainter", value: function createContainter() { var maindiv = document.createElement('div'); maindiv.id = "maincontainer"; maindiv.class = "maincontainer"; document.body.appendChild(maindiv); return maindiv; } }, { key: "applycss", value: function applycss() { var slidercss = ".maincontainer{ position : relative; margin :auto;}.left, .right { cursor: pointer; position: absolute;" + "top: 50%; width: auto; padding: 16px; margin-top: -22px; color: white; font-weight: bold; " + "font-size: 18px; transition: 0.6s ease; border-radius: 0 3px 3px 0; } .right { right: 0; border-radius: 3px 0 0 3px;}" + ".left:hover, .right:hover { background-color: rgba(0,0,0,0.8);}"; var style = document.createElement('style'); style.id = "slidercss"; style.type = "text/css"; document.getElementsByTagName("head")[0].appendChild(style); var styleall = style; if (styleall.styleSheet) { styleall.styleSheet.cssText = slidercss; } else { var text = document.createTextNode(slidercss); style.appendChild(text); } } }, { key: "imagecontainer", value: function imagecontainer() { var childdiv = []; var imgcont = []; for (var _a = 1; _a <= this.slidercounter; _a++) { childdiv[_a] = document.createElement('div'); childdiv[_a].id = "childdiv" + _a; childdiv[_a].style.width = this.imagecontainerwidth + "px"; childdiv[_a].style.height = this.imagecontainerheight + "px"; if (_a > 1) { childdiv[_a].style.display = "none"; } imgcont[_a] = document.createElement('img'); imgcont[_a].src = "src/img/img" + _a + ".jpg"; imgcont[_a].style.width = "100%"; imgcont[_a].style.height = "100%"; childdiv[_a].appendChild(imgcont[_a]); this.maincontainer.appendChild(childdiv[_a]); } } }, { key: "autoslide", value: function autoslide() { var _this = this; console.log(this.startindex); var previousimg = this.startindex; this.startindex++; if (this.startindex > 5) { this.startindex = 1; } setTimeout(function () { document.getElementById("childdiv" + _this.startindex).style.display = ""; document.getElementById("childdiv" + previousimg).style.display = "none"; _this.autoslide(); }, this.slidetimer); } }]); return SlidingImage; }(); var a = new SlidingImage(300, 250, 5, 5000);
我们将如下所示在浏览器中测试代码行 -
index.html
<html> <head></head> <body> <script type="text/javascript" src="dev/slidingimage.js"></script> <h1>Sliding Image Demo</h1> </body> </html>
我们在 index.html 中使用了 dev 文件夹中的编译文件。命令 gulp start 启动服务器,我们可以在其中测试输出。
在 Chrome 中
在 Firefox 中
在 Internet Explorer 中
编译后的代码在所有浏览器中都能正常工作。