taro3.x: 查询组件封装

查询组件:

import React, { useState, useEffect } from 'react'
import Taro from '@tarojs/taro'
import classnames from 'classnames'
import { map, includes } from 'lodash'
import { View, Text, Input, RichText, ScrollView } from '@tarojs/components'

import api from '@services/api'
import app from '@services/request'
import { keywordcolorful } from '@utils/index'
import storage from '@utils/storage'
import useNavData from '@hooks/useNavData'
import NavBar from '@components/navbar/index'
import './index.scss'

export interface ISearchOption {
  type: string
  name: string
}

interface ISearchProps {
  searchTitle: string
  searchOption: any[]
  searchRemark?: string
  searchUrl: string
  onItemClick: (any, ISearchOption) => void
}

const Search = (props: ISearchProps) => {
  const isMultiply = props.searchOption.length > 1
  const INIT_OPTION = props.searchOption[0]
  const INIT_HISTORIES = storage.getItem('histories', `search_${INIT_OPTION.name}`) || []
  const { contentHeight } = useNavData()
  const [clear, setClear] = useState(false)
  const [hotList, setHotList] = useState([])
  const [matcheList, setMatcheList] = useState([])
  const [searchValue, setSearchValue] = useState("")
  const [searchHistories, setSearchHistories] = useState(INIT_HISTORIES)
  const [option, setOption] = useState<ISearchOption>(INIT_OPTION)
  const [showOption, setShowOption] = useState<boolean>(false)

  useEffect(() => {
    app.request({ url: api.getSearchHotList }, { isMock: true, loading: false })
      .then((result: any) => {
        setHotList(result || [])
      })
  }, [])

  Taro.setNavigationBarColor({
    frontColor: '#000000',
    backgroundColor: '#f7f7f7',
    animation: {
      duration: 400,
      timingFunc: 'easeIn'
    }
  })

  const handleItemClick = (item: any) => {
    let ids = map(searchHistories, 'id')
    if (!includes(ids, item.id)) {
      searchHistories.push(item)
    }
    storage.setItem('histories', searchHistories, `search_${option.name}`)
    props.onItemClick(item, option)
  }

  const handleInput = (event) => {
    let keyValue = event.currentTarget.value
    if (keyValue) {
      setClear(true)
    } else {
      setClear(false)
    }
    setSearchValue(keyValue)
    updateKeyList(keyValue)
  }

  const updateKeyList = (keyValue) => {
    app.request({
      url: props.searchUrl,
      data: { kw: keyValue }
    }, { isMock: true, loading: false })
      .then((result: any) => {
        setMatcheList(result || [])
      })
  }

  const clearSearchValue = () => {
    setClear(false)
    setSearchValue("")
  }

  const handleCancel = () => {
    Taro.navigateBack()
  }

  const handleClearClick = () => {
    storage.clear(`search_${option.name}`)
    setSearchHistories([])
  }

  const handleSwitchOption = (item: ISearchOption) => {
    if (item.type === option.type) {
      return
    }
    setOption(item)
    setShowOption(false)
    setSearchHistories(storage.getItem('histories', `search_${item.name}`) || [])
  }

  const renderSearchKeys = (title, className, keyList, allowClear = false) => {
    if (keyList && keyList.length > 0) {
      return (
        <View className={classnames("search-record", className)}>
          <View className="search-header clearfix">
            <Text className="title">{title}</Text>
            {allowClear && <Text className="iconfont iconclear1" onClick={handleClearClick}></Text>}
          </View>
          <View className="search-list clearfix">
            {keyList.map((item: any) => {
              return <Text
                key={item.id}
                className="item"
                onClick={() => handleItemClick(item)}
              >{item.name}
              </Text>
            })}
          </View>
        </View>
      )
    }
  }

  const renderSearOption = () => {
    return props.searchOption.map((item: ISearchOption, index: number) => (
      <View
        key={index}
        className={classnames('options-item', option.type === item.type && 'actived')}
        onClick={() => handleSwitchOption(item)}
      >{item.name}
      </View>
    ))
  }

  return (
    <View className="search">
      <NavBar title={props.searchTitle} back={true} backgroundColor="#f7f7f7" color="#000" />
      <View className="search-wrapper clearfix">
        <View className="search-content">

          <View className="search-label" onClick={() => setShowOption(!showOption)}>
            <Text className="search-label-text">{option.name}</Text>
            <Text className={classnames('iconfont', isMultiply ? 'iconarrow-down-bold' : 'iconsearch')}></Text>
          </View>
          <Input className="search-input" placeholder={props.searchRemark} onInput={handleInput} value={searchValue} autoFocus></Input>

          {clear && <Text className="iconfont iconclear" onClick={clearSearchValue}></Text>}

          {showOption &&
            <View className="search-options">
              <View className="triangle-up">
                <Text className="cover"></Text>
              </View>
              {renderSearOption()}
            </View>
          }
        </View>
        <Text className="search-cancel" onClick={handleCancel}>取消</Text>
      </View>
      <ScrollView scrollY style={{ maxHeight: contentHeight - 50 }}>
        {searchValue ?
          <View className="search-matches">
            {
              matcheList.map((item: any, index: number) => {
                return (
                  <View className="match-item" key={index} onClick={() => handleItemClick(item)}>
                    <RichText nodes={keywordcolorful(item.name, searchValue)} />
                    <View className="address">{item.address}</View>
                  </View>
                )
              })
            }
          </View> :
          <View className="search-category">
            {renderSearchKeys('搜索历史', 'search-history', searchHistories, true)}
            {renderSearchKeys('热门搜索', 'search-hot', hotList)}
          </View>
        }
      </ScrollView>
    </View>
  )
}

export default Search

使用:

import React from 'react'
import Taro from '@tarojs/taro'
import { View } from '@tarojs/components'

import api from '@services/api'
import Search, { ISearchOption } from '@components/search'
import './index.scss'

const HouseSearch = () => {

  const searchOption: ISearchOption[] = [
    { type: "newhouse", name: "新房" },
    { type: "esf", name: "二手房" }
  ]

  const handleItemClick = (item: any, option: ISearchOption) => {
    Taro.navigateTo({
      url: `/pages/${option.type}/index?id=${item.id}&name=${item.name}`
    })
  }

  return (
    <View className="house-search">
      <Search
        searchTitle="搜索"
        searchOption={searchOption}
        onItemClick={handleItemClick}
        searchRemark="请输入楼盘名称或地址"
        searchUrl={api.getSearchKeyList}
      ></Search>
    </View>
  )
}

export default HouseSearch

 

posted @ 2020-09-16 15:55  Nyan  阅读(368)  评论(0编辑  收藏  举报