由于 markdown 排版问题建议从掘金阅读:https://juejin.cn/post/6902323049513615374

目录

  • 前言
  • babel 是什么
  • babel 能做什么
  • 工作流程
  • 解析 Parse
  • 转换 Transform
  • 生成 Generator
  • 使用方式
  • babel-standalone
    • 介绍
    • 版本
    • 示例
    • 问答
    • 补充
  • cli 命令
    • 介绍
    • 安装
    • 使用
    • 问答
  • 作为构建工具的插件
  • 模块介绍
  • babel-node
  • 版本升级
  • 问答
  • 总结

前言

babel 是什么

Babel 是一个 JavaScript 编译器

这是babel 官网对 babel 一句短而精的定义, 该如何理解这句话的含义呢?首先定义它为一个编译器,其次只对 JavaScript 语言负责.

关于编译器概念可参考维基百科https://bk.tw.lvfukeji.com/wiki/%E7%BC%96%E8%AF%91%E5%99%A8

babel 能做什么

这里我们只需要知道 babel 作为 JavaScript 编译器的工作流程:解析->转换->生成.

通俗的可以理解为 babel 负责把 JavaScript 高级语法、新增 API 转换为低规范以保障能够在低版本的环境下正常执行,接下来我们看 babel 是如何工作的.

工作流程

解析 Parse

万事开头难,第一步的解析工作该由谁完成?

babylon

Babylon 是一款 JavaScript 解析器.

babel 本身是不负责解析工作的,而是调用了 babylon.parse 方法对源码进行词法解析生成 AST 树.

转换 Transform

babel-traverse

babel-traverse 负责遍历 AST 树进行增删改的操作.

从第一步获取到 AST 树之后,调用 babel-traverse 库提供的 traverse 方法对树进行更新.

babel-types

一个基于 AST 树的工具库(可对节点增删改查校验).babel-traverse 对 AST 树进行操作的时候便使用了此库.

生成 Generator

最后一步将更新之后的 AST 树进行生成代码.

babel-generator

对外提供 generator 方法接收 ast 参数返回值为改变之后的源码.

以上则是对 babel 编译器整个流程大概的描述信息.所以 babel 是由一系列动作配合完成的.

使用方式

babel-standalone

介绍

由于 babel 是基于 node 环境下运行,对于非 node 环境(如浏览器),babel-standalone这个开源项目提供了 babel.min.js 可通过<script>方式引入使用.

题外话:babel-standalone已加入了babel大家族(上岸成为有编制一员),以后下载的 7.x 版本 babel 包内可以看到它的身影.

版本

| 名称 | 版本 | 体积 | 备注 | 在线地址 | | ------------ | ------ | ------ | ------ | ------------------------------------------------------- | | babel.js | 6.26.0 | 1.78MB | 未压缩 | https://unpkg.com/babel-standalone@6.26.0/babel.js | | babel.min.js | 6.26.0 | 773KB | 已压缩 | https://unpkg.com/babel-standalone@6.26.0/babel.min.js | | babel.js | 7.12.9 | 3.1MB | 未压缩 | https://unpkg.com/@babel/standalone@7.12.9/babel.js | | babel.min.js | 7.12.9 | 1.6MB | 已压缩 | https://unpkg.com/@babel/standalone@7.12.9/babel.min.js |

示例

  • 示例一 es6 转码
  • 使用<script>引入在线地址或者下载之后本地引用.
  • 将编写的 es6 代码放入<script type="text/babel">内,需要注意一点type 类型为 text/babel.
<!DOCTYPE html>
<html><head><meta charset="utf-8" /><title>babel-standalone es6 转码</title><script src="https://unpkg.com/@babel/standalone@7.12.9/babel.min.js"></script></head><body><div id="output"></div><script type="text/babel">const getMsg = () => {const name = 'Babel';document.getElementById('output').innerHTML = `Hello ${name} version:${Babel.version}`;};getMsg();</script></body>
</html>

  • 示例二 模拟在线实时转码用户输入的脚本
  • 这种方式适用于一些在线转码的场景:
    • babel 官网首页
  • babel-repl 在线转码
  • JSFiddle
  • JSBin

