React項(xiàng)目實(shí)戰(zhàn)五

地圖找房模塊

功能:

  • 展示當(dāng)前定位城市
  • 展示該城市所有區(qū)的房源數(shù)據(jù)
  • 展示某區(qū)下所有鎮(zhèn)的房源數(shù)據(jù)
  • 展示某鎮(zhèn)下所有小區(qū)的房源數(shù)據(jù)
  • 展示某小區(qū)下的房源數(shù)據(jù)列表
    涉及到的功能點(diǎn):地圖標(biāo)注姑躲、縮放登記晋被、縮放事件等
1搬味,封裝頂部導(dǎo)航欄

1燕偶,在components中創(chuàng)建NavHeader組件封裝導(dǎo)航欄可復(fù)用組件
2燥透,使用NavHeader組件

export default function NavHeader ({children, history}) {
  // history是props.history
  // 默認(rèn)情況下栗弟,只有路由 Route 直接渲染的組件才能獲取到路由信息(比如:history.go()等)悍手,如果需要在其他組件中獲取到路由信息可以通過 withRouter 高階組件來獲取渴逻。
  
  // 那么我們可以使用高階組件處理
  // 1妙啃,從 react-router-dom 中導(dǎo)入 withRouter 高階組件
  // 2档泽,使用 withRouter 包裹 NavHeader 組件
  // 3,從 props 中解構(gòu)出 history 對象
  // 4揖赴,調(diào)用 history.go() 實(shí)現(xiàn)返回上一頁
  // 5馆匿,從 props 中解構(gòu)出 onLeftClick 函數(shù),實(shí)現(xiàn)自定義返回按鈕的點(diǎn)擊事件
  
  import { withRouter } from 'react-router-dom'
  
  export default function NavHeader ({children, history, onLeftClick}) {
    const defaultHandler = () => history.go(-1)
    return (
      <NavBar
        mode="light"
        icon={<i className="iconfont icon-back"/>}
        onLeftClick={onLeftClick || defaultHandler}
        >
          {children}
      </NavBar>
    )
  }
  以上代碼修改為:
  function NavHeader ({children, history, onLeftClick}) {
    const defaultHandler = () => history.go(-1) // 默認(rèn)點(diǎn)擊行為
    return (
      <NavBar
        mode="light"
        icon={<i className="iconfont icon-back"/>}
        onLeftClick={onLeftClick || defaultHandler}
        >
          {children}
      </NavBar>
    )
  }
  export default withRouter(NavHeader)
}

onLeftClick點(diǎn)擊事件燥滑,可以在使用 NavHeader 組件自定義onLeftClick事件:

// Map組件
<NavHeader onLeftClick={() => {
  this.props.history.go(-1)
}}>
  地圖找房
</NavHeader>
添加props校驗(yàn):
  • 1渐北,安裝:yarn add prop-types
  • 2, 導(dǎo)入 PropTypes
import PropTypes from 'prop-types'
  • 3, 給 NavHeader 組件的 children 和 onLeftClick 屬性添加 props 校驗(yàn)
function NavHeader ({children, history, onLeftClick}) {
  const defaultHandler = () => history.go(-1)
  return (
    <NavBar
      mode="light"
      icon={<i className="iconfont icon-back"/>}
      onLeftClick={onLeftClick || defaultHandler}
      >
        {children}
    </NavBar>
  )
}


NavHeader.propTypes = {
  children: PropTypes.string.isRequired,
  onLeftClick: PropTypes.func
}
export default withRouter(NavHeader)
組件間樣式覆蓋問題

css IN JS

  • css IN JS:是使用 js 編寫 css 的統(tǒng)稱,用來解決 css 樣式?jīng)_突铭拧、覆蓋等問題
  • css in js的具體實(shí)現(xiàn)有50多種赃蛛,比如:CSS Modules、styled-components等
  • 推薦使用: CSS Modules(React腳手架已集成羽历,可直接使用)

CSS Modules:

  • CSS Modules通過對css類名重命名焊虏,保證每個(gè)類名的唯一性,從而避免樣式?jīng)_突的問題
  • 換句話:所有類名都具有“局部作用域”秕磷,只在當(dāng)前組件內(nèi)部生效
  • 命名采用:BEM

BEM(Block塊诵闭,Element元素,Modifier三部分組成)命名規(guī)范澎嚣,比如: .list_item__active

  • 在React腳手架中演化為:文件名疏尿、類名、hash(隨機(jī))三部分易桃,只需要指定類名即可
