前言
在使用 React 或 Vue.js 开发前端应用时,经常会使用 ES6 类语法定义组件,然后通过 Babel 进行转义以兼容低版本浏览器。但是,当我们在 Babel 转义时使用了“transform-class-properties”插件时,可能会遇到一些问题,本文将介绍这些问题的解决方案。
问题描述
在使用 Babel 进行转义时,当使用了“transform-class-properties”插件进行转义时,会出现类似下面的错误:
TypeError: Class constructor SomeComponent cannot be invoked without 'new'
这是因为在使用了“transform-class-properties”插件转义后,类的私有变量和静态变量定义方式发生了变化,导致类的调用方式不再是原始的方式,而是采用一种新的方式。这个新的方式不兼容低版本的浏览器,从而导致了错误的出现。
解决方案
为了解决这个问题,我们需要采用一些方法,以便在保证使用了“transform-class-properties”插件的情况下,也能够使其在低版本的浏览器中正常运行。
方法一:使用 babel-plugin-transform-runtime
babel-plugin-transform-runtime 可以帮助我们转义没有被编写在你自己的代码中的一个新的内置工具库,在类的调用上,这个工具会注入一个函数 _classCallCheck()
。这个函数会判断当前环境是否支持 ES6 类,如果支持则直接调用原始类,否则包装一个自定义的构造函数返回。使用这个插件的效果跟 Webpack 的 externals 一样,能够避免把整个 polyfill 都打包进去。
首先安装 babel-plugin-transform-runtime 插件:
npm install --save-dev babel-plugin-transform-runtime
然后在.babelrc
文件中添加以下代码:
-- -------------------- ---- ------- - ---------- ---------------------- ---------- - - ---------------------------------- - --------- - - -- ----------------------------------------- - -
其中 "@babel/plugin-proposal-class-properties"
是“transform-class-properties”插件。注意这里只要使用了 runtime,哪怕是没有在业务代码中使用 class,最终打包后也会有一些 legacy 代码(如果有需要可以通过 Webpack 将这部分代码抽离出去)。
方法二:使用 babel-polyfill
使用 babel-polyfill 可以将 ES6+ 代码转换成 ES5,同时还可以为当前环境添加一些缺失的特性,比如:Promise、Set、Map、Array.includes 等等。在这里,我们可以使用 babel-preset-env 来兼容打包后在低版本浏览器运行的代码。
首先安装 babel-polyfill:
npm install --save-dev babel-polyfill
在入口文件(一般是src/index.js
或src/main.js
)添加以下代码:
import 'babel-polyfill';
这个被导入的 polyfill 将包含整个 ES6+ 的特性,此时类的调用方式与不使用“transform-class-properties”插件时差不多,不再需要像上面的方法一般深度地探究其背后的原理。
总结
在使用 Babel 进行转义时,使用“transform-class-properties”插件会导致类的调用方式变化,从而在低版本浏览器中出现错误。为了避免这个问题,我们可以使用 babel-plugin-transform-runtime 或 babel-polyfill 解决,其中 babel-plugin-transform-runtime 是一种轻量级的方案,而 babel-polyfill 则是完整覆盖 ES6+ 特性的方案。不同的场景可以根据实际需求选择合适的方案。
示例代码
-- -------------------- ---- ------- -- -- -------------------------- ------- ----- ------------- - ------ ------------ - - ----- ---------------- -- ------------------ - ------------- ---------- - - ------ --- -- - ----------- - -- -- - --------------------- -- -------- - ----- - ---- - - ----------- ------ ---- ---------------------------------------- - - -- -- ------------------------------ ------- ------ --------------- ---- -------------------------------------------- ------ ------------ ---- ----------------------------------------- ------ -------------- ---- ------------------------------------------- --- ------------- - ------------- --------- -- - -------- -------------------- - ---------- - - ------ --- -- - --- ------ - ------------------------ ------------------ - -------- ------------- - --------------------- -- ------------- - -------- -------- - --- ---- - ---------------- ------ -------------------------- - -------- ---------------------------- -- ------ -- --------------------------- ----- - - ---- --------------- ------ - ----- ---------------- -- ----------- ------ ------------- ----- --------- ----- -- --- ------ -------------- ----- --- -------- - -------------- ------ - -------- -- ------- --
-- -------------------- ---- ------- -- -- -------------- ----- ------ ----------------- ----- ------------- - ------ ------------ - - ----- ---------------- -- ------------------ - ------------- ---------- - - ------ --- -- - ----------- - -- -- - --------------------- -- -------- - ----- - ---- - - ----------- ------ ---- ---------------------------------------- - - ------ ------- --------------
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/6642e894d3423812e40d82d9