以上这些均引入babel.min.js(可能引入的名称或版本不一样)通过调用Babel对象提供的各种 API(如transformdisableScriptTagstransformScriptTags...)实现在线实时转码.

<!DOCTYPE html>
<html><head><meta charset="utf-8" /><title>babel-standalone 模拟在线实时转码用户输入的脚本</title><script src="https://unpkg.com/@babel/standalone@7.12.9/babel.min.js"></script></head><body>输入:<textarea id="input" style="width: 100%" rows="15">class UserInfo{constructor(name='张三') {this.name = name;}getUserName(){return `${this.name}`;}}const user=new UserInfo('张三');console.log(user.getUserName());</textarea>实时转码:<pre id="output"></pre><script>var inputEl = document.getElementById('input');var outputEl = document.getElementById('output');function transform() {try {outputEl.innerHTML = Babel.transform(inputEl.value, {presets: ['es2015',['stage-2',{decoratorsBeforeExport: false,},],],}).code;} catch (e) {outputEl.innerHTML = 'ERROR: ' + e.message;}}inputEl.addEventListener('keyup', transform, false);transform();</script></body>
</html>

  • 示例三 import、export 的使用

以上示例都是通过内嵌的方式在页面直接写 es6 代码,但实际开发中有可能需要以外链的方式引入脚本,所以我们看会遇到哪些问题.

<!DOCTYPE html>
<html><head><meta charset="utf-8" /><title>babel-standalone import、export 的使用</title><script src="https://unpkg.com/@babel/standalone@7.12.9/babel.min.js"></script></head><body><div id="output"></div><script type="text/babel" src="./index.js"></script></body>
</html>
// index.js
const getMsg = () => {const name = 'Babel';document.getElementById('output').innerHTML = `Hello ${name} version:${Babel.version}`;
};
getMsg();

把示例一从内嵌方式修改为外链引入脚本证明没问题.但我们不止编写一个 index.js 脚本,对于使用 import、export 这些 es6 语法是否也支持?

<!DOCTYPE html>
<html><head><meta charset="utf-8" /><title>babel-standalone import、export 的使用</title><script src="https://unpkg.com/@babel/standalone@7.12.9/babel.min.js"></script></head><body><div id="output"></div><script type="text/babel">export default {name: '小朋友',age: 18,};</script></body>
</html>

首先我们以内嵌方式运行之后抛错Uncaught ReferenceError: exports is not defined,这里抛出exports未定义而不是 es6 的export未定义,由此说明内部是要把 es6 代码转换 CommonJS 模块规范(印证了前面介绍中提到过的由于 babel 是基于 node 环境下运行),而我们是需要在浏览器执行的,所以babel-standalone项目提供的babel.min.js包含了 babel 用到的所有插件(各种特性、规范),可以直接配置为 umd 模式即可.

6.x 版本配置data-plugins="transform-es2015-modules-umd"

7.x 版本配置data-plugins="transform-modules-umd"

<!DOCTYPE html>
<html><head><meta charset="utf-8" /><title>babel-standalone import、export 的使用</title><script src="https://unpkg.com/@babel/standalone@7.12.9/babel.min.js"></script></head><body><div id="output"></div><script type="text/babel" data-plugins="transform-modules-umd">export default {name: '小朋友',age: 18,};</script></body>
</html>

既然可以定义export导出那该如何import导入呢?这里babel-standalone又给我们提供了data-module定义导出的模块名称,然后导入即可.

<!DOCTYPE html>
<html><head><meta charset="utf-8" /><title>babel-standalone import、export 的使用</title><script src="https://unpkg.com/@babel/standalone@7.12.9/babel.min.js"></script></head><body><div id="output"></div><scripttype="text/babel"data-plugins="transform-modules-umd"data-module="userInfo">export default {name: '小朋友',age: 18,};</script><script type="text/babel" data-plugins="transform-modules-umd">import userInfo from 'userInfo';document.getElementById('output').innerHTML = `Hello ${userInfo.name}`;</script></body>
</html>

