我使用的是browserify-shim,我想使用一个通用的jQuery插件。我已经多次查看Browserify-shim文档,我只是不知道发生了什么和/或它如何知道在哪里放置插件、附加到jQuery对象等。下面是我的package.json文件的样子:
"browser": {
"jquery": "./src/js/vendor/jquery.js",
"caret": "./src/js/vendor/jquery.caret.js"
},
"browserify-shim": {
"caret": {
"depends": ["jquery:$"]
}
}根据浏览器文档中给出的示例,我不想指定导出,因为这个插件(如果不是所有的jQuery插件)都会自己附加到jQuery对象上。除非我上面做错了什么,否则我不明白为什么它不能工作(我收到一个错误,告诉我函数是未定义的)。见下文:
$('#contenteditable').caret(5); // Uncaught TypeError: undefined is not a function所以我的问题是,如何用浏览器化和浏览器化-shim来配置一个通用的jQuery插件(它自己连接到jQuery对象)?
发布于 2014-08-30 18:59:17
在重新审视了这个问题并尝试了更多的事情之后,我终于把我的头集中在了褐化-shim正在做的事情以及如何使用它。对我来说,在我最终理解如何使用browserify-shim之前,我必须掌握一个关键的原则。对于两个不同的用例,基本上有两种方法可以使用浏览器化- shimming :公开和shimming。
背景
假设您只想在标记中插入一个脚本标记(因为测试或性能方面的原因,比如缓存、CDN等)。通过在标记中包含一个脚本标记,浏览器将命中脚本,运行它,并且很可能在窗口对象上附加一个属性(在JS中也称为全局属性)。当然,这可以通过执行myGlobal或window.myGlobal来访问。但这两种语法都有问题。它不遵循CommonJS规范,这意味着如果一个模块开始支持CommonJS语法(require()),您就无法利用它。
解决方案
Browserify-shim允许您通过CommonJS require()语法指定希望“公开”的全局。请记住,您可以执行var whatever = global;或var whatever = window.global;,但不能执行var whatever = require('global'),并期望它为您提供正确的lib/模块。不要对变量的名称感到困惑。这可能是任意的。本质上是使全局变量成为局部变量。这听起来很愚蠢,但这是浏览器中JS的可悲状态。同样,希望库一旦支持CommonJS语法,就永远不会通过窗口对象上的全局附加。这意味着您必须使用require()语法并将其赋值给局部变量,然后在需要的地方使用它。
注意:我发现变量命名在browserify-shim /示例中有些混乱。记住,关键是您希望包含一个lib ,就好像是一个行为正常的CommonJS模块一样。因此,您最终要做的是告诉browserify,当您需要myGlobal require('myGlobal')时,您实际上只想获得窗口对象(即window.myGlobal )上的全局属性。
事实上,如果您对require函数的实际功能感到好奇,这是非常简单的。下面是引擎盖下面发生的事情:
var whatever = require('mygGlobal');变成..。
var whatever = window.mygGlobal;曝光
因此,在这种背景下,让我们看看如何在浏览器化-shim中公开一个模块/lib。基本上,你告诉布朗-希姆两件事。调用require()时希望用它访问的名称以及它应该在窗口对象上找到的全局名称。因此,这就是global:*语法的来源。让我们看一个例子。我希望在index.html中使用jquery作为脚本标记,这样我就可以获得更好的性能。下面是我在配置中需要做的事情(在package.json或外部配置JS文件中):
"browserify-shim": {
"jquery": "global:$"
}所以这是什么意思。我在其他地方包括了jQuery (记住,browserify-shim不知道我们把标记放在哪里,但它不需要知道),但是当我需要具有字符串参数"jquery“的模块时,我只想得到窗口对象上的$属性。以进一步说明。我也可以这样做:
"browserify-shim": {
"thingy": "global:$"
}在本例中,我必须将"thingy“作为参数传递给require函数,以便返回jQuery对象的实例(它只是从window.$获取jQuery ):
var $ = require('thingy');是的,再说一遍,变量名可以是任何东西。$与实际jQuery库使用的全局属性$没有什么特别之处。尽管使用相同的名称来避免混淆是有意义的。这将最终引用窗口对象上的$属性,如global:$值在package.json中的browserify-shim对象中所选择的那样。
闪鸣
好吧,那就包括曝光了。褐化的另一个主要特征那那是什么?Shimming与公开本质上是一样的,除了将lib或模块包含在HTML标记中(比如脚本标记)之外,您可以告诉browserify-shim本地抓取JS文件的位置。没有必要使用global:*语法。让我们回到我们的jQuery示例,但这一次假设我们不是从CDN加载jQuery,而是将它与所有的JS文件捆绑在一起。下面是配置的样子:
"browser": {
"jquery": "./src/js/vendor/jquery.js", // Path to the local JS file relative to package.json or an external shim JS file
},
"browserify-shim": {
"jquery": "$"
},此配置告诉browserify-shim从指定的本地路径加载jQuery,然后从window对象获取$属性,并在需要具有字符串参数的jQuery时将其返回给require函数"jquery“。同样,为了说明起见,您也可以将其重命名为任何其他内容。
"browser": {
"thingy": "./src/js/vendor/jquery.js", // Path to the local JS file relative to package.json or an external shim JS file
},
"browserify-shim": {
"thingy": "$"
},这可能需要以下方面:
var whatever = require('thingy');我建议使用exports属性和depends属性查看browserify-shim文档,以获得更多关于长手语法的信息,如果库依赖于另一个lib /模块,则可以告诉您browserify-shim。我在这里所解释的都适用于两者。我希望这能帮助其他人理解浏览器化-shim实际上在做什么,以及如何使用它。
匿名闪现
匿名shimming是浏览器化-shim的另一种选择,它允许您使用browserify的--standalone选项将lib(如jQuery )转换为UMD模块。
$ browserify ./src/js/vendor/jquery.js -s thingy > ../dist/jquery-UMD.js如果将其放入脚本标记中,则此模块将以thingy的形式将jQuery添加到窗口对象中。当然,它也可以是$或者你喜欢的任何东西。
然而,如果它是require编辑到您的浏览器化的应用程序包,var $ = require("./dist/jquery-UMD.js");,您可以在应用程序中使用jQuery,而无需将它添加到窗口对象中。
该方法不需要浏览器化-shim,并且利用jQuery的CommonJS感知,它查找一个module对象并将一个noGlobal标志传递到它的工厂,工厂告诉它不要将自己附加到该窗口对象。
发布于 2015-01-11 11:09:51
对于每一个正在寻找具体例子的人来说:
下面是连接到package.json /$对象的jQuery插件的jQuery和app.js文件的示例,例如:$('div').expose()。我不希望jQuery在需要时成为全局变量(window.jQuery),这就是为什么jQuery设置为'exports': null的原因。但是,由于插件需要一个全局jQuery对象,它可以将自己附加到该对象,因此必须在文件名:./jquery-2.1.3.js:jQuery之后的依赖项中指定它。此外,在使用插件时,您需要实际导出jQuery全局,即使您不想这样做,因为插件不能正常工作(至少这个插件是这样的)。
package.json
{
"name": "test",
"version": "0.1.0",
"description": "test",
"browserify-shim": {
"./jquery-2.1.3.js": { "exports": null },
"./jquery.expose.js": { "exports": "jQuery", "depends": [ "./jquery-2.1.3.js:jQuery" ] }
},
"browserify": {
"transform": [
"browserify-shim"
]
}
}app.js
// copy and delete any previously defined jQuery objects
if (window.jQuery) {
window.original_jQuery = window.jQuery;
delete window.jQuery;
if (typeof window.$.fn.jquery === 'string') {
window.original_$ = window.$;
delete window.$;
}
}
// exposes the jQuery global
require('./jquery.expose.js');
// copy it to another variable of my choosing and delete the global one
var my_jQuery = jQuery;
delete window.jQuery;
// re-setting the original jQuery object (if any)
if (window.original_jQuery) { window.jQuery = window.original_jQuery; delete window.original_jQuery; }
if (window.original_$) { window.$ = window.original_$; delete window.original_$; }
my_jQuery(document).ready(function() {
my_jQuery('button').click(function(){
my_jQuery(this).expose();
});
});在上面的例子中,我不希望我的代码设置任何全局,但为了使插件工作,我不得不暂时这样做。如果您只需要jQuery,就可以这样做,而不需要任何解决办法:var my_jQuery = require('./jquery-2.1.3.js')。如果您可以将jQuery公开为全局的,那么您可以修改上面的package.json示例,如下所示:
"browserify-shim": {
"./jquery-2.1.3.js": { "exports": "$" },
"./jquery.expose.js": { "exports": null, "depends": [ "./jquery-2.1.3.js" ] }希望这能帮助一些人,他们正在寻找具体的例子(就像我发现这个问题时一样)。
发布于 2016-07-17 14:09:13
为了完整起见,这里有一种方法可以利用jQuery的CommonJS感知来避免担心会污染window对象而不需要实际使用。
特性
window对象无污染配置
在./pacage.json中,添加一个browser节点来为资源位置创建别名。--这纯粹是为了方便起见,没有必要实际移除任何东西,因为模块和全局空间(脚本标记)之间没有通信。
{
"main": "app.cb.js",
"scripts": {
"build": "browserify ./app.cb.js > ./app.cb.bundle.js"
},
"browser": {
"jquery": "./node_modules/jquery/dist/jquery.js",
"expose": "./js/jquery.expose.js",
"app": "./app.cb.js"
},
"author": "cool.blue",
"license": "MIT",
"dependencies": {
"jquery": "^3.1.0"
},
"devDependencies": {
"browserify": "^13.0.1",
"browserify-shim": "^3.8.12"
}
}方法
module对象的存在,并返回一个实例,而不将它添加到window对象中。require jquery并将其添加到module.exports对象中(以及需要共享的任何其他上下文)。$,并在插件中使用jQuery。代码
app.cb.js
var $ = module.exports.jQuery = require("jquery");
require('expose');
$(document).ready(function() {
$('body').append(
$('<button name="button" >Click me</button>')
.css({"position": "relative",
"top": "100px", "left": "100px"})
.click(function() {
$(this).expose();
})
);
});在插件顶部
var jQuery = require("app").jQuery;在HTML中
<script type="text/javascript" src="app.cb.bundle.js"></script>背景
jQuery使用的模式是使用noGlobal标志调用它的工厂,如果它感觉到CommonJS环境。它不会向window对象添加一个实例,并将一如既往地返回一个实例。
默认情况下,CommonJS上下文是由浏览器创建的。下面是显示jQuery模块结构的捆绑包的简化摘录。为了清晰起见,我删除了处理window对象同构处理的代码。
3: [function(require, module, exports) {
( function( global, factory ) {
"use strict";
if ( typeof module === "object" && typeof module.exports === "object" ) {
module.exports = factory( global, true );
} else {
factory( global );
}
// Pass this if window is not defined yet
} )( window, function( window, noGlobal ) {
// ...
if ( !noGlobal ) {
window.jQuery = window.$ = jQuery;
}
return jQuery;
}) );
}, {}]我发现的最好的方法是在节点模块系统中工作,然后每次浏览器化之后它都能工作。
只需使用jsdom对window对象进行平移,以便代码是同构的。然后,专注于让它在节点中工作。然后,移除模块与全局空间之间的任何通信量,并最终将其浏览,它将只在浏览器中工作。
https://stackoverflow.com/questions/24835954
复制相似问题