// 自動(dòng)生成的類名褥琐,我們只需要提供 classname即可
[filename]_[classname]__[hash]

// 類名
.error{}
// 生成的類名:
.Button_error__ax7yz

CSS Modules在項(xiàng)目中的使用:

1,創(chuàng)建名為[name].module.css的樣式文件(React腳手架中的約定晤郑,與普通CSS作區(qū)分)

在CityList組件中創(chuàng)建的樣式文件名:
index.module.css

2,組件中導(dǎo)入樣式文件

import styles from './index.module.css'

3敌呈,通過 styles 對象訪問對象中的樣式名來設(shè)置樣式

<div className={styles.test}></div>

示例:

image

CityList index.js:

import styles from './index.module.css'
<div className={styles.test}>測試樣式</div>

index.module.css:

.test {
  color: red;
  font-size: 40px;
}
  • 對于組件庫中已經(jīng)有的全局樣式(比如:.am-navnar-title)贸宏,需要使用 :global() 來指定:
:global(.am-navnar-title){}
2, 根據(jù)定位展示當(dāng)前城市
  • 1,獲取當(dāng)前定位城市
  • 2磕洪,獲取地址解析器解析當(dāng)前城市坐標(biāo)
  • 3吭练,調(diào)用 centerAndZoom()方法在地圖中展示當(dāng)前城市,并設(shè)置縮放級別為11
  • 4析显,在地圖中添加比例尺和平移縮放控件
componentDidMount() {
  // 獲取當(dāng)前定位城市
  const {label, value} = JSON.parse(localStorage.getItem('current_city'))

  //創(chuàng)建地址解析器實(shí)例
  const map = new BMapGL.Map('container')
  const myGeo = new BMapGL.Geocoder();
  // 將地址解析結(jié)果顯示在地圖上鲫咽,并調(diào)整地圖視野
  myGeo.getPoint(label, (point) => {
      if(point){
          map.centerAndZoom(point, 11);
          map.addOverlay(new BMapGL.Marker(point, {title: label}))
          
          // 添加比例尺和平移縮放控件
          // 使用Map.addControl()方法向地圖添加控件
          map.addControl(new BMapGL.ScaleControl)
          map.addControl(new BMapGL.ZoomControl)
      }else{
          alert('您選擇的地址沒有解析到結(jié)果!');
      }
  }, label)
}
3谷异,創(chuàng)建文本覆蓋物

百度地圖文本覆蓋物文檔

  • 1, 創(chuàng)建label實(shí)例對象
  • 2分尸,調(diào)用 setStyle()方法設(shè)置樣式
  • 3,在 map 對象上調(diào)用 addOverlay()方法歹嘹,將文本覆蓋物添加到地圖中
const opts = {
  position : point,    // 指定文本標(biāo)注所在的地理位置
  offset   : new BMap.Size(30, -30)    //設(shè)置文本偏移量
}

const label = new BMapGL.Label("文本信息", opts);  // 創(chuàng)建文本標(biāo)注對象

// 設(shè)置樣式
label.setStyle({
   color : "red",
   fontSize : "12px",
   height : "20px",
   lineHeight : "20px",
   fontFamily:"微軟雅黑"
 });
 
 // 將創(chuàng)建好的文本標(biāo)注添加為地圖的覆蓋物
 map.addOverlay(label); 
繪制房源覆蓋物
  • 1箩绍,調(diào)用Label的setContent()方法,傳入HTML結(jié)構(gòu)荞下,修改HTML內(nèi)容的樣式
// 設(shè)置房源覆蓋物
Label.setContent(`
  <div class="${styles.bubble}">
    <p class="${styles.name}">哈哈哈</p>
    <p>99套</p>
  </div>
`)
  • 2伶选,調(diào)用setStyle()修改覆蓋物樣式
Label.setStyle()
  • 3, 給文本覆蓋物添加單擊事件
Label.addEventListener("click", () => {
  console.log('被點(diǎn)擊了')
})
地圖找房
  • 1,獲取房源數(shù)據(jù)尖昏,渲染覆蓋物
  • 2,單擊覆蓋物后:1构资,放大地圖 2抽诉,獲取數(shù)據(jù),渲染下一級覆蓋物