这一些似乎都没发现问题,难道真的没有什么问题?那直接修改为外链的方式呢.

<!DOCTYPE html>
<html><head><meta charset="utf-8" /><title>babel-standalone import、export 的使用</title><script src="https://unpkg.com/@babel/standalone@7.12.9/babel.min.js"></script></head><body><div id="output"></div><scripttype="text/babel"data-plugins="transform-modules-umd"src="./userInfo.js"></script><script type="text/babel" data-plugins="transform-modules-umd">import userInfo from 'userInfo';document.getElementById('output').innerHTML = `Hello ${userInfo.name}`;</script></body>
</html>
// userInfo.js
export default {name: '小朋友',age: 18,
};

如果仔细看上面这段代码的话,有没有发现script标签内缺少了属性data-module定义模块名称,依然可以正常执行呢?

划重点,babel.min.js内部获取script标签之后对属性做了判断,如果有src属性则使用属性值作为模块名称(如src="./userInfo.js"最终以userInfo作为模块名称),如果没有src属性则获取data-module属性值作为模块名称,所以如果使用外链方式的话是不需要data-module属性的(即使配置了也无效).

上面示例演示了 export 可以使用外链的方式,那import又如何使用外链方式呢?

<!DOCTYPE html>
<html><head><meta charset="utf-8" /><title>babel-standalone import、export 的使用</title><script src="https://unpkg.com/@babel/standalone@7.12.9/babel.min.js"></script></head><body><div id="output"></div><scripttype="text/babel"data-plugins="transform-modules-umd"src="./userInfo.js"></script><scripttype="text/babel"data-plugins="transform-modules-umd"src="./index.js"></script></body>
</html>
// userInfo.js
export default {name: '小朋友',age: 18,
};
// index.js
import userInfo from 'userInfo';
document.getElementById('output').innerHTML = `Hello ${userInfo.name}`;

import 的使用方式同export的方式是一样的,这样就完成了以外链的方式引入脚本.

问答

感觉示例部分关于import export修改外链的方式一直提起有什么问题,结尾也没发现什么坑?

说这个问题之前,大家是否考虑过如果没有外链引入<script src="./userInfo.js">,只有<script src="./index.js">会怎样?在index.js内部已经通过import userInfo from 'userInfo';导入,是否可以不需要外链的方式引入,如果import导入多个 js 又会怎样?

稳住.所以拎到问答部分单独聊...

<!DOCTYPE html>
<html><head><meta charset="utf-8" /><title>babel-standalone import、export 的使用</title><script src="https://unpkg.com/@babel/standalone@7.12.9/babel.min.js"></script></head><body><div id="output"></div><scripttype="text/babel"data-plugins="transform-modules-umd"src="./index.js"></script></body>
</html>
// index.js
import userInfo from 'userInfo';
document.getElementById('output').innerHTML = `Hello ${userInfo.name}`;

如上面的示例的,直接外链引入index.js,抛出Uncaught TypeError: Cannot read property 'name' of undefined错误,原因是userInfoundefined所以userInfo.name也无法取到值.

那我们就从转码开始入手.

// index.js 转码之后
(function (global, factory) {if (typeof define === 'function' && define.amd) {define(['userInfo'], factory);} else if (typeof exports !== 'undefined') {factory(require('userInfo'));} else {var mod = {exports: {},};factory(global.userInfo);global.index = mod.exports;}
})(typeof globalThis !== 'undefined'? globalThis: typeof self !== 'undefined'? self: this,function (_userInfo) {'use strict';_userInfo = _interopRequireDefault(_userInfo);function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { default: obj };}document.getElementById('output').innerHTML = 'Hello '.concat(_userInfo['default'].name);}
);

我们对比一下index.js转码前后:

| 转码前 | 转码后 | | ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | | import userInfo from 'userInfo'; | _userInfo = _interopRequireDefault(_userInfo); function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { default: obj };} |

