美文网首页
React项目实战五

React项目实战五

作者: 小王子__ | 来源:发表于2021-12-06 15:16 被阅读0次

地图找房模块

功能:

  • 展示当前定位城市
  • 展示该城市所有区的房源数据
  • 展示某区下所有镇的房源数据
  • 展示某镇下所有小区的房源数据
  • 展示某小区下的房源数据列表
    涉及到的功能点:地图标注、缩放登记、缩放事件等
1,封装顶部导航栏

1,在components中创建NavHeader组件封装导航栏可复用组件
2,使用NavHeader组件

export default function NavHeader ({children, history}) {
  // history是props.history
  // 默认情况下,只有路由 Route 直接渲染的组件才能获取到路由信息(比如:history.go()等),如果需要在其他组件中获取到路由信息可以通过 withRouter 高阶组件来获取。
  
  // 那么我们可以使用高阶组件处理
  // 1,从 react-router-dom 中导入 withRouter 高阶组件
  // 2,使用 withRouter 包裹 NavHeader 组件
  // 3,从 props 中解构出 history 对象
  // 4,调用 history.go() 实现返回上一页
  // 5,从 props 中解构出 onLeftClick 函数,实现自定义返回按钮的点击事件
  
  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) // 默认点击行为
    return (
      <NavBar
        mode="light"
        icon={<i className="iconfont icon-back"/>}
        onLeftClick={onLeftClick || defaultHandler}
        >
          {children}
      </NavBar>
    )
  }
  export default withRouter(NavHeader)
}

onLeftClick点击事件,可以在使用 NavHeader 组件自定义onLeftClick事件:

// Map组件
<NavHeader onLeftClick={() => {
  this.props.history.go(-1)
}}>
  地图找房
</NavHeader>
添加props校验:
  • 1,安装:yarn add prop-types
  • 2, 导入 PropTypes
import PropTypes from 'prop-types'
  • 3, 给 NavHeader 组件的 children 和 onLeftClick 属性添加 props 校验
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 的统称,用来解决 css 样式冲突、覆盖等问题
  • css in js的具体实现有50多种,比如:CSS Modules、styled-components等
  • 推荐使用: CSS Modules(React脚手架已集成,可直接使用)

CSS Modules:

  • CSS Modules通过对css类名重命名,保证每个类名的唯一性,从而避免样式冲突的问题
  • 换句话:所有类名都具有“局部作用域”,只在当前组件内部生效
  • 命名采用:BEM

BEM(Block块,Element元素,Modifier三部分组成)命名规范,比如: .list_item__active

  • 在React脚手架中演化为:文件名、类名、hash(随机)三部分,只需要指定类名即可
// 自动生成的类名,我们只需要提供 classname即可
[filename]_[classname]__[hash]

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

CSS Modules在项目中的使用:

1,创建名为[name].module.css的样式文件(React脚手架中的约定,与普通CSS作区分)

在CityList组件中创建的样式文件名:
index.module.css

2,组件中导入样式文件

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

3,通过 styles 对象访问对象中的样式名来设置样式

<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;
}
  • 对于组件库中已经有的全局样式(比如:.am-navnar-title),需要使用 :global() 来指定:
:global(.am-navnar-title){}
2, 根据定位展示当前城市
componentDidMount() {
  // 获取当前定位城市
  const {label, value} = JSON.parse(localStorage.getItem('current_city'))

  //创建地址解析器实例
  const map = new BMapGL.Map('container')
  const myGeo = new BMapGL.Geocoder();
  // 将地址解析结果显示在地图上,并调整地图视野
  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('您选择的地址没有解析到结果!');
      }
  }, label)
}
3,创建文本覆盖物

百度地图文本覆盖物文档

  • 1, 创建label实例对象
  • 2,调用 setStyle()方法设置样式
  • 3,在 map 对象上调用 addOverlay()方法,将文本覆盖物添加到地图中
const opts = {
  position : point,    // 指定文本标注所在的地理位置
  offset   : new BMap.Size(30, -30)    //设置文本偏移量
}

const label = new BMapGL.Label("文本信息", opts);  // 创建文本标注对象

// 设置样式
label.setStyle({
   color : "red",
   fontSize : "12px",
   height : "20px",
   lineHeight : "20px",
   fontFamily:"微软雅黑"
 });
 
 // 将创建好的文本标注添加为地图的覆盖物
 map.addOverlay(label); 
绘制房源覆盖物
  • 1,调用Label的setContent()方法,传入HTML结构,修改HTML内容的样式
// 设置房源覆盖物
Label.setContent(`
  <div class="${styles.bubble}">
    <p class="${styles.name}">哈哈哈</p>
    <p>99套</p>
  </div>
`)
  • 2,调用setStyle()修改覆盖物样式
Label.setStyle()
  • 3, 给文本覆盖物添加单击事件
Label.addEventListener("click", () => {
  console.log('被点击了')
})
地图找房
  • 1,获取房源数据,渲染覆盖物
  • 2,单击覆盖物后:1,放大地图 2,获取数据,渲染下一级覆盖物

1,渲染多有区的房源覆盖物

  • 1,获取房源数据
  • 2,遍历数据,创建覆盖物,给每个覆盖物添加唯一标识
  • 3,给覆盖物添加单击事件
  • 4,在单击事件中,获取到当前单击项的唯一标识
  • 5,放大地图(级别为13),调用clearOverlays()方法清除当前覆盖物
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)


      // 获取房源数据
      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,    // 指定文本标注所在的地理位置
          offset: new BMapGL.Size(-35, -35)    //设置文本偏移量
        }
        const Label = new BMapGL.Label("", opts)

        // 给 label对象添加一个唯一标识
        Label.id = value

        // 设置房源覆盖物
        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", () => {
          // 放大地图,以当前点击的覆盖物为中心放大地图
          map.centerAndZoom(areaPoint, 13);

          // 清除当前覆盖物信息
          map.clearOverlays()
        })
      });


  }else{
      alert('您选择的地址没有解析到结果!');
  }
}, label)

相关文章

网友评论

      本文标题:React项目实战五

      本文链接:https://www.haomeiwen.com/subject/xmagxrtx.html