1吐绵,渲染多有區(qū)的房源覆蓋物

  • 1迹淌,獲取房源數(shù)據(jù)
  • 2,遍歷數(shù)據(jù)己单,創(chuàng)建覆蓋物唉窃,給每個(gè)覆蓋物添加唯一標(biāo)識
  • 3,給覆蓋物添加單擊事件
  • 4纹笼,在單擊事件中纹份,獲取到當(dāng)前單擊項(xiàng)的唯一標(biāo)識
  • 5,放大地圖(級別為13)廷痘,調(diào)用clearOverlays()方法清除當(dāng)前覆蓋物
myGeo.getPoint(label, async (point) => {
  if(point){
      map.centerAndZoom(point, 11);
      map.addOverlay(new BMapGL.Marker(point, {title: label}))

      map.addControl(new BMapGL.ScaleControl)
      map.addControl(new BMapGL.ZoomControl)


      // 獲取房源數(shù)據(jù)
      const res = await axios.get(`http://localhost:8080/area/map?id=${value}`)
      res.data.body.forEach(item => {
        const {coord: {latitude, longitude}, label: areaname, count, value} = item
        const areaPoint = new BMapGL.Point(longitude, latitude)
        const opts = {
          position: areaPoint,    // 指定文本標(biāo)注所在的地理位置
          offset: new BMapGL.Size(-35, -35)    //設(shè)置文本偏移量
        }
        const Label = new BMapGL.Label("", opts)

        // 給 label對象添加一個(gè)唯一標(biāo)識
        Label.id = value

        // 設(shè)置房源覆蓋物
        Label.setContent(`
          <div class="${styles.bubble}">
            <p class="${styles.name}">${areaname}</p>
            <p>${count}套</p>
          </div>
        `)
        Label.setStyle(labelStyle);
        map.addOverlay(Label);

        // 添加單擊事件
        Label.addEventListener("click", () => {
          // 放大地圖蔓涧,以當(dāng)前點(diǎn)擊的覆蓋物為中心放大地圖
          map.centerAndZoom(areaPoint, 13);

          // 清除當(dāng)前覆蓋物信息
          map.clearOverlays()
        })
      });


  }else{
      alert('您選擇的地址沒有解析到結(jié)果!');
  }
}, label)
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末笋额,一起剝皮案震驚了整個(gè)濱河市元暴,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌兄猩,老刑警劉巖茉盏,帶你破解...
    沈念sama閱讀 221,635評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件鉴未,死亡現(xiàn)場離奇詭異,居然都是意外死亡鸠姨,警方通過查閱死者的電腦和手機(jī)铜秆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來享怀,“玉大人羽峰,你說我怎么就攤上這事√泶桑” “怎么了梅屉?”我有些...
    開封第一講書人閱讀 168,083評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長鳞贷。 經(jīng)常有香客問我坯汤,道長,這世上最難降的妖魔是什么搀愧? 我笑而不...
    開封第一講書人閱讀 59,640評論 1 296
  • 正文 為了忘掉前任惰聂,我火速辦了婚禮,結(jié)果婚禮上咱筛,老公的妹妹穿的比我還像新娘搓幌。我一直安慰自己,他們只是感情好迅箩,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,640評論 6 397
  • 文/花漫 我一把揭開白布溉愁。 她就那樣靜靜地躺著,像睡著了一般饲趋。 火紅的嫁衣襯著肌膚如雪拐揭。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,262評論 1 308
  • 那天奕塑,我揣著相機(jī)與錄音堂污,去河邊找鬼。 笑死龄砰,一個(gè)胖子當(dāng)著我的面吹牛盟猖,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播寝贡,決...
    沈念sama閱讀 40,833評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼扒披,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了圃泡?” 一聲冷哼從身側(cè)響起碟案,我...
    開封第一講書人閱讀 39,736評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎颇蜡,沒想到半個(gè)月后价说,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體辆亏,經(jīng)...
    沈念sama閱讀 46,280評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,369評論 3 340
  • 正文 我和宋清朗相戀三年鳖目,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了扮叨。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,503評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡领迈,死狀恐怖彻磁,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情狸捅,我是刑警寧澤衷蜓,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站尘喝,受9級特大地震影響磁浇,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜朽褪,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,870評論 3 333
  • 文/蒙蒙 一置吓、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧缔赠,春花似錦衍锚、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至梁棠,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間斗埂,已是汗流浹背符糊。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留呛凶,地道東北人男娄。 一個(gè)月前我還...
    沈念sama閱讀 48,909評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像漾稀,于是被迫代替她去往敵國和親模闲。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,512評論 2 359

推薦閱讀更多精彩內(nèi)容