我们看到转码之后的代码通过_interopRequireDefault(_userInfo)函数对_userInfo重新赋值的操作.(_interopRequireDefault函数的作用判断对象是否需要添加default属性).

划重点:这里插一段为什么会有__esModuledefault属性,首先在本节开头提到过由于 babel 是基于 node 环境下运行,所以 babel 是要把 es6 的模块转换为 CommonJS 的形式,那么就需要了解两者的区别.

| | 导出 | 导入 | | -------- | ------------------------------- | ------------------------ | | es6 | exportexport default | import {}import | | CommonJS | module.exports | require |

通过对比发现 es6 的导出、导入可以是多种形式,而 CommonJS 则是单一的对象导出、导入.所以 babel 要把 es6 转换 CommonJS 的形式就需要一些辅助改动.

关于模块对象添加__esModule属性,是为了标记此模块是否被转码,如果有此属性则直接调用模块(exports)的default属性导出对象(babel 会把 es6 的export default默认导出对象转码为 exports.default的形式,同时这种写法又符合 CommonJS 的规范module.exports = exports.default),主要是做到 es6 转码后与 CommonJS 规范的一致性.

关于default属性,上面介绍了是有__esModule属性的情况下,如果没有__esModule属性说明没有对该模块进行转换(有可能是一个第三方模块)对于这种情况直接调用模块(exports)的default属性会为undefined,所以这种情况就直接返回一个对象并且该对象添加一个default属性,把属性值指向自己(如上面这句转码之后的代码return obj && obj.__esModule ? obj : { default: obj })

快醒醒,这两个属性不是这里的重点,还记得问题是什么吗?userInfo为什么是undefined,看完转码之后的代码,我们只需要知道一点import只是导入而已,至于导入的对象是否存在,是不属于转码的职责所在(转码不会检测导入的对象否存在...),还是继续查找userInfo在哪里定义的吧...

继续看转码之后的代码发现在开头有if...else if...else对各种环境(AMD、CommonJS、UMD)做判断,由于我们是浏览器内执行(UMD 模式),所以进入else里在global.userInfo全局对象上有个userInfo,至此得出一个结论,在外链方式引入的脚本内直接使用import导入对象引用,而外部无任何声明export,此对象是undefined(其实在 AMD 的define(['userInfo'], factory)、CommonJS 的require('userInfo')也是同理).

简单一句话:无论通过哪种形式引用,必须要声明,所以外链的方式还是需要script声明.

简单一句话:无论通过哪种形式引用,必须要声明,所以外链的方式还是需要script声明.

简单一句话:无论通过哪种形式引用,必须要声明,所以外链的方式还是需要script声明.

此处使用的声明可能用词不太准确,但相信看到这里应该可以意会到.

<!DOCTYPE html>
<html><head><meta charset="utf-8" /><title>babel-standalone import、export 的使用</title><script src="https://unpkg.com/@babel/standalone@7.12.9/babel.min.js"></script></head><body><div id="output"></div><scripttype="text/babel"data-plugins="transform-modules-umd"src="./userInfo.js"></script><scripttype="text/babel"data-plugins="transform-modules-umd"src="./index.js"></script></body>
</html>
// userInfo.js
export default {name: '小朋友',age: 18,
};
// index.js
import userInfo from 'userInfo';
document.getElementById('output').innerHTML = `Hello ${userInfo.name}`;
// userInfo.js 转码后
(function (global, factory) {if (typeof define === 'function' && define.amd) {define(['exports'], factory);} else if (typeof exports !== 'undefined') {factory(exports);} else {var mod = {exports: {},};factory(mod.exports);global.userInfo = mod.exports;}
})(typeof globalThis !== 'undefined'? globalThis: typeof self !== 'undefined'? self: this,function (_exports) {'use strict';Object.defineProperty(_exports, '__esModule', {value: true,});_exports['default'] = void 0;var _default = {name: '小朋友',age: 18,};_exports['default'] = _default;}
);
// index.js 转码之后
(function (global, factory) {if (typeof define === 'function' && define.amd) {define(['userInfo'], factory);} else if (typeof exports !== 'undefined') {factory(require('userInfo'));} else {var mod = {exports: {},};factory(global.userInfo);global.index = mod.exports;}
})(typeof globalThis !== 'undefined'? globalThis: typeof self !== 'undefined'? self: this,function (_userInfo) {'use strict';_userInfo = _interopRequireDefault(_userInfo);function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { default: obj };}document.getElementById('output').innerHTML = 'Hello '.concat(_userInfo['default'].name);}
);

