百度地圖官方文檔的使用指導是這樣說的:在頁面中引入<script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=你獲取的秘鑰"></script>,然后就可以使用腳本中引入的BMap對象去調用各種API了
我遇到的問題
我在入口文件——index.html引入上面那段腳本后,而在另外一個JS文件里訪問BMap時候報錯了,提示BMap is not defined,
我解決問題的思路
1.到github上找一找有沒有開源的SDK(如果有的話通過npm install 安裝好依賴包,然后我就可以通過require或import 的方式引入BMap了)——失敗,根本就沒有開源的依賴包
2.通過require或import直接引入http地址,如require('http..../*上面那個script的地址*/')——失敗,require或import只能直接引入本地的資源文件,不能直接引入外部的
3.把BMap綁到Window對象上實現跨文件訪問——成功!(能實現但不推薦,為了實現而實現)
4.通過webpack輸出對象中的externals屬性實現require的訪問——成功!(推薦做法)
重現問題:
我的目錄:

我的index.html長這樣:
/*剩下的部分自己想象*/ <script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=我的的秘鑰"></script> /*剩下的部分自己想象*/
我的test/index.js長這樣:
import React from 'react' class Test extends React.Component{ componentDidMount () { var map = new BMap.Map("allmap") } render () { return (<div id='allmap'></div>) } }
然而渲染Test時卻報了錯:

一個事實擺在眼前:
以模塊化的方式構建應用時,在JS模塊中是不能夠直接訪問入口文件中的變量的,那么我們又該如何在某個JS文件中導入入口HTML文件中的變量呢?
或者說在這個例子中,我們如何能夠在test/index.js中取得HTML中引入的腳本中的BMap對象呢?

可能許多同學會想:就用export/import嘛!但直接在HTML文件中export變量顯然並不是什么合理的做法
解決方法
方法一:用window對象保存BMap變量,實現HTML文件和JS文件間的變量傳遞
在引入百度地圖的腳本下再加入這一段腳本:
<script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=eBGR7XzaPhB5UbYARl3E7ksdkMdgrCw7"></script> <script> window.BMap = BMap </script>
沒錯,就是把BMap對象保存到全局可訪問的window對象中
當要使用BMap的時候這樣用:
var BMap = window.BMap//取出window中的BMap對象 var map = new BMap.Map("allmap"); // 創建Map實例
//通過map調用API
例子如下:
import React from 'react' import ReactDOM from 'react-dom' class BaiduMap extends React.Component { componentDidMount () { var BMap = window.BMap var map = new BMap.Map("allmap"); // 創建Map實例 map.centerAndZoom(new BMap.Point(116.404, 39.915), 11); // 初始化地圖,設 置中心點坐標和地圖級別 map.addControl(new BMap.MapTypeControl()); //添加地圖類型控件 map.setCurrentCity("北京"); // 設置地圖顯示的城市 此項是必須設置的 map.enableScrollWheelZoom(true); //開啟鼠標滾輪縮放 } render () { return ( <div> <div id='allmap' style={{ width:'100vw', height:'100vh' }} /> </div> ) } } ReactDOM.render( <BaiduMap />, document.getElementById('root') )
demo:

方法二.通過webpack的externals加載BMap使它可以通過require或import引入
在webpack.config.js中
module.exports = { /*此處省略了entry,output,modules等配置*/ externals:{ 'BMap':'BMap' }, }
在使用到BMap的時候,這樣引入:
import BMap from 'BMap' var map = new BMap.Map("allmap"); // 創建Map實例 //通過map調用API
例子:
import React from 'react' import ReactDOM from 'react-dom' import BMap from 'BMap' class BaiduMap extends React.Component { componentDidMount () { var map = new BMap.Map("allmap"); // 創建Map實例 map.centerAndZoom(new BMap.Point(116.404, 39.915), 11); // 初始化地圖,設置中心點坐標和地圖級別 map.addControl(new BMap.MapTypeControl()); //添加地圖類型控件 map.setCurrentCity("北京"); // 設置地圖顯示的城市 此項是必須設置的 map.enableScrollWheelZoom(true); //開啟鼠標滾輪縮放 } render () { return ( <div> <div id='allmap' style={{ width:'100vw', height:'100vh' }} /> </div> ) } } ReactDOM.render( <BaiduMap />, document.getElementById('root') )
webpack的externals的具體作用
我概括為兩點:
1.寫入externals中的依賴是不會被打包進最后的bundle里面的
2.雖然它不會被打包,但在程序運行的時候你仍然能通過模塊化的方式去引入這些依賴,如commonJS,AMD,ES6的import等
(原文:Prevent bundling of certain imported packages and instead retrieve these external dependencies at runtime.)
demo同上:

百度地圖新手(尤其是用react的)容易犯的錯誤及其解決方式
1.忘記寫< div id= 'allmap' >< /div >這個元素
忘記寫<div id= 'allmap'></div>這個元素(id不一定要是allmap,只要和 new BMap.map(參數)里的字符串參數相同便可)
然后控制台就會報:TypeError: Cannot read property 'gc' of undefined的錯誤

解決方法:記得寫<div id= 'XXXX'></div>
2.在渲染前就執行了 var map = new BMap.Map("allmap")
你寫入了<div id= 'allmap'></div>,但還是報了TypeError: Cannot read property 'gc' of undefined的錯誤,你可能犯了一個原生JS碼農不太可能會犯但是react碼農可能會犯的錯誤:你在<div id= 'allmap'></div>渲染前就執行了 var map = new BMap.Map("allmap");這一行代碼
例如:
render () { var map = new BMap.Map("allmap"); // 創建Map實例 return (<div id='allmap' />) ) }
解決辦法:在渲染<div id='allmap' />后才執行var map = new BMap.Map("allmap"); 例如將初始化map的代碼放入組件類的
componentDidMount ()鈎子函數中(這個函數將在組件被初次渲染完畢后調用)
例如:
class BaiduMap extends React.Component { componentDidMount () { var map = new BMap.Map("allmap"); // 創建Map實例 } render () { return <div id='allmap' /> ) }
3.你寫入了<div id= 'allmap'></div>,控制台也沒有報錯,但是你就是看!不!到!地!圖!
這多半是你沒有給<div id= 'allmap'></div>加上寬高,百度地圖的API是不會給你的div加寬高的,所以height默認是0就是0
解決方法:給目標地圖div加上寬高(嚴格地說是高,寬默認為width:auto)
render () { return <div id='allmap' style={{width:'100%',height:'100px'}} /> }
一封反饋給百度地圖的工作者們的信件
為此,我寫了一封反饋的信件給百度地圖的工作者們,目前在等待回應中(希望能有所回應吧)

以下為詳細內容:
親愛的百度地圖開發者您好,作為一名react框架開發者,我在入門百度地圖API時遇到困難——我不知道如何在模塊化JS中使用BMap的API(問題現已解決)。因為你們只提供了原生JS下的入門指導,而沒有任何關於模塊化JS編程下的指導內容。這對於一些框架新手來說確實有些難以下手
我遇到的問題是:在引入攜帶AK的script的前提下,在一個JS模塊文件(不是入口文件)中使用BMap報錯:"error! BMap is not defined!"
我的解決法是通過在Webpack輸出對象中的externals屬性中加入BMap:"BMap",然后通過在對后在對應的JS頁面中通過Window.BMap取得。
希望你們能夠提供更為詳細的操作指導,例如webpack下BMap的用法。這將讓你們的產品變得更好。
以上 —— 某個愛好javaScript的大二學生
