![](/img/trans.png)
[英]How to expose 'require' to the browser when using browserify from within gulp?
[英]How to expose callback function for Google Maps when using Browserify?
我正在使用Gulp和Browserify捆綁我的JavaScripts。 我需要公開一個應該在Google Maps API加載后執行的回調函數。
如何在不使用window.initMap
類的情況下完成這項工作? 這個問題是我需要在initMap中觸發大量其他方法,因此除了使用window.functionName
和污染全局命名空間之外,還必須有更好的方法。
另一方面,是否可以排除callback
參數並執行類似的操作?
$.getScript('https://maps.googleapis.com/maps/api/js').done(function() {
initMap();
});
任何幫助將不勝感激。 我花了更多的時間來承認讓它發揮作用。
gulpfile.js:
gulp.task('browserify', ['eslint'], function() {
return browserify('/src/js/main.js')
.bundle()
.pipe(source('main.js'))
.pipe(buffer())
.pipe(gulp.dest('/dist/js'))
.pipe(reload({ stream: true }));
});
main.js:
require('jquery');
require('./map');
map.js:
var map = (function() {
'use strict';
var mapElement = $('#map');
function googleMapsAPI() {
$.getScript('https://maps.googleapis.com/maps/api/js?callback=initMap');
}
function initMap() {
var theMap = new google.maps.Map(mapElement);
// functions...
}
function init() {
googleMapsAPI();
}
});
map.init();
不,不包括callback
參數也不行。
谷歌地圖API庫調用要在頁面上加載的一堆其他腳本,然后,當它們全部被加載時,在窗口對象上callback
參數。
只需在window
對象上聲明它:
var MyApp = {
init: function() {
//all your stuff
}
}
window.initMap = function() {
window.initMap = null; //set this to null this so that it can't get called anymore....if you want
MyApp.init();
};
然后只需在頁面上包含腳本標記:
<script src="https://maps.googleapis.com/maps/api/js?callback=initMap"></script>
如果要加載腳本,然后在加載腳本時執行某些操作,則可以在注入script
時設置屬性async
和onload
。 通過將所有代碼包裝到IIFE中,我們將保留在IIFE內定義的所有對象的私有 ,從而避免填充全局命名空間window
。 請參閱以下示例:
// IIFE (Immediately-Invoked Function Expression)
// Keeps all private
!function() {
/**
* Injects the script asynchronously.
*
* @param {String} url: the URL from where the script will be loaded
* @param {Function} callback: function executed after the script is loaded
*/
function inject(url, callback) {
var tag = 'script',
script = document.createElement(tag),
first = document.getElementsByTagName(tag)[0];
script.defer = script.async = 1; // true
script.type = 'text/javascript';
script.src = url;
script.onload = callback;
first.parentNode.insertBefore(script, first);
}
/**
* Injects and initializes the google maps api script.
*/
function injectMapsApi() {
var key = 'your-api-key';
var query = '?key=' + key;
var url = 'https://maps.googleapis.com/maps/api/js' + query;
inject(url, initMapsApi);
}
/**
* Callback that initializes the google maps api script.
*/
function initMapsApi() {
var maps = window.google.maps;
// ... code initializations
console.log(maps);
}
injectMapsApi();
}(); // end IIFE
您需要注冊並聲明API密鑰才能使用Google Maps API。 更多信息:
老實說,我認為這是一個更好的解決方案,只需定義一個全局initMap
函數,以便在利用Google Maps異步初始化的同時保持簡單。 這可能聽起來像是黑客攻擊,但您可以為該功能定義一個隨機名稱,然后在Google Maps SDK調用它后將其從全局范圍中刪除。 此機制類似於JSONP中使用的機制。
var functionName = getRandomName();
window[functionName] = function() {
window[functionName] = undefined;
// call to your initialization functions
};
在這個答案中,您可以看出防止污染全球范圍的方法是使谷歌地圖腳本同步加載,這可能會損害用戶體驗,特別是在智能手機上。
我對谷歌采取的這種方法也存在疑問。 我自己並不喜歡它。
我最近處理這個問題的方法是創建全局函數,其中包括觸發事件來觸發我的實際應用程序javascript。 這樣我的應用程序JS就可以處理地圖API處理了,它是我主要對象之外的一個小型全局函數調用。
function initMap(){
$(document).ready(function(){
$(window).on('GoogleMapsLoaded', myObj.init());
$(window).trigger('GoogleMapsLoaded');
});
};
我只是在腳本url中包含callback=initMap
。
更新:另一種選擇是將回調作為函數包含在對象中。 例如:你的對象可能是這樣的
var app = app || {};
(function($){
$(function(){
$.extend(app, {
initMap:function(yourMainWrapDiv){
//Do whatever you need to do after the map has loaded
},
mapLoadFunction(){
//Map API has loaded, run the init for my whole object
this.initMap($('#mainWrapper'))
},
mainInit: function(){
///do all your JS that can or needs
// to be done before the map API loads
this.maybeSetSomeBindings();
},
maybeSetSomeBindings: function(){
//do things
}
});
//On document ready trigger your mainInit
//To do other things while maps API loads
app.mainInit()
});
})(jQuery);
然后,您可以使用回調跳轉到一個全局對象中,並運行您只需要為地圖處理運行的內容。 您的API網址可以使用callback=app.initMap
這也可以保持清潔
更新2:另一個選項(我經過最低限度測試)將不使用Google API網址中的callback
參數,並將其與您需要的任何其他圖書館鏈接相關聯。 (地方,搜索等)。 https://maps.googleapis.com/maps/api/js?key=YOUR-KEY-HERE&libraries=places
例如。
然后在你的對象init函數中設置一個計時器,看看google
對象是否可用! 也許是這樣的:
var app = app || {}; (function($){ $(function(){ $.extend(app, { init:function(){ var self = this; var timer = setInterval(function(){ if ($('.ex').length){ //but really check for google object console.log('things exist google, elements, etc..'); self.next(); clearInterval(timer); } }); }, next:function(){ console.log('google object exists') } }); app.init() }); })(jQuery);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div class='ex'>as an example for something to trigger a flag (true/false) to clear the interval</div>
在任何情況下,你試圖訪問全局對象,在這種情況下app
,作為URL中的回調你將設置callback=app.yourFunctionToCall
NOT callback=app.funtionToCall()
你script
標簽也應該有async
和defer
屬性歸因於它促進進一步的html解析(你的應用程序的js應該直接在地圖腳本之后)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.