继上一个问题,如果外链引入了userInfo.jsindex.js里没有import userInfo from 'userInfo';又如何呢?

对于这个问题,请品一下,上面对__esModuledefault属性的介绍,就是那段这两个属性不是这里的重点,现在是这个问题的答案.

babel-standalone 如何使用多个import export.

其实和上面的示例是一样的,只需要外链多个script即可.

<!DOCTYPE html>
<html><head><meta charset="utf-8" /><title>babel-standalone 如何使用多个import、export</title><script src="https://unpkg.com/@babel/standalone@7.12.9/babel.min.js"></script></head><body><div id="output"></div><scripttype="text/babel"data-plugins="transform-modules-umd"src="./other.js"></script><scripttype="text/babel"data-plugins="transform-modules-umd"src="./userInfo.js"></script><scripttype="text/babel"data-plugins="transform-modules-umd"src="./index.js"></script></body>
</html>
// other.js
export function random() {return Math.floor(Math.random() * 10);
}export const randomStr = '幸运数字:';
// userInfo.js
export default {name: '小朋友',age: 18,
};
// index.js
import { randomStr, random } from 'other';
import userInfo from 'userInfo';
function init() {document.getElementById('output').innerHTML = `Hello ${userInfo.name} ${randomStr} ${random()}`;
}init();

补充

对于开发者来说这种直接编写 es6 代码实时转码比较方便,同时也耗时影响性能,所以开发环境可以使用,对于生产环境还是推荐加载转码之后的脚本.

You are using the in-browser Babel transformer. Be sure to precompile your scripts for production——官网建议.

cli

介绍

CLI:命令行界面(英语:Command-Line Interface,缩写:CLI)是在图形用户界面得到普及之前使用最为广泛的用户界面,它通常不支持鼠标,用户通过键盘输入指令,计算机接收到指令后,予以执行.

关于 CLI 概念可参考维基百科https://bk.tw.lvfukeji.com/wiki/CLI

babel 内置的 CLI, 可直接在命令行转码文件.

安装

安装 babel cli之前先检查是否安装nodenpm(前面有提到过 babel 是基于 node 环境下运行,所以自行检索安装步骤).

babel cli分为以下两种安装方式:

  1. 全局安装:npm install --global babel-cli项目运行需要依赖全局安装,且如果多个项目依赖的版本不一致的话,无法解决...
  2. 局部安装:npm install --save-dev babel-cli直接在项目内安装,完全解决全局安装的问题.

建议局部安装,且下面的使用示例均为局部安装.

使用

在介绍使用之前,请先准备好项目环境.

  1. 创建项目.
  2. 项目中需包含package.json文件(自己新建一个)

关于 package.json的相关配置可参考https://docs.npmjs.com/cli/v6/configuring-npm/package-json

接下来正式进入babel cli的使用.

项目目录结构如下:

|--babel-cli 项目名称|-- package.json
// package.json
{"name": "cli"
}

  1. 使用命令进入项目 cd babel-cli
  2. 执行局部安装命令 npm install --save-dev babel-cli

安装完成之后项目目录结构如下:

|--babel-cli 项目名称|-- package.json|-- package-lock.json 记录安装模块的版本、来源信息|-- node_modules node 依赖模块集合|-- babel-cli cli模块|-- babel-* 以babel开头的各个模块后面会介绍
// package.json
{"name": "cli","devDependencies": {"babel-cli": "^6.26.0"}
}

