react好租客项目Day04-城市列表索引列相关功能&封装NavHeader&CSS IN JS
react好租客项目Day04-城市列表索引列相关功能&封装NavHeader&CSS IN JS
Ramsayi渲染城市列表
目标
- 完成城市索引高亮效果
- 完成点击索引跳转到对应位置
- 能够实现切换城市功能(除了北京,上海,广州,深圳,其他成均无房源信息,需要提示用户)
城市索引列表高亮
- 给 list 组件添加 onRowsRendered 配置项,用于获取当前列表渲染的行信息,在里面就会有相应信息
- 通过参数 startIndex 获取到 起始行对应的索引号
- 判断 startIndex 和 activeIndex 不同时候,更新状态 activeIndex 为 startIndex
1 | <List |
点击索引置顶该索引城市
给索引列表绑定点击事件
在点击事件中,通过 index 获取到当前项索引号
调用 List 组件的 scrollToRow 方法,让 List 组件滚动到指定行
- 在 constructor 中,调用 React.createRef() 创建 ref 对象
- 将创建好的 ref 对象,添加为 List 组件的 ref 属性
- 通过 ref 的 current 属性,获取到组件实例,再调用组件的 scrollToRow 方法
设置 List 组件的 scrollToAlignment 配置项值为 start,保证点击行出现在页面顶部
对于点击索引无法正确定位的问题,调用 List 组件的 measureAllRows 方法,提前计算高度来解决
1 | // 核心代码 |
切换城市
- 给城市列表项绑定事件
- 判断当前城市是否有房源数据
- 如果有房源数据,则保持当前城市数据到本地缓存中,并返回上一页
- 如果没有房源数据,则提示用户:改城市暂无房源数据,不执行任何操作
1 | const HOST_CITY = ['北京', '上海', '广州', '深圳'] |
好客租房移动 Web(上)-总结
- 项目准备:部署本地接口,脚手架初始化项目,antd-mobile,路由等
- 项目整体布局:分析两种页面布局,使用嵌套路由实现带 TabBar 页面布局等
- 首页模块:租房小组结构布局,数据获取,H5 地理定位和百度地图地理定位等
- 城市选择模块:数据结构处理,长列表性能优化,react-virtualized,索引列表等
好客租房移动 Web(中)-目标
- 能够在百度地图中展示当前定位城市
- 能够使用地图标注完成房源信息绘制
- 能够展示城市所有区的房源数据
- 能够封装找房页面的条件筛选栏组件
- 能够使用 react-spring 组件实现动画效果
- 能够完成房屋详情页面的数据展示
地图找房模块
目标
封装 NavHeader 组件
实现 NavHeader 组件中左侧按钮功能
能够解决 NavHeader 组件中获取不到路由信息的问题
对 NavHeader 的 props 进行校验
功能分析
- 展示当前定位城市
- 展示该城市所有区的房源数据
- 展示某区下所有镇的房源数据
- 展示某镇下所有的校区的房源数据
- 展示某小区下的房源数据列表
顶部导航栏
结构实现
- 封装 NavHeader 组件实现城市选择,地图找房页面的复用
- 在 components 目录中创建组件 NavHeader/index.js
- 在该组件中封装 antd-mobile 组件库中的 NavBar 组件
- 在地图找房页面使用封装好的 NavHeader 组件实现顶部导航栏功能
- 使用 NavHeader 组件,替换城市选择页面的 NavBar 组件
1 | import React from 'react'; |
样式调整
- 在 components 下的 NavHeader 文件夹中创建 index.scss 文件
- 把之前城市列表写过的样式,复制到这个文件下
功能处理
注意:默认情况下,只有路由 Route 直接渲染的组件才能够获取到路由信息,如果需要在其他组件中获取到路由信息可以通过 withRouter 高阶组件来获取
从 react-router-dom 中导入 withRouter 高阶组件
使用 withRouter 高阶组件包装 NavHeader 组件
- 目的:包装后,就可以在组建中获取到当前路由信息
从 props 中就能获取 history 对象
调用 history 对象的 go() 方法就能实现返回上一页功能了
由于头部的左侧按钮不一定是返回上一个页面的功能,所以我们需要把左侧点击逻辑处理需要通过父组件传递进来,如果说外界传递了,那么我们就直接使用外界的行为,如果没有传递,那么就用默认的行为
1 | import React from 'react'; |
添加 props 校验
往往我们封装好了的组件可能会提供给别人去使用,然而别人在使用我们组件的时候不清楚需要传递怎样的 props,所以我们可以通过添加 props 校验,来提示使用者,应该怎样正确的传递 props
- 安装 yarn add prop-types
- 导入 PropTypes
- 给 NavHeader 组件的 children 和 onLeftClick 添加 props 校验
1 | import PropTypes from 'prop-types' |
城市选择页面使用 NavHeader 组件
- 在 CityList.js 文件中,引入 NavHeader 组件
- 把之前 NavBar 组件去掉,使用我们封装好的 NavHeader 组件就好
组件之间样式覆盖问题
目标
- 能够利用 CSS Modules 解决组件之间样式覆盖的问题
概念
- 问题:CityList 组件的样式,会影响 Map 组件的样式
- 原因:在配置路由的时候,CityList 组件与 Map 组件都会被导入到路由中,那么只要组件被导入,那么相关的样式也会被导入进来,如果两个组件的样式名称相同,那么就会影响另外一个组件的样式
- 小结:默认情况下,只要导入了组件,不管组件有没有显示在页面中,组件的样式就会生效
- 解决方式
- 写不同的类名
- CSS IN JS
CSS IN JS
CSS IN JS 是使用 JavaScript 编写 CSS 的统称,用来解决 CSS 样式冲突,覆盖等问题;
CSS IN JS 的具体实现有 50 多种,比如:CSS Modules、styled-components 等
推荐使用:CSS Modules(React 脚手架已经集成进来了,可以直接使用)
CSS Modules
概念
- CSS Modules 通过对 CSS 类名重命名,保证每一个类名的唯一性,从而避免样式冲突问题
- 实现方式:webpack 的 css-loader 插件
- 命名采用:BEM(Block 块、Element 元素、Modifier 三部分组成)命名规范。比如: .list_item_active
- 在 React 脚手架中演化成:文件名、类名、hash(随机)三部分,只需要指定类名即可
使用
- 创建名为[name].module.css 的样式文件(React 脚手架中的约定,与普通 CSS 区分开)
- 组件中导入样式文件(注意语法)
- 通过 styles 对象访问对象中的样式名来设置样式
使用 CSS Modules 修改 NavHeader 样式
- 在 NavHeader 目录中创建 index.module.css 的样式文件
- 在样式文件中修改当前组件的样式
- 对于组件库中已经有的全局样式,需要使用:global() 来指定,例如:我们在修改 NavBar 里面文字颜色的时候,用到了一个类名叫: am-navbar-title 这个类名不是我们设置的,而是组件库中定义的,所以对于这一类,我们需要这样去设置:
或者:
示例 demo
1 | .navbar { |
在 Map 组件中修改头部样式
1 | .map { |
页面结构
1 | <div className={styles.map}> |