我在以下情况下遇到了这个问题:我想在为本地 index.html 文件编写的脚本中使用 react 和 react-dom api。我可以在index.html 的<head> 中放置一个<script src="react-cdn-url"></script> 标记,但我更愿意在我的本地系统上安装这些api。所以我wget react-cdn-url 看看我是否可以导入它。我在控制台上遇到了一些错误,所以我查看了我现在拥有的 react.js 文件并看到以下几行:
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global.React = factory());
}(this, (function () { 'use strict';
...
})));
一旦我破译了这个,我应该能够让我的 react api “可导入”。所以让我们一点一点地剥离它。第一个构造:
(function (global,factory){}(this,(function() {...})));
一开始有点混乱,所以首先看一下表达式:(function (params){}(args)); 这样做的目的是创建一个未命名的函数,它接受参数params,然后立即使用参数arg 调用它。将此与;function (params){}(args); 进行对比。这不是有效的 javascript,如果您在节点中尝试它会破坏解析器,如果您在 Firefox 控制台中执行此操作,则会收到错误:SyntaxError: function statement requires a name。原因是这是一个不完整的句法结构。 Javascript 语法允许您编写没有绑定名称的函数定义,但这仅在 表达式 中有意义。将函数定义括在括号中会导致对其进行评估。把这一切放在一起,我们有一个未命名的函数在参数this 和(function(){})(另一个未命名的函数)上被调用。 this 将是本地上下文,未命名函数对应于“顶级”匿名函数中的 factory 参数。考虑以下三行:
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global.React = factory());
这些检查是否正在从节点导入此模块,如果是,则导出factory 函数的结果。如果它是由 require.js 导入的,它会“定义”factory 函数,如果两者都不是,那么 factory 的结果在全局对象中被命名为“React”。最后一种情况适用于通过<script> 标签“导入”库时。
但是,如果您尝试 es6 import 它,这些情况都不会真正适用。为了使import 按需要工作,我们只需导出工厂函数,然后在导入脚本中调用它。为什么不直接调用工厂函数并将其分配给导出的名称?因为您需要将此工厂的结果传递给 react-dom 的工厂。一般来说,沿着这条路继续存在许多问题,最终解决某种依赖管理器会更好,但现在我们继续玩。
let ReactFactory;
export default ReactFactory = function () { 'use strict';
...
}
我对 react-dom 文件做同样的事情,改变这些行:
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('react')) :
typeof define === 'function' && define.amd ? define(['react'], factory) :
(global.ReactDOM = factory(global.React));
}(this, (function (React) { 'use strict';
...
})));
进入:
let ReactDOMFactory;
export default ReactDOMFactory = function (React) { 'use strict';
...
}
注意这次工厂函数有参数React。我看到下面几行:
if (!React) {
{
throw Error("ReactDOM was loaded before React. Make sure you load the React package before loading ReactDOM.");
}
}
从中我得到提示,我需要从我的第一个工厂创建我的React 对象并将其传递给ReactDOMFactory。总而言之,我在我的script.js 文件中加入了以下几行:
import ReactFactory from '/path-to-modified/react.js';
import ReactDOMFactory from '/path-to-modified/react-dom.js';
let React = ReactFactory();
let ReactDOM = ReactDOMFactory(React);
当然,path-to-modified 是修改后的 api 文件的路径,瞧!现在它工作得很好。