至此所有的配置、安装已完成,接下来我们在项目中创建一个脚本文件(script.js),并且执行转码.

// script.js
const hello = 'Hello';[1, 2, 3, 4].forEach((item) => console.log(item));

执行命令进行转码...

  • 转码输出到 stdout(标准输出).

npx babel script.js

  • 转码输出到指定文件.

npx babel script.js --out-file script-compiled.js

  • 转码某个目录到指定目录

npx babel src --out-dir lib

以上就是关于babel cli的简单使用,更多配置可参考官网https://babel.docschina.org/docs/en/babel-cli/

问答

全局安装、局部安装、npx、 npm 有什么区别?

从安装方式来说babel cli有两种(全局安装、局部安装)上面提到过,安装完之后如何执行命令转码,同样也分为两种:

  1. 全局安装之后直接执行babel命令如(babel script.js),它是找全局node_modules/babel-cli/bin/babel.js执行.
  2. 局部安装之后需要使用npxnpm执行,它则是查找当前项目下的node_modules/.bin/babel命令执行(最终执行的是项目下的node_modules/babel-cli/bin/babel.js),

全局、局部唯一区别是查找的路径不同.

全局、局部唯一区别是查找的路径不同.

全局、局部唯一区别是查找的路径不同.

接下来对比一下npxnpm的区别.

想要使用npm运行命令转码则需要配置package.jsonscripts对象,关于 scripts的相关配置可参考https://docs.npmjs.com/cli/v6/commands/npm-run-script

// package.json
{"name": "cli","devDependencies": {"babel-cli": "^6.26.0"},"scripts": {"babel": "babel script.js","babel-compiled": "babel script.js --out-file script-compiled.js"}
}

如上面的使用示例可以通过配置package.jsonscripts对象,命令行进入项目目录,通过执行命令npm run babelnpm run babel-compiled实现转码.

如果不配置scripts对象就无法使用npm吗?答案是可以的,使用起来稍微麻烦一点,由于npm是查找的项目目录下node_modules/.bin/babel命令执行,所以我们可以在命令行手动调用node_modules/.bin/babel scripts.js实现转码.

有什么办法既可以不需要命令行每次都输入node_modules/...这一堆,也不需要配置scripts对象.答案就是npx,它直接查找项目下的node_modules/.bin对应的命令执行,无需我们手动输入或配置scripts对象.(不信你看上面的使用部分,就是直接使用的npx).

即安装了全局,又安装了局部,npxnpm该如何查找node_modules

上面的一个问题第 2 点提到查找当前项目下的node_modules这是不严谨的,应该是由近到远,如果项目没有node_modules模块集合,才查找全局.

为什么上面的使用示例输出的代码没有转码?

// 转码前
const hello = 'Hello';[1, 2, 3, 4].forEach((item) => console.log(item));
// 转码后
const hello = 'Hello';[1, 2, 3, 4].forEach((item) => console.log(item));

这里只对babel cli做一个初步了解,关于(语法、新特性)转码、配置文件后面会介绍,另外如果开发工具库babel cli还是比较适合的.

作为构建工具的插件

介绍

现在一些构建工具集成了 babel 或提供了配置方式,这些插件只是配置方式不同,如同babel cli一样 无论全局、局部(npx、npm)哪种方式最终的转码流程都是一样,所以这里不对插件的配置使用做介绍.

webpack=>babel-loaderhttps://www.webpackjs.com/loaders/babel-loader/

gulp=>gulp-babelhttps://www.npmjs.com/package/gulp-babel

rollup=>rollup-plugin-babelhttps://github.com/rollup/rollup-plugin-babel

未完待续.

