React+AntdUi实现《好客租房系统》条件找房界面04

一、条件找房界面分为4个部分,搜索部分、条件检索部分、房屋列表和底部。搜索部分和底部用之前封装好的组件即可,条件检索部分如图所示,将所有的条件检索封装到父组件Filter,而四个部分封装到各个组件之中

React+AntdUi实现《好客租房系统》条件找房界面04

 

 

React+AntdUi实现《好客租房系统》条件找房界面04

 

 

 1.渲染Filter组件,onFilter传递获取的数据,Filter组件中包含了FilterMore、FilterPicker、FilterTitle。FilterTitle 标题菜单组件。FilterPicker 前三个菜单对应的内容组件。FilterMore 最后一个菜单对应的内容组件

 

FilterTilte
根据标题菜单数据,渲染标题列表,标题可以被点击,点击时高亮
有筛选条件选中时标题高亮状态,提升至父组件Filter中,由父组件提供高亮状态,子组件通过props接受状态来实现高亮
原则:单一数据源,也就是说,状态只应该有一个组件提供并且提供操作状态的方法,其他组件直接使用组件中状态和操作状态的方法即可  

 

  • // 条件筛选栏标题数组:
    const titleList = [
      { title: '区域', type: 'area' },
      { title: '方式', type: 'mode' },
      { title: '租金', type: 'price' },
      { title: '筛选', type: 'more' }
    ]
    
    export default function FilterTitle(props) {
      const { titleSelectedStatus, onTitleClick } = props;
      return (
        <Flex align="center" className={styles.root}>
          {
            titleList.map((item) => <Flex.Item onClick={() => onTitleClick(item.type)} key={item.type}>
              {/* 根据选中的类名高亮: selected */}
              <span className={[styles.dropdown, titleSelectedStatus[item.type] ? styles.selected : ''].join(' ')}>
                <span>{item.title}</span>
                <i className="iconfont icon-arrow" />
              </span>
            </Flex.Item>)
          }
  • 更新titleSelectStatus,调用父组件的方法onTitleClick,将status传给父组件
      // 传递给子组件控制状态的方法
      onTitleClick = (type) => {
        this.setState({
          titleSelectedStatus: { ...titleSelectedStatus, [type]: true },
          openType: type
        })  

 

FilterPicker
点击前三个标题展示该组件,点击取消的时候隐藏
使用PickerView组件来实现页面效果,获取到PickerView组件中,选中的筛选条件值
点击确定按钮,隐藏该组件,将获取到的筛选条件值传递给父组件,展示或隐藏对话框的状态:由父组件提供,通过props传递给子组件
筛选条件数据:由父组件提供(因为所有筛选条件是通过一个接口来获取的),通过props传递给子组件
  •   // 设置当前选中状态
      state = {
        value: this.props.value
      }
    
      componentDidMount() {
        console.log('重新初始化!')
      }
    
      handlerChange = (value) => {
        this.setState({
          value
        })
      }
      render() {
        const { onCancel, onOk, data, cols } = this.props;
        const { value } = this.state;
        return (
          <>
            {/* 选择器组件: */}
            <PickerView value={value} onChange={this.handlerChange} data={data} cols={cols} />
    
            {/* 底部按钮 */}
            <FilterFooter onCancel={onCancel} onOk={() => { onOk(value) }} />
          </>
        )
    
  •   // 给Picker组件提供数据
      renderFilterPicker = () => {
        if (this.isShow()) {
          const { openType } = this.state;
          const { area, subway, rentType, price } = this.filterData;
          let data, cols = 1;
          switch (openType) {
            case 'area':
              data = [area, subway];
              cols = 3
              break;
            case 'mode':
              data = rentType;
              cols = 1
              break;
            default:
              data = price;
              cols = 1
          }
          console.log('n-sel:', this.selectedValues[openType])
          return <FilterPicker key={openType} data={data} value={this.selectedValues[openType]} cols={cols} onCancel={this.onCancel} onOk={this.onOk} />
    
        }
      }
FilterMore
能够渲染FilterMore组件
能够实现 清除按钮和确定按钮 的逻辑
能够实现 FilterMore的默认选中
父组件封装renderFilterMore方法,渲染FilterMore组件从filtersData中,获取数据(roomType,oriented,floor,characteristic),通过props传递给FilterMore组件
  •  // 父组件中渲染和处理FilterMore组件
      renderFilterMore = () => {
        const {
          openType
        } = this.state;
        if (openType === 'more') {
          console.log(this.filterData);
          const { roomType, oriented, floor, characteristic } = this.filterData;
          const data = { roomType, oriented, floor, characteristic }
          console.log('n-sel:', this.selectedValues[openType]);
          return <FilterMore
            data={data}
            value={this.selectedValues[openType]}
            onOk={this.onOk}
            onCancel={this.onCancel}
          />
        }
        return null
      }
  • // 设置选中值状态
      state = {
        selected: this.props.value
      }
    
      // 获取选中数据
      handlerSel = (val) => {
        const { selected } = this.state;
        const newSelected = [...selected]
        // 没有该值,新增(高亮显示)
        let index = newSelected.indexOf(val);
        if (index < 0) {
          newSelected.push(val)
        } else {
          //有,删除(取消高亮)
          newSelected.splice(index, 1)
        }
        console.log('选中:', newSelected);
        this.setState({
          selected: newSelected
        })
      }
    
      // 渲染标签
      renderFilters(data) {
        // 高亮类名: styles.tagActive
        // return (
        //   <span className={[styles.tag, styles.tagActive].join(' ')}>东北</span>
        // )
        const { selected } = this.state;
        return data.map((item) => <span
          onClick={() => this.handlerSel(item.value)}
          key={item.value}
          className={[styles.tag, selected.includes(item.value) ? styles.tagActive : ''].join(' ')}>
          {item.label}
       

 

2.获取房屋列表,封装筛选条件对象,根据筛选对象获取到房屋列表数据,将数据返回到条件找房界面,在条件找房界面使用HouseItem组件渲染房屋列表数据在页面中

React+AntdUi实现《好客租房系统》条件找房界面04

 

 

 

 

 // 处理后台需要的筛选条件数据,组装起来
  handlerFilters = (selectedValues) => {
    // 筛选条件数据
    const { area, mode, price, more } = selectedValues;
    // 组装数据
    const filters = {};
    // area | subway
    let areaKey = area[0], aval;
    if (area.length === 2) {
      aval = area[1]
    } else {
      if (area[2] !== 'null') {
        aval = area[2]
      } else {
        aval = area[1]
      }
    }
    filters[areaKey] = aval;
    // mode
    filters.rentType = mode[0]
    // price
    filters.price = price[0]
    // more
    filters.more = more.join(',')
    console.log('filters:', filters);
    return filters
  }
  •  加载传输的数据,传入HouseItem组件进行渲染
  •   // 加载房屋列表数据
      getHouseList = async () => {
        // 加载提示
        // 第二个参数为0,不自动关闭
        // Toast.loading('加载中...', 0)
        let res = await getHouseByFilters(this.cityId, this.filters, 1, 20);
        console.log(res);
        // 调用hide关闭
        // Toast.hide();
        const { list, count } = res.data;
        if (count !== 0) {
          Toast.success(`获取到${count}条房源信息`, 2)
        }
        this.setState({
          list,
          count
        })
      }
    
      // 渲染列表项
      renderHouseItem = ({
        key, // Unique key within array of rows
        index, // Index of row within collection
        isScrolling, // The List is currently being scrolled
        isVisible, // This row is visible within the List (eg it is not an overscanned row)
        style, // Style object to be applied to row (to position it)
      }) => {
        const { list } = this.state
        const item = list[index]
        // 处理暂时没有加载到数据情况
        if (!item) {
          return (
            <div style={style} key={key}>
              <p className={styles.loading}></p>
            </div>
          )
        };
        // console.log(this.props.history)
        // 处理图片地址
        item.src = BASE_URL + item.houseImg;
        // console.log(item);
        return <HouseItem {...item} key={key} onClick={() => { this.props.history.push({ pathname: `/detail/${item.houseCode}` }, { id: item.houseCode }) }} style={style} />
      }
  • HouseItem组件
  • function HouseItem({ src, title, desc, tags, price, onClick, style }) {
      return (
        <div className={styles.house} onClick={onClick} style={style}>
          <div className={styles.imgWrap}>
            <img className={styles.img} src={src} alt="" />
          </div>
          <div className={styles.content}>
            <h3 className={styles.title}>{title}</h3>
            <div className={styles.desc}>{desc}</div>
            <div>
              {/* ['近地铁', '随时看房'] */}
              {tags.map((tag, index) => {
                const tagClass = 'tag' + (index + 1)
                return (
                  <span
                    className={[styles.tag, styles[tagClass]].join(' ')}
                    key={tag}
                  >
                    {tag}
                  </span>
                )
              })}
            </div>
            <div className={styles.price}>
              <span className={styles.priceNum}>{price}</span> 元/月
            </div>
          </div>
        </div>
      )
    }  
  • 在将加载出的列表使用List组件渲染数据,InfiniteLoader滚动房屋列表时候,动态加载更多房屋数据

  •  // 渲染列表
      renderHouseList = () => {
        const { count } = this.state;
        // 没有数据渲染NoHouse组件
        return count === 0 ? this.renderNoHouse() : (
          <InfiniteLoader
            isRowLoaded={this.isRowLoaded}
            loadMoreRows={this.loadMoreRows}
            // 远程数据总条数
            rowCount={this.state.count}
          >
            {({ onRowsRendered, registerChild }) => (
              <AutoSizer>
                {({ height, width }) => (
                  <List
                    className={styles.houseList}
                    height={height}
                    rowCount={this.state.count}
                    rowHeight={130}
                    rowRenderer={this.renderHouseItem}
                    onRowsRendered={onRowsRendered}
                    ref={registerChild}
                    width={width}
                  />
                )}
              </AutoSizer>
            )}
          </InfiniteLoader>
        )
      }

 

上一篇:SAP CRM organization Model(组织架构模型)自动决定的逻辑分析


下一篇:2021-07-31