我们使用YUI3加载器来管理加载javascript和css文件。作为每个页面引导js代码的一部分,我们有如下内容:
YUI({
...
groups: {
...
myGroup: {
modules: {
"my-module": {
...
path: "MyModule.js",
requires: [ "yui-base" ]
},
}
...
}
}
}).use("my-module", function (Y) {
Y.MyModule.doStuff();
});MyModule.js有如下内容:
YUI.add('my-module', function (Y) {
Y.MyModule = function () {
...
_validator: Y.Lang.isString
};
}, '3.4.0', {
requires: [ "yui-base" ]
});YUI还声称,这里可以将加载程序与非YUI 3“模块”一起使用,因为它们在配置中具有指定的依赖关系。它们给出了yui2组的以下模块配置示例:
yui2: {
combine: true,
base: 'http://yui.yahooapis.com/2.8.0r4/build/',
comboBase: 'http://yui.yahooapis.com/combo?',
root: '2.8.0r4/build/',
modules: { // one or more external modules that can be loaded along side of YUI
yui2_yde: {
path: "yahoo-dom-event/yahoo-dom-event.js"
},
yui2_anim: {
path: "animation/animation.js",
requires: ['yui2_yde']
}
}
}这表明,只有在Yahoo多姆事件. is加载和运行后,YUI才能加载和运行YUI 2的animation.js。
我不明白的是,如果这对非YUI模块有效,为什么我必须用YUI.add和冗余的需求列表包装自己的模块(因为在配置中也指定了requires )?
我尝试删除add包装器(我用(function (Y) { /* module content */ })(YUI);替换它),但是这会导致页面加载时出现js错误: Y.Lang是未定义的。因此,在定义Y.Lang的基本yui脚本之前,似乎不知何故,如果不调用add(),脚本就会被执行。但是,如果是这样的话,那么对于非YUI模块(不调用YUI.add()),这难道不是一个问题吗?
发布于 2013-08-07 20:28:24
区分使用YUI3特性(沙箱Y.Lang等)的自定义模块和完全外部代码是很重要的。
在第一种情况下,YUI.add()包装始终是必要的,因为沙箱Y变量在模块回调(YUI.add()的第二个参数)之外不可用。不幸的是,在手工编写的模块中重复模块配置是必要的,因为Y.Loader中的约束(其中发生了组合加载魔术)。使用YUI的构建工具的模块具有自动添加包装器和元数据的功能。
使用完全的外部代码,您只需要提供fullpath配置属性,而YUI将做正确的事情。在内部,YUI知道给定的<script>请求何时完成,并将该成功与配置的模块名关联起来。
为了简化操作,我将使用YUI.applyConfig演示配置位。使用它,您可以创建任意数量的YUI沙箱(通过YUI().use(...))和混合配置,而不是到处重复它。
YUI.applyConfig({
"modules": {
"leaflet": {
"fullpath": "http://cdn.leafletjs.com/leaflet-0.6.4/leaflet.js"
},
"my-leaflet-thing": {
"path": "path/to/my-leaflet-thing.js",
"requires": [
"base-build",
"node-base",
"leaflet"
]
}
}
});我的传单.my看起来是这样的:
YUI.add("my-leaflet-thing", function (Y) {
// a safe reference to the global "L" provided by leaflet.js
var L = Y.config.global.L;
Y.MyLeafletThing = Y.Base.create("myLeaflet", Y.Base, {
initializer: function () {
var id = this.get('node').get('id');
var map = L.map(id);
// etc
}
}, {
ATTRS: {
node: {
getter: Y.one
}
}
});
// third argument is a version number,
// but it doesn't affect anything right now
}, "1.0.0", {
"requires": [
"base-build",
"node-base",
"leaflet"
]
});考虑到这个设置,因为这需要一个非异步库,所以您可以安全地这样做:
YUI().use("my-leaflet-thing", function (Y) {
var instance = new Y.MyLeafletThing({
"node": "#foo"
});
});注意:如果外部文件自己动态加载(例如异步Google),YUI只知道初始请求成功,而不是加载的整个文件链。要解决这个问题,您需要在fullpath配置中使用querystring回调参数,该参数与需要它的模块中的一些全局公开回调相关联。
在这些情况下,最好做一个内部Y.use() (注意沙箱变量),以便更好地封装所需的全局。
配置:
YUI.applyConfig({
"modules": {
"google-maps-api": {
"fullpath": "http://maps.googleapis.com/maps/api/js" +
"?v=3&sensor=false&callback=initGMapsAPI"
},
"my-google-map-thing": {
"path": "path/to/my-google-map-thing.js",
"requires": [
"base-build",
"node-base"
]
}
}
});我的-谷歌-地图-东西my:
YUI.add("my-google-map-thing", function (Y) {
// publish a custom event that will be fired from the global callback
Y.publish('gmaps:ready', {
emitFacade: true,
fireOnce: true
});
// private sentinel to determine if Y.use() has been called
var isUsed = false;
// expose global function that matches "callback" parameter value
Y.config.global.initGMapsAPI = function () {
// Y.config.global.google is now available
Y.fire('gmaps:ready');
};
Y.MyGoogleMapThing = Y.Base.create("myGoogleMap", Y.Base, {
initializer: function () {
Y.on('gmaps:ready', this.render, this);
if (!isUsed) {
isUsed = true;
Y.use("google-maps-api");
}
},
render: function () {
// safe reference to global "google"
var google = Y.config.global.google;
var id = this.get('node').get('id');
var map = new google.maps.Map(id, {
// ...
});
// etc
}
}, {
ATTRS: {
node: {
getter: Y.one
}
}
});
}, "1.0.0", {
"requires": [
"base-build",
"node-base"
]
});总之:只有在编写依赖于YUI.add()沙箱资源的模块时,才需要使用YUI3。加载外部代码,只要是同步的,就像使用fullpath配置属性一样简单。异步外部加载有点麻烦,但仍然有可能。
https://stackoverflow.com/questions/18109852
复制相似问题