babel import语法 js_Babel 的理解相关推荐

  1. babel import语法 js_搭建开发JS库的运行环境

    1.npm 首先在自定义的目录下打开终端执行 npm init : 根据对应的步骤生成相应的package.json 文件 . 2.Eslint (代码检查工具) 安装eslint:npm insta ...

  2. ES6 模块加载export 、import、export default 、import() 语法与区别,笔记总结

    ES6模块加载export .import.export default .import() 语法与区别 在 ES6 之前,社区制定了一些模块加载方案,最主要的有 CommonJS 和 AMD 两种. ...

  3. python3基础语法-Python3的一些基础语法介绍和理解

    作者:心叶 时间:2018-04-23 22:18 此处长期维护一些对帮助快速使用python3的一些基础语法,方便日常算法练习使用. 控制语法 break 语句可以跳出 for 和 while 的循 ...

  4. python import from class_Python: import vs from (module) import function(class) 的理解

    Python: Import vs From (module) import function(class) 本文涉及的 Python 基本概念: Module Class import from . ...

  5. c 定义结构体时提示应输入声明_C|语法的合理性理解和分析

    试想如果你作为C语言或C语言编译器的的设计者,肯定不会任意设置语法规则,除了考虑不能有歧义以外,还会考虑其合理性. 1 效率是第一位的,安全处于次要位置 了解C语言"效率第一.安全次之&qu ...

  6. cv::Mat dst 这句话从语法是怎么理解?

    c++中的双冒号表示一种作用于域的概念,在这里,cv其实可以理解为一个命名空间,具体的可以参考我写的博客 http://blog.csdn.net/wenhao_ir/article/details/ ...

  7. 关于css 的AST 语法树的理解

    css 处理插件大致分为压缩css和给css添加浏览器兼容前缀. cssmin 可以压缩css,大致原理是将使用正则将css 中的注释和空格删除. px2rem 插件是将css 中的px 转换为 re ...

  8. python中import as的浅显理解

    在python中import A as B调用A给B,即导入A 的包给B. B.X的形式是调用A库中的库函数X,使用库中的X函数.

  9. Python打印杨辉三角-生成器语法yield的理解

    ###先看代码. def triangles():# 定义最初的数据 1 ,存到列表中lt = [1]# 进入循环while True:# 使用yield语句产生一个生成器,返回当前列表yield l ...

最新文章

  1. imutils用法总结
  2. AQS理解之三,由刚才写的锁转变成一个公平锁
  3. 【Zookeeper】zookeeper客户端KeeperErrorCode = ConnectionLoss
  4. 进程和线程的区别【转】
  5. python买卖股票_用Python买卖股票III的最佳时间
  6. 第三方登录页面java_第三方登录接口使用说明(JAVA)
  7. java 动态报表 sql,报表SQL
  8. 项目中出现npm WARN locking errno: -4048, npm WARN locking code: ‘EPERM‘, npm WARN locking syscall:
  9. 第五届强网杯全国网络安全挑战赛writeup
  10. 逆变器LCL滤波器参数设计(一)
  11. wordpress后台打开速度非常慢怎么办
  12. Git 工具之储藏与清理-7.3
  13. 美信监控易:石油销售公司全省IT一体化运维解决方案
  14. 乱象?真象!——中国公有云服务市场大起底
  15. 经典Vue面试题一起学起来
  16. 类的设计和实现II---销售数据统计
  17. 永恒之蓝黑脏牛提权范围
  18. 2021年起重机司机(限桥式起重机)考试题及起重机司机(限桥式起重机)模拟考试
  19. 解决谷歌浏览器升级后,selenium无法使用的问题
  20. 国产PIE-SAR软件

热门文章

  1. linux sit0 wifi,I.MX6 AW-NB177NF wifi HAL 调试修改(示例代码)
  2. 用c++做贪吃蛇_用世界公认的变态羊毛做袜子!不用插电恒温37°C,还能抑菌99%...
  3. 问题 H: 方块填数(2012年蓝桥决赛第5题--dfs)
  4. 离线实时一体化数仓与湖仓一体—云原生大数据平台的持续演进
  5. 一文揭秘阿里实时计算Blink核心技术:如何做到唯快不破?
  6. UI自学宝典,完整UI学习线路图
  7. 将表导入到其他用户的impdp命令
  8. GoldenGate学习笔记(11)_常用参数
  9. oracle 后台进程(background process)详解
  10. 59. Spiral Matrix II ***