RequireJS 创建对象副本的方法
RequireJS way of creating a copy of object
我们的项目非常庞大,单页企业应用程序,基于 RequireJS 和 Backbone.js,对于一些复杂的 UI 我们使用 jqWidgets。
特别是这些 jqWidgets 是导致我们出现问题的原因。
有许多应用程序功能使用较旧的 jqWidgets 3.3 实现,对于所有新功能,我们希望使用 3.6,但是将旧功能移植到 3.6 非常棘手,并且会花费我们目前没有的时间。
为了节省时间,我们想做的是让 3.3 和 3.6 一起工作而不产生任何问题,然后在我们可以的时候再做移植部分。
到目前为止我尝试过的:
requirejs.config({
paths: {
"jquery": "vendor/jquery",
"jqx": "vendor/jqwidgets/3.3",
"jqx3.6": "vendor/jqwidgets/3.6",
... other libs...
},
shim: {
... other shims ...
// jqWidgets3.3
"jqx/jqxcore": {
deps: ["jquery"]
},
"jqx/<<some_plugin>>": {
deps: ["jqx/jqxcore"],
exports: "$.fn.<<some_plugin>>"
},
// jqWidgets3.6
"jqx3.6/jqxcore": {
deps: ["jquery"]
},
"jqx3.6/<<some_plugin>>": {
deps: ["jqx3.6/jqxcore"],
exports: "$.fn.<<some_plugin>>"
},
}
});
旧功能中的用法:
require(["jquery", "jqx/<<some_plugin>>"], function($) {
$('<<some_selector>>').<<some_plugin>>(...options...);
});
新功能中的用法:
require(["jquery", "jqx3.6/<<some_plugin>>"], function($) {
$('<<some_selector>>').<<some_plugin>>(...options...);
});
因为这两个插件都应用于相同的 jQuery 对象,所以用不同的 names/paths 引用它们可以工作,但会产生很多错误。示例:如果您在应用程序中使用的第一个功能是使用 jqWidgets 3.3 加载的,那么下一个使用 3.6 的功能可能会损坏,反之亦然。仅当您在每次使用功能后刷新页面时它才有效——这有点毫无意义,因为它是单页应用程序。
所以我的问题是:是否可以让 jqWidgets 3.3 和 3.6 同时工作,然后每个都依赖于它们自己的 jQuery 对象,这样就不会发生这种冲突?
// 附录一:
我认为潜在的解决方案在于对这个问题的评论:RequireJS - jQuery plugins with multiple jQuery versions
我会仔细查看,post 如果找到解决方案,我会在此处提供解决方案。
如果 jqWidgets 不支持开箱即用,我会试试这个:
- 加载jQuery
- 加载jqxWidget 3.3
- 再次加载 jQuery ,但在其无冲突模式下,并将其分配给
</code> 例如(我不确定 RequireJS 是否可以做到这一点,但您可以复制 jQuery.js 文件并将其重命名为不同的名称以便第二次加载它)</li>
<li>将第一个 jQuery 设置为 $1 (<code>window. = $
)
- 设置第二个jQuery为$(
window.$ =
)
- 加载jqxWidget 3.6
现在每个 jqxWidget 都应该有自己的、独立的 jQuery。
显然 jQuery 加载两次并不理想,但除了在您的应用程序上使用更多内存外,这应该不是问题。
你可以使用 requirejs 的 'map' 功能,
Map 允许您根据使用依赖项的模块将相同的依赖项映射到不同的文件。
所以你像这样配置你的构建文件:
requirejs.config({
paths: {
"jquery": "vendor/jquery",
"jqueryForjqx3.6": "toNoConflictJQueryModule",
"jqx": "vendor/jqwidgets/3.3",
"jqx3.6": "vendor/jqwidgets/3.6",
... other libs...
},
map:{
'*':{
.....
},
'jqx':{
'jquery' : 'jquery'
},
'jqx3.6':{
// map jquery to no conlict jquery
'jquery' : 'jqueryForjqx3.6'
},
'jqueryForjqx3.6':{
'jquery' : 'jquery'
}
},
shim: {
... other shims ...
// jqWidgets3.3
"jqx/jqxcore": {
deps: ["jquery"]
},
"jqx/<<some_plugin>>": {
deps: ["jqx/jqxcore"],
exports: "$.fn.<<some_plugin>>"
},
// jqWidgets3.6
"jqx3.6/jqxcore": {
deps: ["jquery"]
},
"jqx3.6/<<some_plugin>>": {
deps: ["jqx3.6/jqxcore"],
exports: "$.fn.<<some_plugin>>"
},
}
});
此配置根据使用它的模块将 jquery 依赖项映射到不同的文件。
无冲突版本的内容可以是这样的:
define(['jquery'], function($){
return $.noConflict();
});
你可以使用http://requirejs.org/docs/jquery.html#noconflictmap了解如何使用jquery no-conflict和requirejs
我们的项目非常庞大,单页企业应用程序,基于 RequireJS 和 Backbone.js,对于一些复杂的 UI 我们使用 jqWidgets。
特别是这些 jqWidgets 是导致我们出现问题的原因。 有许多应用程序功能使用较旧的 jqWidgets 3.3 实现,对于所有新功能,我们希望使用 3.6,但是将旧功能移植到 3.6 非常棘手,并且会花费我们目前没有的时间。
为了节省时间,我们想做的是让 3.3 和 3.6 一起工作而不产生任何问题,然后在我们可以的时候再做移植部分。
到目前为止我尝试过的:
requirejs.config({
paths: {
"jquery": "vendor/jquery",
"jqx": "vendor/jqwidgets/3.3",
"jqx3.6": "vendor/jqwidgets/3.6",
... other libs...
},
shim: {
... other shims ...
// jqWidgets3.3
"jqx/jqxcore": {
deps: ["jquery"]
},
"jqx/<<some_plugin>>": {
deps: ["jqx/jqxcore"],
exports: "$.fn.<<some_plugin>>"
},
// jqWidgets3.6
"jqx3.6/jqxcore": {
deps: ["jquery"]
},
"jqx3.6/<<some_plugin>>": {
deps: ["jqx3.6/jqxcore"],
exports: "$.fn.<<some_plugin>>"
},
}
});
旧功能中的用法:
require(["jquery", "jqx/<<some_plugin>>"], function($) {
$('<<some_selector>>').<<some_plugin>>(...options...);
});
新功能中的用法:
require(["jquery", "jqx3.6/<<some_plugin>>"], function($) {
$('<<some_selector>>').<<some_plugin>>(...options...);
});
因为这两个插件都应用于相同的 jQuery 对象,所以用不同的 names/paths 引用它们可以工作,但会产生很多错误。示例:如果您在应用程序中使用的第一个功能是使用 jqWidgets 3.3 加载的,那么下一个使用 3.6 的功能可能会损坏,反之亦然。仅当您在每次使用功能后刷新页面时它才有效——这有点毫无意义,因为它是单页应用程序。
所以我的问题是:是否可以让 jqWidgets 3.3 和 3.6 同时工作,然后每个都依赖于它们自己的 jQuery 对象,这样就不会发生这种冲突?
// 附录一: 我认为潜在的解决方案在于对这个问题的评论:RequireJS - jQuery plugins with multiple jQuery versions 我会仔细查看,post 如果找到解决方案,我会在此处提供解决方案。
如果 jqWidgets 不支持开箱即用,我会试试这个:
- 加载jQuery
- 加载jqxWidget 3.3
- 再次加载 jQuery ,但在其无冲突模式下,并将其分配给
</code> 例如(我不确定 RequireJS 是否可以做到这一点,但您可以复制 jQuery.js 文件并将其重命名为不同的名称以便第二次加载它)</li> <li>将第一个 jQuery 设置为 $1 (<code>window. = $
) - 设置第二个jQuery为$(
window.$ =
) - 加载jqxWidget 3.6
现在每个 jqxWidget 都应该有自己的、独立的 jQuery。 显然 jQuery 加载两次并不理想,但除了在您的应用程序上使用更多内存外,这应该不是问题。
你可以使用 requirejs 的 'map' 功能, Map 允许您根据使用依赖项的模块将相同的依赖项映射到不同的文件。 所以你像这样配置你的构建文件:
requirejs.config({
paths: {
"jquery": "vendor/jquery",
"jqueryForjqx3.6": "toNoConflictJQueryModule",
"jqx": "vendor/jqwidgets/3.3",
"jqx3.6": "vendor/jqwidgets/3.6",
... other libs...
},
map:{
'*':{
.....
},
'jqx':{
'jquery' : 'jquery'
},
'jqx3.6':{
// map jquery to no conlict jquery
'jquery' : 'jqueryForjqx3.6'
},
'jqueryForjqx3.6':{
'jquery' : 'jquery'
}
},
shim: {
... other shims ...
// jqWidgets3.3
"jqx/jqxcore": {
deps: ["jquery"]
},
"jqx/<<some_plugin>>": {
deps: ["jqx/jqxcore"],
exports: "$.fn.<<some_plugin>>"
},
// jqWidgets3.6
"jqx3.6/jqxcore": {
deps: ["jquery"]
},
"jqx3.6/<<some_plugin>>": {
deps: ["jqx3.6/jqxcore"],
exports: "$.fn.<<some_plugin>>"
},
}
});
此配置根据使用它的模块将 jquery 依赖项映射到不同的文件。
无冲突版本的内容可以是这样的:
define(['jquery'], function($){
return $.noConflict();
});
你可以使用http://requirejs.org/docs/jquery.html#noconflictmap了解如何使用jquery no-conflict和requirejs