use*_*100 5 javascript jquery requirejs knockout.js
我开发了一个JavaScript插件,可以包含在我们客户的网站上.我创建的插件依赖于一些外部库,它们被捆绑并作为一个大包传递给客户端:jQuery 1.8.2和KnockoutJS v3.0.0.
该插件在大多数站点上都可以正常运行,但如果主机站点使用RequireJS,则我的包无法加载,因为KnockoutJS会自动检测到RequireJS存在并尝试使用它.这是抛出的错误:
Mismatched anonymous define() module
Run Code Online (Sandbox Code Playgroud)
显然,我在RequireJS网站上找到了错误消息的"解释".不幸的是,我不明白如何避免它.在我的KnockoutJS库的本地副本中,我发现了违规行:
(function(factory) {
// Support three module loading scenarios
if (typeof require === 'function' && typeof exports === 'object' && typeof module === 'object') {
// [1] CommonJS/Node.js
var target = module['exports'] || exports; // module.exports is for Node.js
factory(target);
} else if (typeof define === 'function' && define['amd']) {
// [2] AMD anonymous module
define(['exports'], factory);
} else {
// [3] No module loader (plain <script> tag) - put directly in global namespace
factory(window['ko'] = {});
}
}
Run Code Online (Sandbox Code Playgroud)
如果我手动编辑这个文件,以便条件[2]永远不会执行,只有每次执行条件[3],那么一切正常.当然,我不想这样做,因为它需要我编辑一个外部库,我宁愿保持原始状态,所以我可以稍后升级它.
我觉得可能有办法让这项工作,我只是不明白RequireJS是如何工作的.显然,KnockoutJS正在尝试与RequireJS一起玩,但在我的情况下,它失败了.对我来说,在这种情况下,即使存在RequireJS,我也不需要KnockoutJS来使用它.
如何让这两个库并排工作?
编辑
我无法控制何时加载库以及主机站点已加载的所有其他库.事实上,大部分时间我的插件都会被包含在内,它将由没有网络开发经验的人使用像WordPress,Webs.com或Weebly这样糟糕的WYSIWYG平台,所以有时我的脚本标签可能会让它成为头顶元素,其他时候它可能包含在某个地方的body元素中.
另外,要清楚,我的库不使用RequireJS.碰巧我们的一个客户试图使用我的库DOES使用RequireJS,当我的库被包含时,KnockoutJS(与我的库捆绑,但尚未在主机站点上)引发异常,因为它认为它需要用RequireJS注册自己(或者至少是我对异常的推测).
虽然原则上我不反对加载我的代码依赖于需求的库,但事实是它会为我的用户创建一个缓慢,糟糕的体验,因为它将需要额外的请求/响应周期来加载它们.
好吧,最简单的事情可能是在 requirejs之前加载淘汰赛。ko 将不再检测 require 是否存在,并将使用选项 [3]。如果您不能这样做,另一个选择是将您的插件和 ko 文件添加到 require 层次结构中。
假设您的插件如下所示:
(function(ko){
//stuff
ko.applyBindings({});
})(ko)
Run Code Online (Sandbox Code Playgroud)
您需要将其更改为:
require([
"knockout-3.0.0.js" // this should be the url you use for knockout
], function(ko){
//stuff
ko.applyBindings({});
})
Run Code Online (Sandbox Code Playgroud)
并且不要将 knockout.js 文件作为单独的标签加载。Require 将处理加载。当然,服务器仍然必须能够传递“knockout-3.0.0.js”url。这就是 require 的工作原理。它加载您作为 require 的数组参数中的元素传递的任何 url,并将它们作为参数返回的内容传递给函数。
如果您需要将插件文件和 ko 文件缩小/捆绑到一个文件中,您可以使用 reuquirejs minifier/optimizer ( http://requirejs.org/docs/optimization.html )。它将导航依赖树并仅输出一个包含所有模块的 js 文件。这里有一个怪癖:你需要删除 .js 扩展名才能使压缩器工作,阅读更多有关它的文档,我只是提到它以减少一些麻烦。
此外,有关如何将 ko 与 require 一起使用的更多文档可以在这里找到:http://knockoutjs.com/documentation/amd-loading.html
编辑,操作编辑后:
好的,所以在这种情况下您应该创建一个单独的范围,您可以在其中执行您想要的操作。您需要将 ko 代码复制到文件中,但这样您至少会得到一个文件。
因此,首先创建一个范围:
(function(){
})()
Run Code Online (Sandbox Code Playgroud)
然后复制ko里面的代码:
(function(){
//ko code here, should be a single, minified line
})()
Run Code Online (Sandbox Code Playgroud)
然后你需要欺骗 ko 使用选项 3,所以这样做:
(function(){
var define = null; //so define will no longer be a function, don't forget the var
var require = null;
//ko code here, should be a single, minified line
})()
Run Code Online (Sandbox Code Playgroud)
或者,如果您不希望 ko 可用于整个页面,您可能还想在上面的步骤中重新分配窗口。
现在添加您的插件代码:
(function(){
var define = null; //so define will no longer be a function, don't forget the var
var require = null;
//ko code here, should be a single, minified line
//plugin code here;
})()
Run Code Online (Sandbox Code Playgroud)