【react】當react框架趕上百度地圖

 
百度地圖官方文檔的使用指導是這樣說的:在頁面中引入<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的大二學生
相關文章
相關標籤/搜索