【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的大二學生

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM